[nautilus-actions] Create import/export assistants



commit 05f872662aebed4251a2cd599cac3fe3972edbd3
Author: Pierre Wieser <pwieser trychlos org>
Date:   Tue Jul 14 20:24:20 2009 +0200

    Create import/export assistants

 ChangeLog                                          |   52 ++
 src/common/na-action-profile.c                     |   54 ++-
 src/common/na-action-profile.h                     |   10 +
 src/common/na-action.c                             |   52 ++-
 src/common/na-action.h                             |    5 +-
 src/common/na-gconf-keys.h                         |    2 +-
 src/common/na-utils.c                              |   45 +-
 src/common/na-utils.h                              |    3 +
 src/nact/Makefile.am                               |   15 +-
 src/nact/base-application.c                        |   34 +-
 src/nact/base-application.h                        |    1 +
 src/nact/base-window.c                             |   93 ++-
 src/nact/nact-assist-export.c                      |  695 ++++++++++++++++
 src/nact/nact-assist-export.h                      |   71 ++
 src/nact/nact-assist-import.c                      |  523 ++++++++++++
 src/nact/nact-assist-import.h                      |   71 ++
 src/nact/nact-assistant.c                          |  394 +++++++++
 src/nact/nact-assistant.h                          |   81 ++
 .../{nact-gconf-schema.h => nact-gconf-keys.h}     |   63 +-
 src/nact/nact-gconf-reader.c                       |  872 ++++++++++++++++++++
 src/nact/nact-gconf-reader.h                       |   77 ++
 src/nact/nact-gconf-schema-writer.h                |   74 --
 src/nact/nact-gconf-schema.c                       |  144 ----
 ...t-gconf-schema-writer.c => nact-gconf-writer.c} |  168 +++--
 src/nact/nact-gconf-writer.h                       |   77 ++
 src/nact/nact-iactions-list.c                      |   17 +-
 src/nact/nact-iactions-list.h                      |    2 +-
 src/nact/nact-iprefs.c                             |    4 +-
 src/nact/nact-main-window.c                        |  200 +----
 src/nact/nact-window.c                             |   35 +-
 src/nact/nact-window.h                             |    4 +-
 src/nact/nautilus-actions-config.ui                |  283 ++++---
 32 files changed, 3542 insertions(+), 679 deletions(-)
---
diff --git a/ChangeLog b/ChangeLog
index 2f0a03f..684fd11 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,55 @@
+2009-07-14 Pierre Wieser <pwieser trychlos org>
+
+	Implement import assistant with new object hierarchy.
+
+	* src/common/na-action.c:
+	* src/common/na-action.h (na_action_get_profile):
+	Now returns a NAObject.
+
+	* src/common/na-action.c:
+	* src/common/na-action.h
+	(na_action_set_uuid, na_action_set_version,
+	na_action_add_profile): New functions.
+
+	* src/common/na-action-profile.c:
+	* src/common/na-action-profile.h
+	(na_action_profile_set_label, na_action_profile_set_isfile,
+	na_action_profile_set_isdir, na_action_profile_set_schemes):
+	New functions.
+
+	* src/common/na-action-profile.h:
+	Define ACTION_PROFILE_PREFIX as a way of identifying a profile.
+
+	* src/common/na-utils.c:
+	* src/common/na-utils.h (na_utils_dump_string_list,
+	na_utils_schema_to_gslist, na_utils_schema_to_boolean):
+	New functions.
+
+	* src/nact/nact-assistant.c:
+	* src/nact/nact-assistant.h:
+	* src/nact/nact-assist-export.c:
+	* src/nact/nact-assist-export.h:
+	* src/nact/nact-assist-import.c:
+	* src/nact/nact-gconf-keys.h:
+	* src/nact/nact-gconf-reader.c:
+	* src/nact/nact-gconf-reader.h:
+	* src/nact/nact-gconf-writer.c:
+	* src/nact/nact-gconf-writer.c: New files.
+
+	* src/nact/nact-gconf-schema.c:
+	* src/nact/nact-gconf-schema.h:
+	* src/nact/nact-gconf-schema-writer.c:
+	* src/nact/nact-gconf-schema-writer.h: Removed files.
+
+	* src/nact/Makefile.am: Updated accordingly.
+
+	* src/nact/base-application.c:
+	* src/nact/base-application.h
+	(base_application_search_for_widget): New function.
+
+	* src/nact/base-window.c:
+	Call gtk_main/gtk_main_quit when we are running an assistant.
+
 2009-07-08 Pierre Wieser <pwieser trychlos org>
 
 	* src/nact/nact-main-window.c:
diff --git a/src/common/na-action-profile.c b/src/common/na-action-profile.c
index 0a75ff5..a931a9d 100644
--- a/src/common/na-action-profile.c
+++ b/src/common/na-action-profile.c
@@ -256,8 +256,8 @@ instance_init( GTypeInstance *instance, gpointer klass )
 	self->private->dispose_has_run = FALSE;
 
 	/* initialize suitable default values
-	 * i18n: default label for the default profile
 	 */
+	/* i18n: default label for the default profile */
 	self->private->label = g_strdup( _( "Default profile" ));
 	self->private->path = g_strdup( "" );
 	self->private->parameters = g_strdup( "" );
@@ -855,6 +855,19 @@ validate_schemes( GSList* schemes2test, NautilusFileInfo* file )
 }
 
 /**
+ * Set the label for this profile.
+ *
+ * @profile: this NAActionProfile object.
+ *
+ * @label: label to be set.
+ */
+void
+na_action_profile_set_label( NAActionProfile *profile, const gchar *label )
+{
+	g_object_set( G_OBJECT( profile ), PROP_PROFILE_LABEL_STR, label, NULL );
+}
+
+/**
  * Set the path of the command for this profile.
  *
  * @profile: this NAActionProfile object.
@@ -921,6 +934,32 @@ na_action_profile_set_mimetypes( NAActionProfile *profile, GSList *mimetypes )
 }
 
 /**
+ * Set the 'isfile' flag on which this profile applies.
+ *
+ * @profile: this NAActionProfile object.
+ *
+ * @isfile: the profile applies only to files.
+ */
+void
+na_action_profile_set_isfile( NAActionProfile *profile, gboolean isfile )
+{
+	g_object_set( G_OBJECT( profile ), PROP_PROFILE_ISFILE_STR, isfile, NULL );
+}
+
+/**
+ * Set the 'isdir' flag on which this profile applies.
+ *
+ * @profile: this NAActionProfile object.
+ *
+ * @isdir: the profile applies only to folders.
+ */
+void
+na_action_profile_set_isdir( NAActionProfile *profile, gboolean isdir )
+{
+	g_object_set( G_OBJECT( profile ), PROP_PROFILE_ISDIR_STR, isdir, NULL );
+}
+
+/**
  * Set the 'isfile' and 'isdir' flags on which this profile applies.
  *
  * @profile: this NAActionProfile object.
@@ -974,6 +1013,19 @@ na_action_profile_set_scheme( NAActionProfile *profile, const gchar *scheme, gbo
 }
 
 /**
+ * Set the schemes on which this profile applies.
+ *
+ * @profile: this NAActionProfile object.
+ *
+ * @schemes: list of schemes which apply.
+ */
+void
+na_action_profile_set_schemes( NAActionProfile *profile, GSList *schemes )
+{
+	g_object_set( G_OBJECT( profile ), PROP_PROFILE_SCHEMES_STR, schemes, NULL );
+}
+
+/**
  * Determines if the given profile is candidate to be displayed in the
  * Nautilus context menu, regarding the list of currently selected
  * items.
diff --git a/src/common/na-action-profile.h b/src/common/na-action-profile.h
index b489530..407ee2c 100644
--- a/src/common/na-action-profile.h
+++ b/src/common/na-action-profile.h
@@ -83,6 +83,12 @@ typedef struct {
 #define PROP_PROFILE_MIMETYPES_STR				"profile-mimetypes"
 #define PROP_PROFILE_SCHEMES_STR				"profile-schemes"
 
+/* internal identifier of profiles must begin with the following prefix
+ * this let us identify a profile key versus an action key
+ * corollarily, no action entry must begin with this same prefix
+ */
+#define ACTION_PROFILE_PREFIX					"profile-"
+
 GType            na_action_profile_get_type( void );
 
 NAActionProfile *na_action_profile_new( const NAObject *action, const gchar *name );
@@ -104,14 +110,18 @@ GSList          *na_action_profile_get_schemes( const NAActionProfile *profile )
 
 gboolean         na_action_profile_are_equal( NAActionProfile *first, NAActionProfile *second );
 
+void             na_action_profile_set_label( NAActionProfile *profile, const gchar *label );
 void             na_action_profile_set_path( NAActionProfile *profile, const gchar *path );
 void             na_action_profile_set_parameters( NAActionProfile *profile, const gchar *parameters );
 void             na_action_profile_set_basenames( NAActionProfile *profile, GSList *basenames );
 void             na_action_profile_set_matchcase( NAActionProfile *profile, gboolean matchcase );
 void             na_action_profile_set_mimetypes( NAActionProfile *profile, GSList *mimetypes );
+void             na_action_profile_set_isfile( NAActionProfile *profile, gboolean isfile );
+void             na_action_profile_set_isdir( NAActionProfile *profile, gboolean isdir );
 void             na_action_profile_set_isfiledir( NAActionProfile *profile, gboolean isfile, gboolean isdir );
 void             na_action_profile_set_multiple( NAActionProfile *profile, gboolean multiple );
 void             na_action_profile_set_scheme( NAActionProfile *profile, const gchar *scheme, gboolean selected );
+void             na_action_profile_set_schemes( NAActionProfile *profile, GSList *schemes );
 
 gboolean         na_action_profile_is_candidate( const NAActionProfile *profile, GList *files );
 gchar           *na_action_profile_parse_parameters( const NAActionProfile *profile, GList *files );
diff --git a/src/common/na-action.c b/src/common/na-action.c
index ba69033..89fc892 100644
--- a/src/common/na-action.c
+++ b/src/common/na-action.c
@@ -393,7 +393,7 @@ na_action_new_with_profile( void )
 {
 	NAAction *action = na_action_new( NULL );
 
-	NAActionProfile *profile = na_action_profile_new( NA_OBJECT( action ), "default-profile" );
+	NAActionProfile *profile = na_action_profile_new( NA_OBJECT( action ), ACTION_PROFILE_PREFIX "zero" );
 
 	action->private->profiles = g_slist_prepend( action->private->profiles, profile );
 
@@ -650,6 +650,34 @@ na_action_set_new_uuid( NAAction *action )
 }
 
 /**
+ * Set a new uuid for the action.
+ *
+ * @action: action whose uuid is to be set.
+ *
+ * @uuid: new uuid.
+ */
+void
+na_action_set_uuid( NAAction *action, const gchar *uuid )
+{
+	g_assert( NA_IS_ACTION( action ));
+	g_object_set( G_OBJECT( action ), PROP_ACTION_UUID_STR, uuid, NULL );
+}
+
+/**
+ * Set a new version for the action.
+ *
+ * @action: action whose version is to be set.
+ *
+ * @version: new version.
+ */
+void
+na_action_set_version( NAAction *action, const gchar *version )
+{
+	g_assert( NA_IS_ACTION( action ));
+	g_object_set( G_OBJECT( action ), PROP_ACTION_VERSION_STR, version, NULL );
+}
+
+/**
  * Set a new label for the action.
  *
  * @action: action whose label is to be set.
@@ -750,18 +778,18 @@ na_action_are_equal( NAAction *first, NAAction *second )
  * The returned pointer is owned by the @action object ; the caller
  * should not try to free or unref it.
  */
-GObject *
+NAObject *
 na_action_get_profile( const NAAction *action, const gchar *name )
 {
 	g_assert( NA_IS_ACTION( action ));
-	GObject *found = NULL;
+	NAObject *found = NULL;
 	GSList *ip;
 
 	for( ip = action->private->profiles ; ip && !found ; ip = ip->next ){
 		NAActionProfile *iprofile = NA_ACTION_PROFILE( ip->data );
 		gchar *iname = na_action_profile_get_name( iprofile );
 		if( !g_ascii_strcasecmp( name, iname )){
-			found = G_OBJECT( iprofile );
+			found = NA_OBJECT( iprofile );
 		}
 		g_free( iname );
 	}
@@ -770,6 +798,22 @@ na_action_get_profile( const NAAction *action, const gchar *name )
 }
 
 /**
+ * Add a profile at the end of the list of profiles.
+ *
+ * @action: the action.
+ *
+ * @profile: the added profile.
+ */
+void
+na_action_add_profile( NAAction *action, NAObject *profile )
+{
+	g_assert( NA_IS_ACTION( action ));
+	g_assert( NA_IS_ACTION_PROFILE( profile ));
+
+	action->private->profiles = g_slist_append( action->private->profiles, profile );
+}
+
+/**
  * Returns the list of profiles of the actions as a GSList of
  * NAActionProfile GObjects.
  *
diff --git a/src/common/na-action.h b/src/common/na-action.h
index aa9abab..6a05c7b 100644
--- a/src/common/na-action.h
+++ b/src/common/na-action.h
@@ -100,14 +100,17 @@ gboolean  na_action_is_readonly( const NAAction *action );
 gpointer  na_action_get_provider( const NAAction *action );
 
 void      na_action_set_new_uuid( NAAction *action );
+void      na_action_set_uuid( NAAction *action, const gchar *uuid );
+void      na_action_set_version( NAAction *action, const gchar *version );
 void      na_action_set_label( NAAction *action, const gchar *label );
 void      na_action_set_tooltip( NAAction *action, const gchar *tooltip );
 void      na_action_set_icon( NAAction *action, const gchar *icon_name );
 
 gboolean  na_action_are_equal( NAAction *first, NAAction *second );
 
-GObject  *na_action_get_profile( const NAAction *action, const gchar *name );
+NAObject *na_action_get_profile( const NAAction *action, const gchar *name );
 GSList   *na_action_get_profiles( const NAAction *action );
+void      na_action_add_profile( NAAction *action, NAObject *profile );
 void      na_action_set_profiles( NAAction *action, GSList *list );
 void      na_action_free_profiles( GSList *list );
 
diff --git a/src/common/na-gconf-keys.h b/src/common/na-gconf-keys.h
index b5d2d61..a1dbc4f 100644
--- a/src/common/na-gconf-keys.h
+++ b/src/common/na-gconf-keys.h
@@ -33,7 +33,7 @@
 
 /* GConf general information
  */
-#define NA_GCONF_CONFIG_PATH		NAUTILUS_ACTIONS_CONFIG_GCONF_BASEDIR "/configurations"
+#define NA_GCONF_CONFIG_PATH			NAUTILUS_ACTIONS_CONFIG_GCONF_BASEDIR "/configurations"
 
 /* GConf key names
  */
diff --git a/src/common/na-utils.c b/src/common/na-utils.c
index 2d4456d..5b3aa2d 100644
--- a/src/common/na-utils.c
+++ b/src/common/na-utils.c
@@ -170,7 +170,8 @@ na_utils_string_list_to_text( GSList *strlist )
 }
 
 /**
- * Extracts a list of strings from a semi-colon-separated text.
+ * Extracts a list of strings from a semi-colon-separated text
+ * (entry text).
  */
 GSList *
 na_utils_text_to_string_list( const gchar *text )
@@ -201,9 +202,23 @@ na_utils_text_to_string_list( const gchar *text )
 	return( strlist );
 }
 
+void
+na_utils_dump_string_list( GSList *list )
+{
+	static const gchar *thisfn = "na_utils_dump_string_list";
+	GSList *i;
+	int c;
+
+	g_debug( "%s: list at %p has %d elements", thisfn, list, g_slist_length( list ));
+	for( i=list, c=0 ; i ; i=i->next, c++ ){
+		gchar *s = ( gchar * ) i->data;
+		g_debug( "%s: %2d - %s", thisfn, c, s );
+	}
+}
+
 /**
  * Converts a list of strings to a comma-separated list of strings,
- * enclosed by brackets.
+ * enclosed by brackets (GConf export format).
  */
 gchar *
 na_utils_gslist_to_schema( GSList *list )
@@ -231,6 +246,17 @@ na_utils_gslist_to_schema( GSList *list )
 }
 
 /**
+ * Converts a string representing a list of strings in a GConf format
+ * to a list of strings.
+ */
+GSList *
+na_utils_schema_to_gslist( const gchar *value )
+{
+	GSList *list = NULL;
+	return( list );
+}
+
+/**
  * Converts a boolean to the suitable string for a GConf schema
  */
 gchar *
@@ -241,6 +267,21 @@ na_utils_boolean_to_schema( gboolean b )
 }
 
 /**
+ * Converts a string to a boolean
+ */
+gboolean
+na_utils_schema_to_boolean( const gchar *value, gboolean default_value )
+{
+	if( !g_ascii_strncasecmp( value, "true", strlen( value ))){
+		return( TRUE );
+	}
+	if( !g_ascii_strncasecmp( value, "false", strlen( value ))){
+		return( FALSE );
+	}
+	return( default_value );
+}
+
+/**
  * Concatenates a gchar **list of strings to a GString.
  */
 gchar *
diff --git a/src/common/na-utils.h b/src/common/na-utils.h
index fe13916..ab08afe 100644
--- a/src/common/na-utils.h
+++ b/src/common/na-utils.h
@@ -45,9 +45,12 @@ GSList  *na_utils_remove_ascii_from_string_list( GSList *list, const gchar *text
 void     na_utils_free_string_list( GSList *list );
 gchar   *na_utils_string_list_to_text( GSList *list );
 GSList  *na_utils_text_to_string_list( const gchar *text );
+void     na_utils_dump_string_list( GSList *list );
 
 gchar   *na_utils_gslist_to_schema( GSList *list );
+GSList  *na_utils_schema_to_gslist( const gchar *value );
 gchar   *na_utils_boolean_to_schema( gboolean b );
+gboolean na_utils_schema_to_boolean( const gchar *value, gboolean default_value );
 
 /*
  * Some functions for GString manipulations.
diff --git a/src/nact/Makefile.am b/src/nact/Makefile.am
index 4df13bb..754fc15 100644
--- a/src/nact/Makefile.am
+++ b/src/nact/Makefile.am
@@ -50,10 +50,17 @@ nautilus_actions_config_SOURCES = \
 	nact-action-profiles-editor.h						\
 	nact-application.c									\
 	nact-application.h									\
-	nact-gconf-schema.c									\
-	nact-gconf-schema.h									\
-	nact-gconf-schema-writer.c							\
-	nact-gconf-schema-writer.h							\
+	nact-assistant.c									\
+	nact-assistant.h									\
+	nact-assist-export.c								\
+	nact-assist-export.h								\
+	nact-assist-import.c								\
+	nact-assist-import.h								\
+	nact-gconf-keys.h									\
+	nact-gconf-reader.c									\
+	nact-gconf-reader.h									\
+	nact-gconf-writer.c									\
+	nact-gconf-writer.h									\
 	nact-iactions-list.c								\
 	nact-iactions-list.h								\
 	nact-imenu-item.c									\
diff --git a/src/nact/base-application.c b/src/nact/base-application.c
index 57a8a3c..a8a9e80 100644
--- a/src/nact/base-application.c
+++ b/src/nact/base-application.c
@@ -543,7 +543,7 @@ base_application_get_dialog( BaseApplication *application, const gchar *name )
  * @name: the name of the searched widget.
  *
  * Returns a pointer to the searched widget, or NULL.
- * This pointer is owned by GtkBuilder object, and moust not be freed
+ * This pointer is owned by GtkBuilder object, and must not be freed
  * nor unreffed by the caller.
  */
 GtkWidget *
@@ -552,14 +552,34 @@ base_application_get_widget( BaseApplication *application, BaseWindow *window, c
 	/*static const gchar *thisfn = "base_application_get_widget";
 	g_debug( "%s: application=%p, name=%s", thisfn, application, name );*/
 
-	GtkWidget *widget = NULL;
 	GtkWindow *toplevel = base_window_get_toplevel_dialog( window );
 
-	if( toplevel ){
-		widget = recursive_search_for_child( application, toplevel, name );
-		if( widget ){
-			g_assert( GTK_IS_WIDGET( widget ));
-		}
+	return( base_application_search_for_widget( application, toplevel, name ));
+}
+
+/**
+ * Returns a pointer to the named widget as a dialog's child.
+ *
+ * @application: this BaseApplication.
+ *
+ * @window: a GtkWindow toplevel dialog.
+ *
+ * @name: the name of the searched widget.
+ *
+ * Returns a pointer to the searched widget, or NULL.
+ * This pointer is owned by GtkBuilder object, and must not be freed
+ * nor unreffed by the caller.
+ */
+GtkWidget *
+base_application_search_for_widget( BaseApplication *application, GtkWindow *window, const gchar *name )
+{
+	/*static const gchar *thisfn = "base_application_get_widget";
+	g_debug( "%s: application=%p, name=%s", thisfn, application, name );*/
+
+	GtkWidget *widget = recursive_search_for_child( application, window, name );
+
+	if( widget ){
+		g_assert( GTK_IS_WIDGET( widget ));
 	}
 
 	return( widget );
diff --git a/src/nact/base-application.h b/src/nact/base-application.h
index 757f75a..b4a1599 100644
--- a/src/nact/base-application.h
+++ b/src/nact/base-application.h
@@ -109,6 +109,7 @@ GObject   *base_application_get_main_window( BaseApplication *application );
 
 GtkWindow *base_application_get_dialog( BaseApplication *application, const gchar *name );
 GtkWidget *base_application_get_widget( BaseApplication *application, BaseWindow *window, const gchar *name );
+GtkWidget *base_application_search_for_widget( BaseApplication *application, GtkWindow *window, const gchar *name );
 
 void       base_application_error_dlg( BaseApplication *application, GtkMessageType type, const gchar *primary, const gchar *secondary );
 gboolean   base_application_yesno_dlg( BaseApplication *application, GtkMessageType type, const gchar *first, const gchar *second );
diff --git a/src/nact/base-window.c b/src/nact/base-window.c
index 218090b..a512cf7 100644
--- a/src/nact/base-window.c
+++ b/src/nact/base-window.c
@@ -91,9 +91,9 @@ static GtkWindow *do_get_toplevel_dialog( BaseWindow *window );
 static GtkWindow *do_get_dialog( BaseWindow *window, const gchar *name );
 static GtkWidget *do_get_widget( BaseWindow *window, const gchar *name );
 
-static gboolean   is_toplevel_initialized( BaseWindow *window );
-static void       set_toplevel_initialized( BaseWindow *window );
 static gboolean   is_main_window( BaseWindow *window );
+static gboolean   is_toplevel_initialized( BaseWindow *window, GtkWindow *toplevel );
+static void       set_toplevel_initialized( BaseWindow *window, GtkWindow *toplevel, gboolean init );
 
 GType
 base_window_get_type( void )
@@ -273,10 +273,17 @@ instance_dispose( GObject *window )
 		self->private->dispose_has_run = TRUE;
 
 		if( is_main_window( BASE_WINDOW( window ))){
+			g_debug( "%s: quitting main window", thisfn );
 			gtk_main_quit ();
 			gtk_widget_destroy( GTK_WIDGET( self->private->toplevel_dialog ));
 
+		} else if( GTK_IS_ASSISTANT( self->private->toplevel_dialog )){
+			g_debug( "%s: quitting assistant", thisfn );
+			gtk_main_quit();
+			gtk_widget_hide_all( GTK_WIDGET( self->private->toplevel_dialog ));
+
 		} else {
+			g_debug( "%s: quitting dialog", thisfn );
 			gtk_widget_hide_all( GTK_WIDGET( self->private->toplevel_dialog ));
 		}
 
@@ -312,9 +319,13 @@ instance_finalize( GObject *window )
  * This is a one-time initialization just after the BaseWindow has been
  * allocated. This should leave the BaseWindow object with a valid
  * toplevel GtkWindow dialog. This is also time to make one-time
- * initialization on the toplevel dialog.
+ * initialization on this toplevel dialog.
  *
  * For an every-time initialization, see base_window_run.
+ *
+ * Note that the BaseWindow itself should be initialized each time
+ * the user opens the dialog, though the GtkWindow itself needs only
+ * be initialized the first time it is loaded.
  */
 void
 base_window_init( BaseWindow *window )
@@ -469,29 +480,30 @@ static void
 do_init_window( BaseWindow *window )
 {
 	static const gchar *thisfn = "base_window_do_init_window";
-	g_debug( "%s: window=%p", thisfn, window );
-
 	g_assert( BASE_IS_WINDOW( window ));
 
-	gchar *dialog_name = v_get_toplevel_name( window );
-	g_assert( dialog_name && strlen( dialog_name ));
+	if( !window->private->initialized ){
+		g_debug( "%s: window=%p", thisfn, window );
+
+		gchar *dialog_name = v_get_toplevel_name( window );
+		g_assert( dialog_name && strlen( dialog_name ));
+
+		GtkWindow *toplevel = base_window_get_dialog( window, dialog_name );
+		window->private->toplevel_dialog = toplevel;
 
-	GtkWindow *toplevel = base_window_get_dialog( window, dialog_name );
-	window->private->toplevel_dialog = toplevel;
+		if( toplevel ){
+			g_assert( GTK_IS_WINDOW( toplevel ));
 
-	if( toplevel ){
-		g_assert( GTK_IS_WINDOW( toplevel ));
+			if( !is_toplevel_initialized( window, toplevel )){
 
-		if( !is_toplevel_initialized( window )){
-			v_initial_load_toplevel( window );
-			set_toplevel_initialized( window );
+				v_initial_load_toplevel( window );
+				set_toplevel_initialized( window, toplevel, TRUE );
+			}
 		}
 
-		v_runtime_init_toplevel( window );
+		g_free( dialog_name );
+		window->private->initialized = TRUE;
 	}
-
-	g_free( dialog_name );
-	window->private->initialized = TRUE;
 }
 
 static void
@@ -522,6 +534,8 @@ do_run_window( BaseWindow *window )
 		base_window_init( window );
 	}
 
+	v_runtime_init_toplevel( window );
+
 	static const gchar *thisfn = "base_window_do_run_window";
 	g_debug( "%s: window=%p", thisfn, window );
 
@@ -534,7 +548,12 @@ do_run_window( BaseWindow *window )
 		g_debug( "%s: starting gtk_main", thisfn );
 		gtk_main();
 
+	} else if( GTK_IS_ASSISTANT( this_dialog )){
+		g_debug( "%s: starting gtk_main", thisfn );
+		gtk_main();
+
 	} else {
+		g_assert( GTK_IS_DIALOG( this_dialog ));
 		g_debug( "%s: starting gtk_dialog_run", thisfn );
 		gint code;
 		do {
@@ -580,30 +599,6 @@ do_get_widget( BaseWindow *window, const gchar *name )
 }
 
 static gboolean
-is_toplevel_initialized( BaseWindow *window )
-{
-	GtkWindow *toplevel = window->private->toplevel_dialog;
-	g_assert( toplevel );
-	g_assert( GTK_IS_WINDOW( toplevel ));
-
-	gpointer data = g_object_get_data( G_OBJECT( toplevel ), "base-window-toplevel-initialized" );
-	if( !data ){
-		return( FALSE );
-	}
-	return(( gboolean ) data );
-}
-
-static void
-set_toplevel_initialized( BaseWindow *window )
-{
-	GtkWindow *toplevel = window->private->toplevel_dialog;
-	g_assert( toplevel );
-	g_assert( GTK_IS_WINDOW( toplevel ));
-
-	g_object_set_data( G_OBJECT( toplevel ), "base-window-toplevel-initialized", ( gpointer ) TRUE );
-}
-
-static gboolean
 is_main_window( BaseWindow *window )
 {
 	BaseApplication *appli = window->private->application;
@@ -617,6 +612,20 @@ is_main_window( BaseWindow *window )
 	return( main_dialog == this_dialog );
 }
 
+static gboolean
+is_toplevel_initialized( BaseWindow *window, GtkWindow *toplevel )
+{
+	gboolean initialized;
+	initialized = GPOINTER_TO_UINT( g_object_get_data( G_OBJECT( toplevel ), "base-window-toplevel-initialized" ));
+	return( initialized );
+}
+
+static void
+set_toplevel_initialized( BaseWindow *window, GtkWindow *toplevel, gboolean initialized )
+{
+	g_object_set_data( G_OBJECT( toplevel ), "base-window-toplevel-initialized", GUINT_TO_POINTER( initialized ));
+}
+
 void
 base_window_error_dlg( BaseWindow *window, GtkMessageType type, const gchar *primary, const gchar *secondary )
 {
diff --git a/src/nact/nact-assist-export.c b/src/nact/nact-assist-export.c
new file mode 100644
index 0000000..9fbae76
--- /dev/null
+++ b/src/nact/nact-assist-export.c
@@ -0,0 +1,695 @@
+/*
+ * 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 <glib/gi18n.h>
+#include <gtk/gtk.h>
+#include <string.h>
+
+#include <common/na-action.h>
+#include <common/na-utils.h>
+
+#include "base-application.h"
+#include "nact-assist-export.h"
+#include "nact-gconf-writer.h"
+#include "nact-iactions-list.h"
+#include "nact-iprefs.h"
+
+/* Export Assistant
+ *
+ * pos.  type     title
+ * ---   -------  ------------------------------------
+ *   0   Intro    Introduction
+ *   1   Content  Selection of the actions
+ *   2   Content  Selection of the target folder
+ *   3   Confirm  Summary of the operations to be done
+ *   4   Summary  Export is done: summary of the done operations
+ */
+
+enum {
+	ASSIST_PAGE_INTRO = 0,
+	ASSIST_PAGE_ACTIONS_SELECTION,
+	ASSIST_PAGE_FOLDER_SELECTION,
+	ASSIST_PAGE_CONFIRM,
+	ASSIST_PAGE_DONE
+};
+
+/* private class data
+ */
+struct NactAssistExportClassPrivate {
+};
+
+/* private instance data
+ */
+struct NactAssistExportPrivate {
+	gboolean  dispose_has_run;
+	gchar    *uri;
+	GSList   *fnames;
+	gint      errors;
+	gchar    *reason;
+};
+
+static GObjectClass *st_parent_class = NULL;
+
+static GType             register_type( void );
+static void              class_init( NactAssistExportClass *klass );
+static void              iactions_list_iface_init( NactIActionsListInterface *iface );
+static void              instance_init( GTypeInstance *instance, gpointer klass );
+static void              instance_dispose( GObject *application );
+static void              instance_finalize( GObject *application );
+
+static NactAssistExport *assist_new( BaseApplication *application );
+
+static gchar            *do_get_iprefs_window_id( NactWindow *window );
+static gchar            *do_get_dialog_name( BaseWindow *dialog );
+static void              on_initial_load_dialog( BaseWindow *dialog );
+static void              on_runtime_init_dialog( BaseWindow *dialog );
+static void              on_apply( NactAssistant *window, GtkAssistant *assistant );
+static void              on_prepare( NactAssistant *window, GtkAssistant *assistant, GtkWidget *page );
+
+static void              assist_initial_load_intro( NactAssistExport *window, GtkAssistant *assistant );
+static void              assist_runtime_init_intro( NactAssistExport *window, GtkAssistant *assistant );
+static void              assist_initial_load_actions_list( NactAssistExport *window, GtkAssistant *assistant );
+static void              assist_runtime_init_actions_list( NactAssistExport *window, GtkAssistant *assistant );
+static void              on_actions_list_selection_changed( GtkTreeSelection *selection, gpointer user_data );
+static void              assist_initial_load_target_folder( NactAssistExport *window, GtkAssistant *assistant );
+static void              assist_runtime_init_target_folder( NactAssistExport *window, GtkAssistant *assistant );
+static GtkFileChooser   *get_folder_chooser( NactAssistExport *window );
+static void              on_folder_selection_changed( GtkFileChooser *chooser, gpointer user_data );
+static gboolean          is_writable_dir( const gchar *uri );
+static void              assist_initial_load_confirm( NactAssistExport *window, GtkAssistant *assistant );
+static void              assist_runtime_init_confirm( NactAssistExport *window, GtkAssistant *assistant );
+static void              assist_prepare_confirm( NactAssistExport *window, GtkAssistant *assistant, GtkWidget *page );
+static void              assist_initial_load_exportdone( NactAssistExport *window, GtkAssistant *assistant );
+static void              assist_runtime_init_exportdone( NactAssistExport *window, GtkAssistant *assistant );
+static void              assist_prepare_exportdone( NactAssistExport *window, GtkAssistant *assistant, GtkWidget *page );
+static void              do_export( NactAssistExport *window );
+
+#ifdef NACT_MAINTAINER_MODE
+static void              dump( NactAssistExport *window );
+#endif
+
+GType
+nact_assist_export_get_type( void )
+{
+	static GType window_type = 0;
+
+	if( !window_type ){
+		window_type = register_type();
+	}
+
+	return( window_type );
+}
+
+static GType
+register_type( void )
+{
+	static const gchar *thisfn = "nact_assist_export_register_type";
+	g_debug( "%s", thisfn );
+
+	static GTypeInfo info = {
+		sizeof( NactAssistExportClass ),
+		( GBaseInitFunc ) NULL,
+		( GBaseFinalizeFunc ) NULL,
+		( GClassInitFunc ) class_init,
+		NULL,
+		NULL,
+		sizeof( NactAssistExport ),
+		0,
+		( GInstanceInitFunc ) instance_init
+	};
+
+	GType type = g_type_register_static( NACT_ASSISTANT_TYPE, "NactAssistExport", &info, 0 );
+
+	/* implement IActionsList interface
+	 */
+	static const GInterfaceInfo iactions_list_iface_info = {
+		( GInterfaceInitFunc ) iactions_list_iface_init,
+		NULL,
+		NULL
+	};
+
+	g_type_add_interface_static( type, NACT_IACTIONS_LIST_TYPE, &iactions_list_iface_info );
+
+	return( type );
+}
+
+static void
+class_init( NactAssistExportClass *klass )
+{
+	static const gchar *thisfn = "nact_assist_export_class_init";
+	g_debug( "%s: klass=%p", thisfn, klass );
+
+	st_parent_class = g_type_class_peek_parent( klass );
+
+	GObjectClass *object_class = G_OBJECT_CLASS( klass );
+	object_class->dispose = instance_dispose;
+	object_class->finalize = instance_finalize;
+
+	klass->private = g_new0( NactAssistExportClassPrivate, 1 );
+
+	BaseWindowClass *base_class = BASE_WINDOW_CLASS( klass );
+	base_class->get_toplevel_name = do_get_dialog_name;
+	base_class->initial_load_toplevel = on_initial_load_dialog;
+	base_class->runtime_init_toplevel = on_runtime_init_dialog;
+
+	NactWindowClass *nact_class = NACT_WINDOW_CLASS( klass );
+	nact_class->get_iprefs_window_id = do_get_iprefs_window_id;
+
+	NactAssistantClass *assist_class = NACT_ASSISTANT_CLASS( klass );
+	assist_class->on_assistant_apply = on_apply;
+	assist_class->on_assistant_prepare = on_prepare;
+}
+
+static void
+iactions_list_iface_init( NactIActionsListInterface *iface )
+{
+	static const gchar *thisfn = "nact_assist_export_iactions_list_iface_init";
+	g_debug( "%s: iface=%p", thisfn, iface );
+
+	iface->on_selection_changed = on_actions_list_selection_changed;
+}
+
+static void
+instance_init( GTypeInstance *instance, gpointer klass )
+{
+	static const gchar *thisfn = "nact_assist_export_instance_init";
+	g_debug( "%s: instance=%p, klass=%p", thisfn, instance, klass );
+
+	g_assert( NACT_IS_ASSIST_EXPORT( instance ));
+	NactAssistExport *self = NACT_ASSIST_EXPORT( instance );
+
+	self->private = g_new0( NactAssistExportPrivate, 1 );
+
+	self->private->dispose_has_run = FALSE;
+	self->private->fnames = NULL;
+	self->private->errors = 0;
+}
+
+static void
+instance_dispose( GObject *window )
+{
+	static const gchar *thisfn = "nact_assist_export_instance_dispose";
+	g_debug( "%s: window=%p", thisfn, window );
+
+	g_assert( NACT_IS_ASSIST_EXPORT( window ));
+	NactAssistExport *self = NACT_ASSIST_EXPORT( window );
+
+	if( !self->private->dispose_has_run ){
+
+		self->private->dispose_has_run = TRUE;
+
+		/* chain up to the parent class */
+		G_OBJECT_CLASS( st_parent_class )->dispose( window );
+	}
+}
+
+static void
+instance_finalize( GObject *window )
+{
+	static const gchar *thisfn = "nact_assist_export_instance_finalize";
+	g_debug( "%s: window=%p", thisfn, window );
+
+	g_assert( NACT_IS_ASSIST_EXPORT( window ));
+	NactAssistExport *self = ( NactAssistExport * ) window;
+
+	g_free( self->private->uri );
+	na_utils_free_string_list( self->private->fnames );
+	g_free( self->private->reason );
+
+	g_free( self->private );
+
+	/* chain call to parent class */
+	if( st_parent_class->finalize ){
+		G_OBJECT_CLASS( st_parent_class )->finalize( window );
+	}
+}
+
+static NactAssistExport *
+assist_new( BaseApplication *application )
+{
+	return( g_object_new( NACT_ASSIST_EXPORT_TYPE, PROP_WINDOW_APPLICATION_STR, application, NULL ));
+}
+
+/**
+ * Run the assistant.
+ *
+ * @main: the main window of the application.
+ */
+void
+nact_assist_export_run( NactWindow *main )
+{
+	BaseApplication *appli = BASE_APPLICATION( base_window_get_application( BASE_WINDOW( main )));
+
+	NactAssistExport *assist = assist_new( appli );
+
+	base_window_run( BASE_WINDOW( assist ));
+}
+
+static gchar *
+do_get_iprefs_window_id( NactWindow *window )
+{
+	return( g_strdup( "export-assistant" ));
+}
+
+static gchar *
+do_get_dialog_name( BaseWindow *dialog )
+{
+	return( g_strdup( "ExportAssistant" ));
+}
+
+static void
+on_initial_load_dialog( BaseWindow *dialog )
+{
+	static const gchar *thisfn = "nact_assist_export_on_initial_load_dialog";
+
+	/* call parent class at the very beginning */
+	if( BASE_WINDOW_CLASS( st_parent_class )->initial_load_toplevel ){
+		BASE_WINDOW_CLASS( st_parent_class )->initial_load_toplevel( dialog );
+	}
+
+	g_debug( "%s: dialog=%p", thisfn, dialog );
+	g_assert( NACT_IS_ASSIST_EXPORT( dialog ));
+	NactAssistExport *window = NACT_ASSIST_EXPORT( dialog );
+
+	GtkAssistant *assistant = GTK_ASSISTANT( base_window_get_toplevel_dialog( dialog ));
+
+	assist_initial_load_intro( window, assistant );
+	assist_initial_load_actions_list( window, assistant );
+	assist_initial_load_target_folder( window, assistant );
+	assist_initial_load_confirm( window, assistant );
+	assist_initial_load_exportdone( window, assistant );
+}
+
+static void
+on_runtime_init_dialog( BaseWindow *dialog )
+{
+	static const gchar *thisfn = "nact_assist_export_on_runtime_init_dialog";
+
+	/* call parent class at the very beginning */
+	if( BASE_WINDOW_CLASS( st_parent_class )->runtime_init_toplevel ){
+		BASE_WINDOW_CLASS( st_parent_class )->runtime_init_toplevel( dialog );
+	}
+
+	g_debug( "%s: dialog=%p", thisfn, dialog );
+	g_assert( NACT_IS_ASSIST_EXPORT( dialog ));
+	NactAssistExport *window = NACT_ASSIST_EXPORT( dialog );
+
+	GtkAssistant *assistant = GTK_ASSISTANT( base_window_get_toplevel_dialog( dialog ));
+
+	assist_runtime_init_intro( window, assistant );
+	assist_runtime_init_actions_list( window, assistant );
+	assist_runtime_init_target_folder( window, assistant );
+	assist_runtime_init_confirm( window, assistant );
+	assist_runtime_init_exportdone( window, assistant );
+}
+
+/*
+ * As of 1.11, nact_gconf_writer doesn't return any error message.
+ * An error is simply indicated by returning a null filename.
+ * So we provide a general error message.
+ *
+ * apply signal is ran from the confirm page _after_ the prepare signal
+ * of the summary page ; it is so almost useless to do anything here if
+ * we want show the result on the summary...
+ */
+static void
+on_apply( NactAssistant *window, GtkAssistant *assistant )
+{
+	static const gchar *thisfn = "nact_assist_export_on_apply";
+	g_debug( "%s: window=%p, assistant=%p", thisfn, window, assistant );
+}
+
+static void
+on_prepare( NactAssistant *window, GtkAssistant *assistant, GtkWidget *page )
+{
+	/*static const gchar *thisfn = "nact_assist_export_on_prepare";
+	g_debug( "%s: window=%p, assistant=%p, page=%p", thisfn, window, assistant, page );*/
+
+	GtkAssistantPageType type = gtk_assistant_get_page_type( assistant, page );
+
+	switch( type ){
+		case GTK_ASSISTANT_PAGE_CONFIRM:
+			assist_prepare_confirm( NACT_ASSIST_EXPORT( window ), assistant, page );
+			break;
+
+		case GTK_ASSISTANT_PAGE_SUMMARY:
+			assist_prepare_exportdone( NACT_ASSIST_EXPORT( window ), assistant, page );
+			break;
+
+		default:
+			break;
+	}
+}
+
+static void
+assist_initial_load_intro( NactAssistExport *window, GtkAssistant *assistant )
+{
+}
+
+static void
+assist_runtime_init_intro( NactAssistExport *window, GtkAssistant *assistant )
+{
+	static const gchar *thisfn = "nact_assist_export_runtime_init_intro";
+	g_debug( "%s: window=%p, assistant=%p", thisfn, window, assistant );
+
+	GtkWidget *content = gtk_assistant_get_nth_page( assistant, ASSIST_PAGE_INTRO );
+	gtk_assistant_set_page_complete( assistant, content, TRUE );
+}
+
+static void
+assist_initial_load_actions_list( NactAssistExport *window, GtkAssistant *assistant )
+{
+	g_assert( NACT_IS_IACTIONS_LIST( window ));
+	nact_iactions_list_initial_load( NACT_WINDOW( window ));
+	nact_iactions_list_set_multiple_selection( NACT_WINDOW( window ), TRUE );
+	nact_iactions_list_set_send_selection_changed_on_fill_list( NACT_WINDOW( window ), FALSE );
+}
+
+static void
+assist_runtime_init_actions_list( NactAssistExport *window, GtkAssistant *assistant )
+{
+	nact_iactions_list_runtime_init( NACT_WINDOW( window ));
+
+	GtkWidget *content = gtk_assistant_get_nth_page( assistant, ASSIST_PAGE_ACTIONS_SELECTION );
+	gtk_assistant_set_page_complete( assistant, content, FALSE );
+}
+
+static void
+on_actions_list_selection_changed( GtkTreeSelection *selection, gpointer user_data )
+{
+	/*static const gchar *thisfn = "nact_assist_export_on_actions_list_selection_changed";
+	g_debug( "%s: selection=%p, user_data=%p", thisfn, selection, user_data );*/
+
+	g_assert( NACT_IS_ASSIST_EXPORT( user_data ));
+	GtkAssistant *assistant = GTK_ASSISTANT( base_window_get_toplevel_dialog( BASE_WINDOW( user_data )));
+	gint pos = gtk_assistant_get_current_page( assistant );
+	if( pos == ASSIST_PAGE_ACTIONS_SELECTION ){
+
+		gboolean enabled = ( gtk_tree_selection_count_selected_rows( selection ) > 0 );
+
+		GtkWidget *content = gtk_assistant_get_nth_page( assistant, pos );
+		gtk_assistant_set_page_complete( assistant, content, enabled );
+		gtk_assistant_update_buttons_state( assistant );
+	}
+}
+
+static void
+assist_initial_load_target_folder( NactAssistExport *window, GtkAssistant *assistant )
+{
+	GtkFileChooser *chooser = get_folder_chooser( window );
+	gtk_file_chooser_set_action( GTK_FILE_CHOOSER( chooser ), GTK_FILE_CHOOSER_ACTION_CREATE_FOLDER );
+	gtk_file_chooser_set_select_multiple( GTK_FILE_CHOOSER( chooser ), FALSE );
+}
+
+static void
+assist_runtime_init_target_folder( NactAssistExport *window, GtkAssistant *assistant )
+{
+	GtkFileChooser *chooser = get_folder_chooser( window );
+	gtk_file_chooser_unselect_all( chooser );
+
+	gchar *uri = nact_iprefs_get_export_folder_uri( NACT_WINDOW( window ));
+	if( uri && strlen( uri )){
+		gtk_file_chooser_set_uri( GTK_FILE_CHOOSER( chooser ), uri );
+	}
+	g_free( uri );
+
+	nact_window_signal_connect( NACT_WINDOW( window ), G_OBJECT( chooser ), "selection-changed", G_CALLBACK( on_folder_selection_changed ));
+
+	GtkWidget *content = gtk_assistant_get_nth_page( assistant, ASSIST_PAGE_FOLDER_SELECTION );
+	gtk_assistant_set_page_complete( assistant, content, FALSE );
+}
+
+static GtkFileChooser *
+get_folder_chooser( NactAssistExport *window )
+{
+	return( GTK_FILE_CHOOSER( base_window_get_widget( BASE_WINDOW( window ), "ExportFolderChooser" )));
+}
+
+/*
+ * we check the selected uri for writability
+ * this is always subject to become invalid before actually writing
+ * but this is better than nothing, doesn't ?
+ */
+static void
+on_folder_selection_changed( GtkFileChooser *chooser, gpointer user_data )
+{
+	static const gchar *thisfn = "nact_assist_export_on_folder_selection_changed";
+	g_debug( "%s: chooser=%p, user_data=%p", thisfn, chooser, user_data );
+
+	g_assert( NACT_IS_ASSIST_EXPORT( user_data ));
+	GtkAssistant *assistant = GTK_ASSISTANT( base_window_get_toplevel_dialog( BASE_WINDOW( user_data )));
+	gint pos = gtk_assistant_get_current_page( assistant );
+	if( pos == ASSIST_PAGE_FOLDER_SELECTION ){
+
+		gchar *uri = gtk_file_chooser_get_uri( chooser );
+		g_debug( "%s: uri=%s", thisfn, uri );
+		gboolean enabled = ( uri && strlen( uri ) && is_writable_dir( uri ));
+
+		if( enabled ){
+			NactAssistExport *assist = NACT_ASSIST_EXPORT( user_data );
+			g_free( assist->private->uri );
+			assist->private->uri = g_strdup( uri );
+			nact_iprefs_save_export_folder_uri( NACT_WINDOW( user_data ), uri );
+		}
+
+		g_free( uri );
+
+		GtkWidget *content = gtk_assistant_get_nth_page( assistant, pos );
+		gtk_assistant_set_page_complete( assistant, content, enabled );
+		gtk_assistant_update_buttons_state( assistant );
+	}
+}
+
+static gboolean
+is_writable_dir( const gchar *uri )
+{
+	static const gchar *thisfn = "nact_assist_export_is_writable_dir";
+
+	if( !uri || !strlen( uri )){
+		return( FALSE );
+	}
+
+	GFile *file = g_file_new_for_uri( uri );
+	GError *error = NULL;
+	GFileInfo *info = g_file_query_info( file,
+			G_FILE_ATTRIBUTE_ACCESS_CAN_WRITE "," G_FILE_ATTRIBUTE_STANDARD_TYPE,
+			G_FILE_QUERY_INFO_NONE, NULL, &error );
+
+	if( error ){
+		g_warning( "%s: g_file_query_info error: %s", thisfn, error->message );
+		g_error_free( error );
+		g_object_unref( file );
+		return( FALSE );
+	}
+
+	GFileType type = g_file_info_get_file_type( info );
+	if( type != G_FILE_TYPE_DIRECTORY ){
+		g_warning( "%s: %s is not a directory", thisfn, uri );
+		g_object_unref( info );
+		return( FALSE );
+	}
+
+	gboolean writable = g_file_info_get_attribute_boolean( info, G_FILE_ATTRIBUTE_ACCESS_CAN_WRITE );
+	if( !writable ){
+		g_warning( "%s: %s is not writable", thisfn, uri );
+	}
+	g_object_unref( info );
+
+	return( writable );
+}
+
+static void
+assist_initial_load_confirm( NactAssistExport *window, GtkAssistant *assistant )
+{
+}
+
+static void
+assist_runtime_init_confirm( NactAssistExport *window, GtkAssistant *assistant )
+{
+}
+
+static void
+assist_prepare_confirm( NactAssistExport *window, GtkAssistant *assistant, GtkWidget *page )
+{
+	static const gchar *thisfn = "nact_assist_export_prepare_confirm";
+	g_debug( "%s: window=%p, assistant=%p, page=%p", thisfn, window, assistant, page );
+
+#ifdef NACT_MAINTAINER_MODE
+	dump( window );
+#endif
+
+	gchar *text = g_strdup( _( "<b>About to export selected actions :</b>\n\n" ));
+
+	GSList *actions = nact_iactions_list_get_selected_actions( NACT_WINDOW( window ));
+	GSList *ia;
+	gchar *tmp;
+
+	for( ia = actions ; ia ; ia = ia->next ){
+		tmp = g_strdup_printf( "%s\t%s\n", text, na_action_get_label( NA_ACTION( ia->data )));
+		g_free( text );
+		text = tmp;
+	}
+
+	g_assert( window->private->uri && strlen( window->private->uri ));
+
+	tmp = g_strdup_printf( _( "%s\n\n<b>Into the destination folder :</b>\n\n\t%s" ), text, window->private->uri );
+	g_free( text );
+	text = tmp;
+
+	gtk_label_set_markup( GTK_LABEL( page ), text );
+	g_free( text );
+
+	gtk_assistant_set_page_complete( assistant, page, TRUE );
+}
+
+static void
+assist_initial_load_exportdone( NactAssistExport *window, GtkAssistant *assistant )
+{
+}
+
+static void
+assist_runtime_init_exportdone( NactAssistExport *window, GtkAssistant *assistant )
+{
+}
+
+static void
+assist_prepare_exportdone( NactAssistExport *window, GtkAssistant *assistant, GtkWidget *page )
+{
+	static const gchar *thisfn = "nact_assist_export_prepare_exportdone";
+	g_debug( "%s: window=%p, assistant=%p, page=%p", thisfn, window, assistant, page );
+
+	do_export( window );
+
+#ifdef NACT_MAINTAINER_MODE
+	dump( window );
+#endif
+
+	gchar *text, *tmp;
+
+	if( window->private->errors ){
+		text = g_strdup_printf(
+				_( "<b>One or more errors have been detected when exporting actions.</b>\n\n%s" ),
+				window->private->reason );
+
+	} else {
+		text = g_strdup( _( "<b>Selected actions have been successfully exported...</b>\n\n" ));
+
+		tmp = g_strdup_printf( _( "%s<b>...in folder :</b>\n\n\t%s/\n\n" ), text, window->private->uri );
+		g_free( text );
+		text = tmp;
+
+		tmp = g_strdup_printf( _( "%s<b>...as files :</b>\n\n" ), text );
+		g_free( text );
+		text = tmp;
+
+		GSList *ifn;
+		for( ifn = window->private->fnames ; ifn ; ifn = ifn->next ){
+			GFile *file = g_file_new_for_uri(( gchar * ) ifn->data );
+			gchar *bname = g_file_get_basename( file );
+			tmp = g_strdup_printf( "%s\t%s\n", text, bname );
+			g_free( bname );
+			g_object_unref( file );
+			g_free( text );
+			text = tmp;
+		}
+	}
+
+	gtk_label_set_markup( GTK_LABEL( page ), text );
+	g_free( text );
+
+	gtk_assistant_set_page_complete( assistant, page, TRUE );
+	nact_assistant_set_warn_on_cancel( NACT_ASSISTANT( window ), FALSE );
+}
+
+static void
+do_export( NactAssistExport *window )
+{
+	static const gchar *thisfn = "nact_assist_export_do_export";
+	g_debug( "%s: window=%p", thisfn, window );
+
+	GSList *actions = nact_iactions_list_get_selected_actions( NACT_WINDOW( window ));
+	GSList *ia;
+	gchar *msg = NULL;
+	gchar *reason = NULL;
+	gchar *tmp;
+
+	g_assert( window->private->uri && strlen( window->private->uri ));
+
+	for( ia = actions ; ia ; ia = ia->next ){
+		NAAction *action = NA_ACTION( ia->data );
+		gchar *fname = nact_gconf_writer_export( action, window->private->uri, &msg );
+
+		if( fname && strlen( fname )){
+			window->private->fnames = g_slist_prepend( window->private->fnames, fname );
+			g_debug( "%s: fname=%s", thisfn, fname );
+
+		} else {
+			window->private->errors += 1;
+			if( msg ){
+				if( reason ){
+					tmp = g_strdup_printf( "%s\n", reason );
+					g_free( reason );
+					reason = tmp;
+				}
+				tmp = g_strdup_printf( "%s%s", reason, msg );
+				g_free( reason );
+				reason = tmp;
+				g_free( msg );
+			}
+		}
+	}
+
+	if( window->private->errors ){
+		if( !reason ){
+			reason = g_strdup( _( "You may not have writing permissions on selected folder." ));
+		}
+		window->private->reason = reason;
+	}
+
+	g_slist_free( actions );
+}
+
+#ifdef NACT_MAINTAINER_MODE
+static void
+dump( NactAssistExport *window )
+{
+	static const gchar *thisfn = "nact_assist_export_dump";
+	g_debug( "%s:          window=%p", thisfn, window );
+	g_debug( "%s:         private=%p", thisfn, window->private );
+	g_debug( "%s: dispose_has_run=%s", thisfn, window->private->dispose_has_run ? "True":"False" );
+	g_debug( "%s:             uri=%s", thisfn, window->private->uri );
+	g_debug( "%s:          errors=%d", thisfn, window->private->errors );
+	na_utils_dump_string_list( window->private->fnames );
+}
+#endif
diff --git a/src/nact/nact-assist-export.h b/src/nact/nact-assist-export.h
new file mode 100644
index 0000000..f61f001
--- /dev/null
+++ b/src/nact/nact-assist-export.h
@@ -0,0 +1,71 @@
+/*
+ * 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 __NACT_ASSIST_EXPORT_H__
+#define __NACT_ASSIST_EXPORT_H__
+
+/*
+ * NactAssistExport class definition.
+ */
+
+#include "nact-assistant.h"
+
+G_BEGIN_DECLS
+
+#define NACT_ASSIST_EXPORT_TYPE					( nact_assist_export_get_type())
+#define NACT_ASSIST_EXPORT( object )			( G_TYPE_CHECK_INSTANCE_CAST( object, NACT_ASSIST_EXPORT_TYPE, NactAssistExport ))
+#define NACT_ASSIST_EXPORT_CLASS( klass )		( G_TYPE_CHECK_CLASS_CAST( klass, NACT_ASSIST_EXPORT_TYPE, NactAssistExportClass ))
+#define NACT_IS_ASSIST_EXPORT( object )			( G_TYPE_CHECK_INSTANCE_TYPE( object, NACT_ASSIST_EXPORT_TYPE ))
+#define NACT_IS_ASSIST_EXPORT_CLASS( klass )	( G_TYPE_CHECK_CLASS_TYPE(( klass ), NACT_ASSIST_EXPORT_TYPE ))
+#define NACT_ASSIST_EXPORT_GET_CLASS( object )	( G_TYPE_INSTANCE_GET_CLASS(( object ), NACT_ASSIST_EXPORT_TYPE, NactAssistExportClass ))
+
+typedef struct NactAssistExportPrivate NactAssistExportPrivate;
+
+typedef struct {
+	NactAssistant            parent;
+	NactAssistExportPrivate *private;
+}
+	NactAssistExport;
+
+typedef struct NactAssistExportClassPrivate NactAssistExportClassPrivate;
+
+typedef struct {
+	NactAssistantClass            parent;
+	NactAssistExportClassPrivate *private;
+}
+	NactAssistExportClass;
+
+GType nact_assist_export_get_type( void );
+
+void  nact_assist_export_run( NactWindow *main );
+
+G_END_DECLS
+
+#endif /* __NACT_ASSIST_EXPORT_H__ */
diff --git a/src/nact/nact-assist-import.c b/src/nact/nact-assist-import.c
new file mode 100644
index 0000000..64c1726
--- /dev/null
+++ b/src/nact/nact-assist-import.c
@@ -0,0 +1,523 @@
+/*
+ * 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 <glib/gi18n.h>
+#include <gtk/gtk.h>
+#include <string.h>
+
+#include <common/na-action.h>
+#include <common/na-utils.h>
+
+#include "base-application.h"
+#include "nact-assist-import.h"
+#include "nact-gconf-reader.h"
+#include "nact-iprefs.h"
+
+/* Import Assistant
+ *
+ * pos.  type     title
+ * ---   -------  ------------------------------------
+ *   0   Intro    Introduction
+ *   1   Content  Selection of the files
+ *   2   Confirm  Display the selected files before import
+ *   3   Summary  Import is done: summary of the done operations
+ */
+
+enum {
+	ASSIST_PAGE_INTRO = 0,
+	ASSIST_PAGE_FILES_SELECTION,
+	ASSIST_PAGE_CONFIRM,
+	ASSIST_PAGE_DONE
+};
+
+typedef struct {
+	gchar    *uri;
+	NAAction *action;
+	GSList   *msg;
+}
+	ImportUriStruct;
+
+/* private class data
+ */
+struct NactAssistImportClassPrivate {
+};
+
+/* private instance data
+ */
+struct NactAssistImportPrivate {
+	gboolean  dispose_has_run;
+	GSList   *results;
+};
+
+static GObjectClass *st_parent_class = NULL;
+
+static GType             register_type( void );
+static void              class_init( NactAssistImportClass *klass );
+static void              instance_init( GTypeInstance *instance, gpointer klass );
+static void              instance_dispose( GObject *application );
+static void              instance_finalize( GObject *application );
+
+static NactAssistImport *assist_new( BaseApplication *application );
+
+static gchar            *do_get_iprefs_window_id( NactWindow *window );
+static gchar            *do_get_dialog_name( BaseWindow *dialog );
+static void              on_runtime_init_dialog( BaseWindow *dialog );
+static void              runtime_init_intro( NactAssistImport *window, GtkAssistant *assistant );
+static void              runtime_init_file_selector( NactAssistImport *window, GtkAssistant *assistant );
+static void              on_file_selection_changed( GtkFileChooser *chooser, gpointer user_data );
+static gboolean          has_readable_files( GSList *uris );
+static void              on_prepare( NactAssistant *window, GtkAssistant *assistant, GtkWidget *page );
+static void              prepare_confirm( NactAssistImport *window, GtkAssistant *assistant, GtkWidget *page );
+static void              prepare_importdone( NactAssistImport *window, GtkAssistant *assistant, GtkWidget *page );
+static void              do_import( NactAssistImport *window, GtkAssistant *assistant );
+static void              free_results( GSList *list );
+
+GType
+nact_assist_import_get_type( void )
+{
+	static GType window_type = 0;
+
+	if( !window_type ){
+		window_type = register_type();
+	}
+
+	return( window_type );
+}
+
+static GType
+register_type( void )
+{
+	static const gchar *thisfn = "nact_assist_import_register_type";
+	g_debug( "%s", thisfn );
+
+	static GTypeInfo info = {
+		sizeof( NactAssistImportClass ),
+		( GBaseInitFunc ) NULL,
+		( GBaseFinalizeFunc ) NULL,
+		( GClassInitFunc ) class_init,
+		NULL,
+		NULL,
+		sizeof( NactAssistImport ),
+		0,
+		( GInstanceInitFunc ) instance_init
+	};
+
+	GType type = g_type_register_static( NACT_ASSISTANT_TYPE, "NactAssistImport", &info, 0 );
+
+	return( type );
+}
+
+static void
+class_init( NactAssistImportClass *klass )
+{
+	static const gchar *thisfn = "nact_assist_import_class_init";
+	g_debug( "%s: klass=%p", thisfn, klass );
+
+	st_parent_class = g_type_class_peek_parent( klass );
+
+	GObjectClass *object_class = G_OBJECT_CLASS( klass );
+	object_class->dispose = instance_dispose;
+	object_class->finalize = instance_finalize;
+
+	klass->private = g_new0( NactAssistImportClassPrivate, 1 );
+
+	BaseWindowClass *base_class = BASE_WINDOW_CLASS( klass );
+	base_class->get_toplevel_name = do_get_dialog_name;
+	base_class->runtime_init_toplevel = on_runtime_init_dialog;
+
+	NactWindowClass *nact_class = NACT_WINDOW_CLASS( klass );
+	nact_class->get_iprefs_window_id = do_get_iprefs_window_id;
+
+	NactAssistantClass *assist_class = NACT_ASSISTANT_CLASS( klass );
+	assist_class->on_assistant_prepare = on_prepare;
+}
+
+static void
+instance_init( GTypeInstance *instance, gpointer klass )
+{
+	static const gchar *thisfn = "nact_assist_import_instance_init";
+	g_debug( "%s: instance=%p, klass=%p", thisfn, instance, klass );
+
+	g_assert( NACT_IS_ASSIST_IMPORT( instance ));
+	NactAssistImport *self = NACT_ASSIST_IMPORT( instance );
+
+	self->private = g_new0( NactAssistImportPrivate, 1 );
+
+	self->private->dispose_has_run = FALSE;
+	self->private->results = NULL;
+}
+
+static void
+instance_dispose( GObject *window )
+{
+	static const gchar *thisfn = "nact_assist_import_instance_dispose";
+	g_debug( "%s: window=%p", thisfn, window );
+
+	g_assert( NACT_IS_ASSIST_IMPORT( window ));
+	NactAssistImport *self = NACT_ASSIST_IMPORT( window );
+
+	if( !self->private->dispose_has_run ){
+
+		self->private->dispose_has_run = TRUE;
+
+		/* chain up to the parent class */
+		G_OBJECT_CLASS( st_parent_class )->dispose( window );
+	}
+}
+
+static void
+instance_finalize( GObject *window )
+{
+	static const gchar *thisfn = "nact_assist_import_instance_finalize";
+	g_debug( "%s: window=%p", thisfn, window );
+
+	g_assert( NACT_IS_ASSIST_IMPORT( window ));
+	NactAssistImport *self = ( NactAssistImport * ) window;
+
+	free_results( self->private->results );
+
+	g_free( self->private );
+
+	/* chain call to parent class */
+	if( st_parent_class->finalize ){
+		G_OBJECT_CLASS( st_parent_class )->finalize( window );
+	}
+}
+
+static NactAssistImport *
+assist_new( BaseApplication *application )
+{
+	return( g_object_new( NACT_ASSIST_IMPORT_TYPE, PROP_WINDOW_APPLICATION_STR, application, NULL ));
+}
+
+/**
+ * Run the assistant.
+ *
+ * @main: the main window of the application.
+ */
+void
+nact_assist_import_run( NactWindow *main )
+{
+	BaseApplication *appli = BASE_APPLICATION( base_window_get_application( BASE_WINDOW( main )));
+
+	NactAssistImport *assist = assist_new( appli );
+
+	base_window_run( BASE_WINDOW( assist ));
+}
+
+static gchar *
+do_get_iprefs_window_id( NactWindow *window )
+{
+	return( g_strdup( "import-assistant" ));
+}
+
+static gchar *
+do_get_dialog_name( BaseWindow *dialog )
+{
+	return( g_strdup( "ImportAssistant" ));
+}
+
+static void
+on_runtime_init_dialog( BaseWindow *dialog )
+{
+	static const gchar *thisfn = "nact_assist_import_on_runtime_init_dialog";
+
+	/* call parent class at the very beginning */
+	if( BASE_WINDOW_CLASS( st_parent_class )->runtime_init_toplevel ){
+		BASE_WINDOW_CLASS( st_parent_class )->runtime_init_toplevel( dialog );
+	}
+
+	g_debug( "%s: dialog=%p", thisfn, dialog );
+	g_assert( NACT_IS_ASSIST_IMPORT( dialog ));
+	NactAssistImport *window = NACT_ASSIST_IMPORT( dialog );
+
+	GtkAssistant *assistant = GTK_ASSISTANT( base_window_get_toplevel_dialog( dialog ));
+
+	runtime_init_intro( window, assistant );
+	runtime_init_file_selector( window, assistant );
+}
+
+static void
+runtime_init_intro( NactAssistImport *window, GtkAssistant *assistant )
+{
+	static const gchar *thisfn = "nact_assist_import_runtime_init_intro";
+
+	GtkWidget *content = gtk_assistant_get_nth_page( assistant, ASSIST_PAGE_INTRO );
+
+	g_debug( "%s: window=%p, assistant=%p, content=%p", thisfn, window, assistant, content );
+
+	gtk_assistant_set_page_complete( assistant, content, TRUE );
+}
+
+static void
+runtime_init_file_selector( NactAssistImport *window, GtkAssistant *assistant )
+{
+	static const gchar *thisfn = "nact_assist_import_runtime_init_file_selector";
+
+	GtkWidget *chooser = gtk_assistant_get_nth_page( assistant, ASSIST_PAGE_FILES_SELECTION );
+
+	g_debug( "%s: window=%p, assistant=%p, chooser=%p", thisfn, window, assistant, chooser );
+
+	gchar *uri = nact_iprefs_get_import_folder_uri( NACT_WINDOW( window ));
+	if( uri && strlen( uri )){
+		gtk_file_chooser_set_current_folder_uri( GTK_FILE_CHOOSER( chooser ), uri );
+	}
+	g_free( uri );
+
+	nact_window_signal_connect( NACT_WINDOW( window ), G_OBJECT( chooser ), "selection-changed", G_CALLBACK( on_file_selection_changed ));
+
+	gtk_assistant_set_page_complete( assistant, chooser, FALSE );
+}
+
+static void
+on_file_selection_changed( GtkFileChooser *chooser, gpointer user_data )
+{
+	/*static const gchar *thisfn = "nact_assist_import_on_file_selection_changed";
+	g_debug( "%s: chooser=%p, user_data=%p", thisfn, chooser, user_data );*/
+
+	g_assert( NACT_IS_ASSIST_IMPORT( user_data ));
+	GtkAssistant *assistant = GTK_ASSISTANT( base_window_get_toplevel_dialog( BASE_WINDOW( user_data )));
+	gint pos = gtk_assistant_get_current_page( assistant );
+	if( pos == ASSIST_PAGE_FILES_SELECTION ){
+
+		GSList *uris = gtk_file_chooser_get_uris( chooser );
+		gboolean enabled = has_readable_files( uris );
+
+		if( enabled ){
+			gchar *folder = gtk_file_chooser_get_current_folder_uri( GTK_FILE_CHOOSER( chooser ));
+			nact_iprefs_save_import_folder_uri( NACT_WINDOW( user_data ), folder );
+			g_free( folder );
+		}
+
+		na_utils_free_string_list( uris );
+
+		GtkWidget *content = gtk_assistant_get_nth_page( assistant, pos );
+		gtk_assistant_set_page_complete( assistant, content, enabled );
+		gtk_assistant_update_buttons_state( assistant );
+	}
+}
+
+static gboolean
+has_readable_files( GSList *uris )
+{
+	static const gchar *thisfn = "nact_assist_import_has_readable_files";
+
+	GSList *iuri;
+	int readables = 0;
+
+	for( iuri = uris ; iuri ; iuri = iuri->next ){
+
+		gchar *uri = ( gchar * ) iuri->data;
+		if( !strlen( uri )){
+			continue;
+		}
+
+		GFile *file = g_file_new_for_uri( uri );
+		GError *error = NULL;
+		GFileInfo *info = g_file_query_info( file,
+				G_FILE_ATTRIBUTE_ACCESS_CAN_READ "," G_FILE_ATTRIBUTE_STANDARD_TYPE,
+				G_FILE_QUERY_INFO_NONE, NULL, &error );
+
+		if( error ){
+			g_warning( "%s: g_file_query_info error: %s", thisfn, error->message );
+			g_error_free( error );
+			g_object_unref( file );
+			continue;
+		}
+
+		GFileType type = g_file_info_get_file_type( info );
+		if( type != G_FILE_TYPE_REGULAR ){
+			g_warning( "%s: %s is not a file", thisfn, uri );
+			g_object_unref( info );
+			continue;
+		}
+
+		gboolean readable = g_file_info_get_attribute_boolean( info, G_FILE_ATTRIBUTE_ACCESS_CAN_READ );
+		if( !readable ){
+			g_warning( "%s: %s is not readable", thisfn, uri );
+			g_object_unref( info );
+			continue;
+		}
+
+		readables += 1;
+		g_object_unref( info );
+	}
+
+	return( readables > 0 );
+}
+
+static void
+on_prepare( NactAssistant *window, GtkAssistant *assistant, GtkWidget *page )
+{
+	static const gchar *thisfn = "nact_assist_import_on_prepare";
+	g_debug( "%s: window=%p, assistant=%p, page=%p", thisfn, window, assistant, page );
+
+	GtkAssistantPageType type = gtk_assistant_get_page_type( assistant, page );
+
+	switch( type ){
+		case GTK_ASSISTANT_PAGE_CONFIRM:
+			prepare_confirm( NACT_ASSIST_IMPORT( window ), assistant, page );
+			break;
+
+		case GTK_ASSISTANT_PAGE_SUMMARY:
+			prepare_importdone( NACT_ASSIST_IMPORT( window ), assistant, page );
+			break;
+
+		default:
+			break;
+	}
+}
+
+static void
+prepare_confirm( NactAssistImport *window, GtkAssistant *assistant, GtkWidget *page )
+{
+	static const gchar *thisfn = "nact_assist_import_prepare_confirm";
+	g_debug( "%s: window=%p, assistant=%p, page=%p", thisfn, window, assistant, page );
+
+	gchar *text = g_strdup( _( "<b>About to import selected files :</b>\n\n" ));
+	gchar *tmp;
+
+	GtkWidget *chooser = gtk_assistant_get_nth_page( assistant, ASSIST_PAGE_FILES_SELECTION );
+	GSList *uris = gtk_file_chooser_get_uris( GTK_FILE_CHOOSER( chooser ));
+	GSList *is;
+
+	for( is = uris ; is ; is = is->next ){
+		tmp = g_strdup_printf( "%s\t%s\n", text, ( gchar * ) is->data );
+		g_free( text );
+		text = tmp;
+	}
+
+	gtk_label_set_markup( GTK_LABEL( page ), text );
+	g_free( text );
+
+	gtk_assistant_set_page_complete( assistant, page, TRUE );
+}
+
+static void
+prepare_importdone( NactAssistImport *window, GtkAssistant *assistant, GtkWidget *page )
+{
+	static const gchar *thisfn = "nact_assist_import_prepare_importdone";
+	g_debug( "%s: window=%p, assistant=%p, page=%p", thisfn, window, assistant, page );
+
+	do_import( window, assistant );
+
+	gchar *text, *tmp;
+	GSList *is;
+
+	text = g_strdup( _( "<b>Selected files have been imported :</b>\n\n" ));
+
+	for( is = window->private->results ; is ; is = is->next ){
+
+		ImportUriStruct *str = ( ImportUriStruct * ) is->data;
+
+		GFile *file = g_file_new_for_uri( str->uri );
+		gchar *bname = g_file_get_basename( file );
+		g_object_unref( file );
+		tmp = g_strdup_printf( _( "%s\t%s\n\n" ), text, bname );
+		g_free( text );
+		text = tmp;
+		g_free( bname );
+
+		if( str->action ){
+			gchar *uuid = na_action_get_uuid( str->action );
+			gchar *label = na_action_get_label( str->action );
+			tmp = g_strdup_printf( _( "%s\t\tUUID: %s\t%s\n\n" ), text, uuid, label );
+			g_free( label );
+			g_free( uuid );
+		} else {
+			tmp = g_strdup_printf( "%s\t\t NOT OK\n\n", text );
+		}
+		g_free( text );
+		text = tmp;
+
+		GSList *im;
+		for( im = str->msg ; im ; im = im->next ){
+			tmp = g_strdup_printf( "%s\t\t%s\n", text, ( const char * ) im->data );
+			g_free( text );
+			text = tmp;
+		}
+
+		tmp = g_strdup_printf( "%s\n", text );
+		g_free( text );
+		text = tmp;
+	}
+
+	gtk_label_set_markup( GTK_LABEL( page ), text );
+	g_free( text );
+
+	gtk_assistant_set_page_complete( assistant, page, TRUE );
+	nact_assistant_set_warn_on_cancel( NACT_ASSISTANT( window ), FALSE );
+}
+
+static void
+do_import( NactAssistImport *window, GtkAssistant *assistant )
+{
+	static const gchar *thisfn = "nact_assist_import_do_import";
+	g_debug( "%s: window=%p", thisfn, window );
+
+	GtkWidget *chooser = gtk_assistant_get_nth_page( assistant, ASSIST_PAGE_FILES_SELECTION );
+	GSList *uris = gtk_file_chooser_get_uris( GTK_FILE_CHOOSER( chooser ));
+	GSList *is, *msg ;
+
+	for( is = uris ; is ; is = is->next ){
+
+		msg = NULL;
+		NAAction *action = nact_gconf_reader_import( G_OBJECT( window ), ( const gchar * ) is->data, &msg );
+		g_debug( "%s: msg has %d lines", thisfn, g_slist_length( msg ));
+
+		ImportUriStruct *str = g_new0( ImportUriStruct, 1 );
+		str->uri = g_strdup(( const gchar * ) is->data );
+		str->action = action;
+		str->msg = na_utils_duplicate_string_list( msg );
+
+		window->private->results = g_slist_prepend( window->private->results, str );
+
+		na_utils_free_string_list( msg );
+	}
+
+	na_utils_free_string_list( uris );
+}
+
+static void
+free_results( GSList *list )
+{
+	GSList *is;
+	for( is = list ; is ; is = is->next ){
+		ImportUriStruct *str = ( ImportUriStruct * ) is->data;
+		g_free( str->uri );
+		na_utils_free_string_list( str->msg );
+	}
+
+	g_slist_free( list );
+}
diff --git a/src/nact/nact-assist-import.h b/src/nact/nact-assist-import.h
new file mode 100644
index 0000000..93bea85
--- /dev/null
+++ b/src/nact/nact-assist-import.h
@@ -0,0 +1,71 @@
+/*
+ * 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 __NACT_ASSIST_IMPORT_H__
+#define __NACT_ASSIST_IMPORT_H__
+
+/*
+ * NactAssistImport class definition.
+ */
+
+#include "nact-assistant.h"
+
+G_BEGIN_DECLS
+
+#define NACT_ASSIST_IMPORT_TYPE					( nact_assist_import_get_type())
+#define NACT_ASSIST_IMPORT( object )			( G_TYPE_CHECK_INSTANCE_CAST( object, NACT_ASSIST_IMPORT_TYPE, NactAssistImport ))
+#define NACT_ASSIST_IMPORT_CLASS( klass )		( G_TYPE_CHECK_CLASS_CAST( klass, NACT_ASSIST_IMPORT_TYPE, NactAssistImportClass ))
+#define NACT_IS_ASSIST_IMPORT( object )			( G_TYPE_CHECK_INSTANCE_TYPE( object, NACT_ASSIST_IMPORT_TYPE ))
+#define NACT_IS_ASSIST_IMPORT_CLASS( klass )	( G_TYPE_CHECK_CLASS_TYPE(( klass ), NACT_ASSIST_IMPORT_TYPE ))
+#define NACT_ASSIST_IMPORT_GET_CLASS( object )	( G_TYPE_INSTANCE_GET_CLASS(( object ), NACT_ASSIST_IMPORT_TYPE, NactAssistImportClass ))
+
+typedef struct NactAssistImportPrivate NactAssistImportPrivate;
+
+typedef struct {
+	NactAssistant            parent;
+	NactAssistImportPrivate *private;
+}
+	NactAssistImport;
+
+typedef struct NactAssistImportClassPrivate NactAssistImportClassPrivate;
+
+typedef struct {
+	NactAssistantClass            parent;
+	NactAssistImportClassPrivate *private;
+}
+	NactAssistImportClass;
+
+GType nact_assist_import_get_type( void );
+
+void  nact_assist_import_run( NactWindow *main );
+
+G_END_DECLS
+
+#endif /* __NACT_ASSIST_IMPORT_H__ */
diff --git a/src/nact/nact-assistant.c b/src/nact/nact-assistant.c
new file mode 100644
index 0000000..1befe39
--- /dev/null
+++ b/src/nact/nact-assistant.c
@@ -0,0 +1,394 @@
+/*
+ * 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 <gdk/gdkkeysyms.h>
+#include <glib.h>
+#include <glib/gi18n.h>
+
+#include "nact-assistant.h"
+
+/* private class data
+ */
+struct NactAssistantClassPrivate {
+};
+
+/* private instance data
+ */
+struct NactAssistantPrivate {
+	gboolean dispose_has_run;
+	gboolean warn_on_cancel;
+};
+
+/* instance properties
+ */
+enum {
+	PROP_ASSIST_WARN_ON_CANCEL = 1
+};
+
+#define PROP_ASSIST_WARN_ON_CANCEL_STR		"nact-assist-warn-on-cancel"
+
+static GObjectClass *st_parent_class = NULL;
+
+static GType    register_type( void );
+static void     class_init( NactAssistantClass *klass );
+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 *application );
+static void     instance_finalize( GObject *application );
+
+static void     v_assistant_apply( GtkAssistant *assistant, gpointer user_data );
+static void     v_assistant_cancel( GtkAssistant *assistant, gpointer user_data );
+static void     v_assistant_close( GtkAssistant *assistant, gpointer user_data );
+static void     v_assistant_prepare( GtkAssistant *assistant, GtkWidget *page, gpointer user_data );
+
+static void     on_runtime_init_toplevel( BaseWindow *window );
+static gboolean on_key_pressed_event( GtkWidget *widget, GdkEventKey *event, gpointer user_data );
+static gboolean on_escape_key_pressed( GtkWidget *widget, GdkEventKey *event, gpointer user_data );
+static void     do_assistant_apply( NactAssistant *window, GtkAssistant *assistant );
+static void     do_assistant_cancel( NactAssistant *window, GtkAssistant *assistant );
+static void     do_assistant_close( NactAssistant *window, GtkAssistant *assistant );
+static void     do_assistant_prepare( NactAssistant *window, GtkAssistant *assistant, GtkWidget *page );
+
+GType
+nact_assistant_get_type( void )
+{
+	static GType window_type = 0;
+
+	if( !window_type ){
+		window_type = register_type();
+	}
+
+	return( window_type );
+}
+
+static GType
+register_type( void )
+{
+	static const gchar *thisfn = "nact_assistant_register_type";
+	g_debug( "%s", thisfn );
+
+	g_type_init();
+
+	static GTypeInfo info = {
+		sizeof( NactAssistantClass ),
+		( GBaseInitFunc ) NULL,
+		( GBaseFinalizeFunc ) NULL,
+		( GClassInitFunc ) class_init,
+		NULL,
+		NULL,
+		sizeof( NactAssistant ),
+		0,
+		( GInstanceInitFunc ) instance_init
+	};
+
+	GType type = g_type_register_static( NACT_WINDOW_TYPE, "NactAssistant", &info, 0 );
+
+	return( type );
+}
+
+static void
+class_init( NactAssistantClass *klass )
+{
+	static const gchar *thisfn = "nact_assistant_class_init";
+	g_debug( "%s: klass=%p", thisfn, klass );
+
+	st_parent_class = g_type_class_peek_parent( klass );
+
+	GObjectClass *object_class = G_OBJECT_CLASS( klass );
+	object_class->dispose = instance_dispose;
+	object_class->finalize = instance_finalize;
+	object_class->get_property = instance_get_property;
+	object_class->set_property = instance_set_property;
+
+	GParamSpec *spec;
+	spec = g_param_spec_boolean(
+			PROP_ASSIST_WARN_ON_CANCEL_STR,
+			PROP_ASSIST_WARN_ON_CANCEL_STR,
+			"Does the user should confirm when exiting the assistant ?", FALSE,
+			G_PARAM_STATIC_STRINGS | G_PARAM_READWRITE );
+	g_object_class_install_property( object_class, PROP_ASSIST_WARN_ON_CANCEL, spec );
+
+	klass->private = g_new0( NactAssistantClassPrivate, 1 );
+
+	BaseWindowClass *base_class = BASE_WINDOW_CLASS( klass );
+	base_class->runtime_init_toplevel = on_runtime_init_toplevel;
+
+	klass->on_escape_key_pressed = on_escape_key_pressed;
+	klass->on_assistant_apply = do_assistant_apply;
+	klass->on_assistant_close = do_assistant_close;
+	klass->on_assistant_cancel = do_assistant_cancel;
+	klass->on_assistant_prepare = do_assistant_prepare;
+}
+
+static void
+instance_init( GTypeInstance *instance, gpointer klass )
+{
+	static const gchar *thisfn = "nact_assistant_instance_init";
+	g_debug( "%s: instance=%p, klass=%p", thisfn, instance, klass );
+
+	g_assert( NACT_IS_ASSISTANT( instance ));
+	NactAssistant *self = NACT_ASSISTANT( instance );
+
+	self->private = g_new0( NactAssistantPrivate, 1 );
+
+	self->private->dispose_has_run = FALSE;
+}
+
+static void
+instance_get_property( GObject *object, guint property_id, GValue *value, GParamSpec *spec )
+{
+	g_assert( NACT_IS_ASSISTANT( object ));
+	NactAssistant *self = NACT_ASSISTANT( object );
+
+	switch( property_id ){
+		case PROP_ASSIST_WARN_ON_CANCEL:
+			g_value_set_boolean( value, self->private->warn_on_cancel );
+			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_ASSISTANT( object ));
+	NactAssistant *self = NACT_ASSISTANT( object );
+
+	switch( property_id ){
+		case PROP_ASSIST_WARN_ON_CANCEL:
+			self->private->warn_on_cancel = g_value_get_boolean( value );
+			break;
+
+		default:
+			G_OBJECT_WARN_INVALID_PROPERTY_ID( object, property_id, spec );
+			break;
+	}
+}
+
+static void
+instance_dispose( GObject *window )
+{
+	static const gchar *thisfn = "nact_assistant_instance_dispose";
+	g_debug( "%s: window=%p", thisfn, window );
+
+	g_assert( NACT_IS_ASSISTANT( window ));
+	NactAssistant *self = NACT_ASSISTANT( window );
+
+	if( !self->private->dispose_has_run ){
+
+		self->private->dispose_has_run = TRUE;
+
+		/* chain up to the parent class */
+		G_OBJECT_CLASS( st_parent_class )->dispose( window );
+	}
+}
+
+static void
+instance_finalize( GObject *window )
+{
+	static const gchar *thisfn = "nact_assistant_instance_finalize";
+	g_debug( "%s: window=%p", thisfn, window );
+
+	g_assert( NACT_IS_ASSISTANT( window ));
+	NactAssistant *self = ( NactAssistant * ) window;
+
+	g_free( self->private );
+
+	/* chain call to parent class */
+	if( st_parent_class->finalize ){
+		G_OBJECT_CLASS( st_parent_class )->finalize( window );
+	}
+}
+
+/**
+ * Set 'warn on close' property.
+ */
+
+void
+nact_assistant_set_warn_on_cancel( NactAssistant *window, gboolean warn )
+{
+	g_assert( NACT_IS_ASSISTANT( window ));
+	g_object_set( G_OBJECT( window ), PROP_ASSIST_WARN_ON_CANCEL_STR, warn, NULL );
+}
+
+static void
+v_assistant_apply( GtkAssistant *assistant, gpointer user_data )
+{
+	g_assert( NACT_IS_ASSISTANT( user_data ));
+
+	if( NACT_ASSISTANT_GET_CLASS( user_data )->on_assistant_apply ){
+		NACT_ASSISTANT_GET_CLASS( user_data )->on_assistant_apply( NACT_ASSISTANT( user_data ), assistant );
+	} else {
+		do_assistant_apply( NACT_ASSISTANT( user_data ), assistant );
+	}
+}
+
+static void
+v_assistant_cancel( GtkAssistant *assistant, gpointer user_data )
+{
+	g_assert( NACT_IS_ASSISTANT( user_data ));
+
+	if( NACT_ASSISTANT_GET_CLASS( user_data )->on_assistant_cancel ){
+		NACT_ASSISTANT_GET_CLASS( user_data )->on_assistant_cancel( NACT_ASSISTANT( user_data ), assistant );
+	} else {
+		do_assistant_cancel( NACT_ASSISTANT( user_data ), assistant );
+	}
+}
+
+static void
+v_assistant_close( GtkAssistant *assistant, gpointer user_data )
+{
+	g_assert( NACT_IS_ASSISTANT( user_data ));
+
+	if( NACT_ASSISTANT_GET_CLASS( user_data )->on_assistant_close ){
+		NACT_ASSISTANT_GET_CLASS( user_data )->on_assistant_close( NACT_ASSISTANT( user_data ), assistant );
+	} else {
+		do_assistant_close( NACT_ASSISTANT( user_data ), assistant );
+	}
+}
+
+static void
+v_assistant_prepare( GtkAssistant *assistant, GtkWidget *page, gpointer user_data )
+{
+	g_assert( NACT_IS_ASSISTANT( user_data ));
+
+	if( NACT_ASSISTANT_GET_CLASS( user_data )->on_assistant_prepare ){
+		NACT_ASSISTANT_GET_CLASS( user_data )->on_assistant_prepare( NACT_ASSISTANT( user_data ), assistant, page );
+	} else {
+		do_assistant_prepare( NACT_ASSISTANT( user_data ), assistant, page );
+	}
+}
+
+static void
+on_runtime_init_toplevel( BaseWindow *window )
+{
+	static const gchar *thisfn = "nact_assistant_on_runtime_init_toplevel";
+
+	/* call parent class at the very beginning */
+	if( BASE_WINDOW_CLASS( st_parent_class )->runtime_init_toplevel ){
+		BASE_WINDOW_CLASS( st_parent_class )->runtime_init_toplevel( window );
+	}
+
+	g_debug( "%s: window=%p", thisfn, window );
+	g_assert( NACT_IS_ASSISTANT( window ));
+
+	GtkWindow *toplevel = base_window_get_toplevel_dialog( window );
+	g_assert( GTK_IS_ASSISTANT( toplevel ));
+
+	nact_window_signal_connect( NACT_WINDOW( window ), G_OBJECT( toplevel ), "key-press-event", G_CALLBACK( on_key_pressed_event ));
+	nact_window_signal_connect( NACT_WINDOW( window ), G_OBJECT( toplevel ), "cancel", G_CALLBACK( v_assistant_cancel ));
+	nact_window_signal_connect( NACT_WINDOW( window ), G_OBJECT( toplevel ), "close", G_CALLBACK( v_assistant_close ));
+	nact_window_signal_connect( NACT_WINDOW( window ), G_OBJECT( toplevel ), "prepare", G_CALLBACK( v_assistant_prepare ));
+	nact_window_signal_connect( NACT_WINDOW( window ), G_OBJECT( toplevel ), "apply", G_CALLBACK( v_assistant_apply ));
+
+	nact_assistant_set_warn_on_cancel( NACT_ASSISTANT( window ), TRUE );
+}
+
+static gboolean
+on_key_pressed_event( GtkWidget *widget, GdkEventKey *event, gpointer user_data )
+{
+	/*static const gchar *thisfn = "nact_assistant_on_key_pressed_event";
+	g_debug( "%s: widget=%p, event=%p, user_data=%p", thisfn, widget, event, user_data );*/
+
+	gboolean stop = FALSE;
+
+	if( event->keyval == GDK_Escape ){
+		if( NACT_ASSISTANT_GET_CLASS( user_data )->on_escape_key_pressed ){
+			stop = NACT_ASSISTANT_GET_CLASS( user_data )->on_escape_key_pressed( widget, event, user_data );
+		}
+	}
+
+	return( stop );
+}
+
+static gboolean
+on_escape_key_pressed( GtkWidget *widget, GdkEventKey *event, gpointer user_data )
+{
+	static const gchar *thisfn = "nact_assistant_on_escape_key_pressed";
+	g_debug( "%s: widget=%p, event=%p, user_data=%p", thisfn, widget, event, user_data );
+
+	GtkWindow *toplevel = base_window_get_toplevel_dialog( BASE_WINDOW( user_data ));
+	v_assistant_cancel( GTK_ASSISTANT( toplevel ), user_data );
+
+	return( TRUE );
+}
+
+static void
+do_assistant_apply( NactAssistant *window, GtkAssistant *assistant )
+{
+	static const gchar *thisfn = "nact_assistant_do_assistant_apply";
+	g_debug( "%s: window=%p, assistant=%p", thisfn, window, assistant );
+}
+
+/*
+ * the 'Cancel' button is clicked
+ */
+static void
+do_assistant_cancel( NactAssistant *window, GtkAssistant *assistant )
+{
+	static const gchar *thisfn = "nact_assistant_do_assistant_cancel";
+	g_debug( "%s: window=%p, assistant=%p", thisfn, window, assistant );
+
+	gboolean ok = TRUE;
+
+	if( window->private->warn_on_cancel ){
+		gchar *first = g_strdup( _( "Are you sure you want to quit this assistant ?" ));
+		ok = base_window_yesno_dlg( BASE_WINDOW( window ), GTK_MESSAGE_QUESTION, first, NULL );
+		g_free( first );
+	}
+
+	if( ok ){
+		do_assistant_close( window, assistant );
+	}
+}
+
+static void
+do_assistant_close( NactAssistant *window, GtkAssistant *assistant )
+{
+	static const gchar *thisfn = "nact_assistant_do_assistant_close";
+	g_debug( "%s: window=%p, assistant=%p", thisfn, window, assistant );
+
+	g_object_unref( window );
+}
+
+static void
+do_assistant_prepare( NactAssistant *window, GtkAssistant *assistant, GtkWidget *page )
+{
+	static const gchar *thisfn = "nact_assistant_do_assistant_prepare";
+	g_debug( "%s: window=%p, assistant=%p, page=%p", thisfn, window, assistant, page );
+}
diff --git a/src/nact/nact-assistant.h b/src/nact/nact-assistant.h
new file mode 100644
index 0000000..ccdc312
--- /dev/null
+++ b/src/nact/nact-assistant.h
@@ -0,0 +1,81 @@
+/*
+ * 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 __NACT_ASSISTANT_H__
+#define __NACT_ASSISTANT_H__
+
+/*
+ * NactAssistant class definition.
+ *
+ * This class is derived from NactWindow class, and serves as a base
+ * class for all Nautilus Actions assistants.
+ */
+
+#include "nact-window.h"
+
+G_BEGIN_DECLS
+
+#define NACT_ASSISTANT_TYPE					( nact_assistant_get_type())
+#define NACT_ASSISTANT( object )			( G_TYPE_CHECK_INSTANCE_CAST( object, NACT_ASSISTANT_TYPE, NactAssistant ))
+#define NACT_ASSISTANT_CLASS( klass )		( G_TYPE_CHECK_CLASS_CAST( klass, NACT_ASSISTANT_TYPE, NactAssistantClass ))
+#define NACT_IS_ASSISTANT( object )			( G_TYPE_CHECK_INSTANCE_TYPE( object, NACT_ASSISTANT_TYPE ))
+#define NACT_IS_ASSISTANT_CLASS( klass )	( G_TYPE_CHECK_CLASS_TYPE(( klass ), NACT_ASSISTANT_TYPE ))
+#define NACT_ASSISTANT_GET_CLASS( object )	( G_TYPE_INSTANCE_GET_CLASS(( object ), NACT_ASSISTANT_TYPE, NactAssistantClass ))
+
+typedef struct NactAssistantPrivate NactAssistantPrivate;
+
+typedef struct {
+	NactWindow            parent;
+	NactAssistantPrivate *private;
+}
+	NactAssistant;
+
+typedef struct NactAssistantClassPrivate NactAssistantClassPrivate;
+
+typedef struct {
+	NactWindowClass            parent;
+	NactAssistantClassPrivate *private;
+
+	/* api */
+	gboolean ( *on_escape_key_pressed )( GtkWidget *widget, GdkEventKey *event, gpointer data );
+	void     ( *on_assistant_apply )   ( NactAssistant *window, GtkAssistant *assistant );
+	void     ( *on_assistant_cancel )  ( NactAssistant *window, GtkAssistant *assistant );
+	void     ( *on_assistant_close )   ( NactAssistant *window, GtkAssistant *assistant );
+	void     ( *on_assistant_prepare ) ( NactAssistant *window, GtkAssistant *assistant, GtkWidget *page );
+}
+	NactAssistantClass;
+
+GType nact_assistant_get_type( void );
+
+void  nact_assistant_set_warn_on_cancel( NactAssistant *window, gboolean warn );
+
+G_END_DECLS
+
+#endif /* __NACT_ASSISTANT_H__ */
diff --git a/src/nact/nact-gconf-schema.h b/src/nact/nact-gconf-keys.h
similarity index 54%
rename from src/nact/nact-gconf-schema.h
rename to src/nact/nact-gconf-keys.h
index 3cac6db..af74b86 100644
--- a/src/nact/nact-gconf-schema.h
+++ b/src/nact/nact-gconf-keys.h
@@ -28,64 +28,41 @@
  *   ... and many others (see AUTHORS)
  */
 
-#ifndef __NACT_GCONF_SCHEMA_H__
-#define __NACT_GCONF_SCHEMA_H__
-
-/*
- * NactGConfSchema class definition.
- *
- * This is the base class for importing into and exporting from GConf
- * storage subsystem.
- */
+#ifndef __NACT_GCONF_KEYS_H__
+#define __NACT_GCONF_KEYS_H__
 
 #include <glib-object.h>
 
-#include <common/na-action.h>
-#include <common/na-action-profile.h>
-#include <common/na-gconf-keys.h>
-#include <common/na-utils.h>
-
 G_BEGIN_DECLS
 
-#define NACT_GCONF_SCHEMA_TYPE					( nact_gconf_schema_get_type())
-#define NACT_GCONF_SCHEMA( object )				( G_TYPE_CHECK_INSTANCE_CAST( object, NACT_GCONF_SCHEMA_TYPE, NactGConfSchema ))
-#define NACT_GCONF_SCHEMA_CLASS( klass )		( G_TYPE_CHECK_CLASS_CAST( klass, NACT_GCONF_SCHEMA_TYPE, NactGConfSchemaClass ))
-#define NACT_IS_GCONF_SCHEMA( object )			( G_TYPE_CHECK_INSTANCE_TYPE( object, NACT_GCONF_SCHEMA_TYPE ))
-#define NACT_IS_GCONF_SCHEMA_CLASS( klass )		( G_TYPE_CHECK_CLASS_TYPE(( klass ), NACT_GCONF_SCHEMA_TYPE ))
-#define NACT_GCONF_SCHEMA_GET_CLASS( object )	( G_TYPE_INSTANCE_GET_CLASS(( object ), NACT_GCONF_SCHEMA_TYPE, NactGConfSchemaClass ))
-
-typedef struct NactGConfSchemaPrivate NactGConfSchemaPrivate;
-
-typedef struct {
-	GObject                 parent;
-	NactGConfSchemaPrivate *private;
-}
-	NactGConfSchema;
-
-typedef struct NactGConfSchemaClassPrivate NactGConfSchemaClassPrivate;
-
-typedef struct {
-	GObjectClass                 parent;
-	NactGConfSchemaClassPrivate *private;
-}
-	NactGConfSchemaClass;
-
-/* GConf XML element names
+/* XML element names (GConf style)
  */
 #define NACT_GCONF_XML_ROOT						"gconfschemafile"
 #define NACT_GCONF_XML_SCHEMA_LIST				"schemalist"
 #define NACT_GCONF_XML_SCHEMA_ENTRY				"schema"
-#define NACT_GCONF_XML_SCHEMA_KEY				"key"
 #define NACT_GCONF_XML_SCHEMA_APPLYTO			"applyto"
-#define NACT_GCONF_XML_SCHEMA_TYPE				"type"
 #define NACT_GCONF_XML_SCHEMA_LOCALE			"locale"
 #define NACT_GCONF_XML_SCHEMA_DFT				"default"
+
+/* Previous used keys
+ *
+ * Up to v 1.10, export used to contain a full schema description,
+ * while import only checked for applyto keys (along with locale
+ * and default)
+ *
+ * Starting with 1.11, export only contains required keys (applyto,
+ * default and locale) ; import of course accept all previous keys
+ * without warning
+ */
+#define NACT_GCONF_XML_SCHEMA_KEY				"key"
+#define NACT_GCONF_XML_SCHEMA_OWNER				"owner"
+#define NACT_GCONF_XML_SCHEMA_TYPE				"type"
 #define NACT_GCONF_XML_SCHEMA_LIST_TYPE			"list_type"
+#define NACT_GCONF_XML_SCHEMA_SHORT				"short"
+#define NACT_GCONF_XML_SCHEMA_LONG				"long"
 
 #define NACT_GCONF_SCHEMA_PREFIX				"/schemas"
 
-GType nact_gconf_schema_get_type( void );
-
 G_END_DECLS
 
-#endif /* __NACT_GCONF_SCHEMA_H__ */
+#endif /* __NACT_GCONF_KEYS_H__ */
diff --git a/src/nact/nact-gconf-reader.c b/src/nact/nact-gconf-reader.c
new file mode 100644
index 0000000..4219053
--- /dev/null
+++ b/src/nact/nact-gconf-reader.c
@@ -0,0 +1,872 @@
+/*
+ * 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 <glib/gi18n.h>
+#include <libxml/tree.h>
+#include <stdarg.h>
+#include <string.h>
+#include <uuid/uuid.h>
+
+#include <common/na-gconf-keys.h>
+#include <common/na-pivot.h>
+#include <common/na-utils.h>
+
+#include "nact-gconf-keys.h"
+#include "nact-gconf-reader.h"
+#include "nact-assistant.h"
+
+/* private class data
+ */
+struct NactGConfReaderClassPrivate {
+};
+
+/* private instance data
+ * we allocate one instance for each imported file, and each imported
+ * file should contain one and only one action
+ * follow here the import flow
+ */
+struct NactGConfReaderPrivate {
+	gboolean         dispose_has_run;
+	NAPivot         *pivot;
+	NAAction        *action;			/* the action that we will return, or NULL */
+	GSList          *messages;
+	gboolean         uuid_set;			/* set at first uuid, then checked against */
+
+	/* followinf values are reset at each schema node
+	 */
+	NAActionProfile *profile;			/* profile */
+	gboolean         locale_waited;		/* does this require a locale ? */
+	gboolean         profile_waited;	/* does this entry apply to a profile ? */
+	gchar           *entry;
+	gchar           *value;				/* found value */
+};
+
+typedef struct {
+	char    *entry;
+	gboolean entry_found;
+	gboolean locale_waited;
+	gboolean profile_waited;
+}
+	GConfReaderStruct;
+
+static GConfReaderStruct reader_str[] = {
+	{ ACTION_VERSION_ENTRY      , FALSE, FALSE, FALSE },
+	{ ACTION_LABEL_ENTRY        , FALSE,  TRUE, FALSE },
+	{ ACTION_TOOLTIP_ENTRY      , FALSE,  TRUE, FALSE },
+	{ ACTION_ICON_ENTRY         , FALSE, FALSE, FALSE },
+	{ ACTION_PROFILE_LABEL_ENTRY, FALSE,  TRUE,  TRUE },
+	{ ACTION_PATH_ENTRY         , FALSE, FALSE,  TRUE },
+	{ ACTION_PARAMETERS_ENTRY   , FALSE, FALSE,  TRUE },
+	{ ACTION_BASENAMES_ENTRY    , FALSE, FALSE,  TRUE },
+	{ ACTION_MATCHCASE_ENTRY    , FALSE, FALSE,  TRUE },
+	{ ACTION_ISFILE_ENTRY       , FALSE, FALSE,  TRUE },
+	{ ACTION_ISDIR_ENTRY        , FALSE, FALSE,  TRUE },
+	{ ACTION_MULTIPLE_ENTRY     , FALSE, FALSE,  TRUE },
+	{ ACTION_MIMETYPES_ENTRY    , FALSE, FALSE,  TRUE },
+	{ ACTION_SCHEMES_ENTRY      , FALSE, FALSE,  TRUE },
+	{                       NULL, FALSE, FALSE,  TRUE },
+};
+
+#define ERR_UNABLE_PARSE_XML_FILE	_( "Unable to parse XML file: %s." )
+#define ERR_ROOT_ELEMENT			_( "Invalid XML root element: waited for '%s', found '%s' at line %d." )
+#define ERR_WAITED_IGNORED_NODE		_( "Waited for '%s' node, found (ignored) '%s' at line %d." )
+#define ERR_IGNORED_NODE			_( "Unexpected (ignored) '%s' node found at line %d." )
+#define ERR_IGNORED_SCHEMA			_( "Schema is ignored at line %d." )
+#define ERR_UNEXPECTED_NODE			_( "Unexpected '%s' node found at line %d." )
+#define ERR_UNEXPECTED_ENTRY		_( "Unexpected '%s' entry found at line %d." )
+#define ERR_NODE_NOT_FOUND			_( "Mandatory node '%s' not found." )
+#define ERR_NO_VALUE_FOUND			_( "No value found." )
+#define ERR_INVALID_UUID			_( "Invalid UUID: waited for %s, found %s at line %d." )
+#define ERR_INVALID_KEY_PREFIX		_( "Invalid content: waited for %s prefix, found %s at line %d." )
+#define ERR_NOT_AN_UUID				_( "Invalid UUID %s found at line %d." )
+#define ERR_UUID_ALREADY_EXISTS		_( "Already existing UUID %s at line %d." )
+#define ERR_VALUE_ALREADY_SET		_( "Value '%s' already set: new value ignored at line %d." )
+
+static GObjectClass *st_parent_class = NULL;
+
+static GType            register_type( void );
+static void             class_init( NactGConfReaderClass *klass );
+static void             instance_init( GTypeInstance *instance, gpointer klass );
+static void             instance_dispose( GObject *object );
+static void             instance_finalize( GObject *object );
+
+static NactGConfReader *gconf_reader_new( void );
+static void             gconf_reader_parse_schemalist( NactGConfReader *reader, xmlNode *schemalist );
+static gboolean         gconf_reader_parse_schema( NactGConfReader *reader, xmlNode *schema );
+static gboolean         gconf_reader_parse_applyto( NactGConfReader *reader, xmlNode *node );
+static gboolean         gconf_reader_check_for_entry( NactGConfReader *reader, xmlNode *node, const char *entry );
+static gboolean         gconf_reader_parse_locale( NactGConfReader *reader, xmlNode *node );
+static void             gconf_reader_parse_default( NactGConfReader *reader, xmlNode *node );
+static void             apply_schema_value( NactGConfReader *reader );
+static void             add_message( NactGConfReader *reader, const gchar *format, ... );
+static int              strxcmp( const xmlChar *a, const char *b );
+static gchar           *get_uuid_from_key( NactGConfReader *reader, const gchar *key, guint line );
+static gboolean         is_uuid_valid( const gchar *uuid );
+static gchar           *get_profile_name_from_key( const gchar *key, const gchar *uuid );
+static gchar           *get_entry_from_key( const gchar *key );
+static void             free_schema_value( NactGConfReader *reader );
+
+GType
+nact_gconf_reader_get_type( void )
+{
+	static GType object_type = 0;
+
+	if( !object_type ){
+		object_type = register_type();
+	}
+
+	return( object_type );
+}
+
+static GType
+register_type( void )
+{
+	static GTypeInfo info = {
+		sizeof( NactGConfReaderClass ),
+		NULL,
+		NULL,
+		( GClassInitFunc ) class_init,
+		NULL,
+		NULL,
+		sizeof( NactGConfReader ),
+		0,
+		( GInstanceInitFunc ) instance_init
+	};
+
+	GType type = g_type_register_static( G_TYPE_OBJECT, "NactGConfReader", &info, 0 );
+
+	return( type );
+}
+
+static void
+class_init( NactGConfReaderClass *klass )
+{
+	static const gchar *thisfn = "nact_gconf_reader_class_init";
+	g_debug( "%s: klass=%p", thisfn, klass );
+
+	st_parent_class = g_type_class_peek_parent( klass );
+
+	GObjectClass *object_class = G_OBJECT_CLASS( klass );
+	object_class->dispose = instance_dispose;
+	object_class->finalize = instance_finalize;
+
+	klass->private = g_new0( NactGConfReaderClassPrivate, 1 );
+}
+
+static void
+instance_init( GTypeInstance *instance, gpointer klass )
+{
+	static const gchar *thisfn = "nact_gconf_reader_instance_init";
+	g_debug( "%s: instance=%p, klass=%p", thisfn, instance, klass );
+
+	g_assert( NACT_IS_GCONF_READER( instance ));
+	NactGConfReader *self = NACT_GCONF_READER( instance );
+
+	self->private = g_new0( NactGConfReaderPrivate, 1 );
+
+	self->private->dispose_has_run = FALSE;
+	self->private->action = NULL;
+	self->private->messages = NULL;
+	self->private->uuid_set = FALSE;
+	self->private->profile = NULL;
+	self->private->locale_waited = FALSE;
+	self->private->entry = NULL;
+	self->private->value = NULL;
+}
+
+static void
+instance_dispose( GObject *object )
+{
+	g_assert( NACT_IS_GCONF_READER( object ));
+	NactGConfReader *self = NACT_GCONF_READER( object );
+
+	if( !self->private->dispose_has_run ){
+
+		self->private->dispose_has_run = TRUE;
+
+		if( self->private->action ){
+			g_assert( NA_IS_ACTION( self->private->action ));
+			g_object_unref( self->private->action );
+		}
+
+		/* chain up to the parent class */
+		G_OBJECT_CLASS( st_parent_class )->dispose( object );
+	}
+}
+
+static void
+instance_finalize( GObject *object )
+{
+	g_assert( NACT_IS_GCONF_READER( object ));
+	NactGConfReader *self = NACT_GCONF_READER( object );
+
+	na_utils_free_string_list( self->private->messages );
+	free_schema_value( self );
+
+	g_free( self->private );
+
+	/* chain call to parent class */
+	if( st_parent_class->finalize ){
+		G_OBJECT_CLASS( st_parent_class )->finalize( object );
+	}
+}
+
+static NactGConfReader *
+gconf_reader_new( void )
+{
+	return( g_object_new( NACT_GCONF_READER_TYPE, NULL ));
+}
+
+/**
+ * Import the specified file as an NAAction XML description.
+ */
+NAAction *
+nact_gconf_reader_import( GObject *window, const gchar *uri, GSList **msg )
+{
+	static const gchar *thisfn = "nact_gconf_reader_import";
+	g_debug( "%s: window=%p, uri=%s, msg=%p", thisfn, window, uri, msg );
+
+	NAAction *action = NULL;
+	gboolean found = FALSE;
+
+	NactGConfReader *reader = gconf_reader_new();
+
+	g_assert( NACT_IS_ASSISTANT( window ));
+	reader->private->pivot = NA_PIVOT( nact_window_get_pivot( NACT_WINDOW( window )));
+
+	xmlDoc *doc = xmlParseFile( uri );
+	xmlNode *iter;
+
+	if( !doc ){
+		xmlErrorPtr error = xmlGetLastError();
+		add_message( reader,
+				ERR_UNABLE_PARSE_XML_FILE, error->message );
+		xmlResetError( error );
+
+	} else {
+		xmlNode *root_node = xmlDocGetRootElement( doc );
+
+		if( strxcmp( root_node->name, NACT_GCONF_XML_ROOT )){
+			add_message( reader,
+					ERR_ROOT_ELEMENT,
+					NACT_GCONF_XML_ROOT, ( const char * ) root_node->name, root_node->line );
+
+		} else {
+			for( iter = root_node->children ; iter ; iter = iter->next ){
+
+				if( iter->type != XML_ELEMENT_NODE ){
+					continue;
+				}
+
+				if( strxcmp( iter->name, NACT_GCONF_XML_SCHEMA_LIST )){
+					add_message( reader,
+							ERR_WAITED_IGNORED_NODE,
+							NACT_GCONF_XML_SCHEMA_LIST, ( const char * ) iter->name, iter->line );
+					continue;
+				}
+
+				if( found ){
+					add_message( reader, ERR_IGNORED_NODE, ( const char * ) iter->name, iter->line );
+					continue;
+				}
+
+				found = TRUE;
+				gconf_reader_parse_schemalist( reader, iter );
+			}
+		}
+
+		xmlFreeDoc (doc);
+	}
+
+	xmlCleanupParser();
+
+	g_debug( "%s: messages has %d lines", thisfn, g_slist_length( reader->private->messages ));
+	*msg = na_utils_duplicate_string_list( reader->private->messages );
+	g_debug( "%s: after", thisfn );
+
+	if( reader->private->action ){
+		g_assert( NA_IS_ACTION( reader->private->action ));
+		action = g_object_ref( reader->private->action );
+	}
+	g_object_unref( reader );
+
+	return( action );
+}
+
+/*
+ * iter points to the 'schemalist' node (already checked)
+ * children should only be 'schema' nodes ; other nodes are warned,
+ * but not fatal
+ */
+static void
+gconf_reader_parse_schemalist( NactGConfReader *reader, xmlNode *schema )
+{
+	static const gchar *thisfn = "gconf_reader_parse_schemalist";
+	g_debug( "%s: reader=%p, schema=%p", thisfn, reader, schema );
+
+	xmlNode *iter;
+
+	reader->private->action = na_action_new( NULL );
+	reader->private->uuid_set = FALSE;
+
+	for( iter = schema->children ; iter ; iter = iter->next ){
+
+		if( iter->type != XML_ELEMENT_NODE ){
+			continue;
+		}
+
+		if( strxcmp( iter->name, NACT_GCONF_XML_SCHEMA_ENTRY )){
+			add_message( reader,
+					ERR_WAITED_IGNORED_NODE,
+					NACT_GCONF_XML_SCHEMA_ENTRY, ( const char * ) iter->name, iter->line );
+			continue;
+		}
+
+		if( !gconf_reader_parse_schema( reader, iter )){
+			add_message( reader, ERR_IGNORED_SCHEMA, iter->line );
+		}
+	}
+
+	gboolean ok = FALSE;
+
+	if( reader->private->uuid_set ){
+		gchar *label = na_action_get_label( reader->private->action );
+		ok = ( label && strlen( label ));
+		g_debug( "%s: action=%p, label=%s, ok=%s", thisfn, reader->private->action, label, ok ? "True":"False" );
+		g_free( label );
+	}
+
+	if( !ok ){
+		g_object_unref( reader->private->action );
+		reader->private->action = NULL;
+	}
+}
+
+/*
+ * iter points to a 'schema' node (already checked)
+ *
+ * we can have
+ * - schema
+ *   +- locale
+ *      +- default
+ * or
+ * - schema
+ *   +- default
+ * depending of the key's entry.
+ *
+ * data found in schema node is imported into the action if and only if
+ * the whole node is correct ; else the error is warned (but not fatal)
+ *
+ * note that versions previous to 1.11 used to export a full schema
+ * we have so always a 'locale' even if the value is in 'default'
+ *
+ * note also that versions previous to 1.11 used to export profile label
+ * as if it were not localized (which is a bug, though not signaled)
+ * so if the profile label is not found inside of locale node, we search
+ * for it outside
+ *
+ * Returns TRUE if the node has been successfully parsed, FALSE else.
+ */
+static gboolean
+gconf_reader_parse_schema( NactGConfReader *reader, xmlNode *schema )
+{
+	static const gchar *thisfn = "gconf_reader_parse_schema";
+	g_debug( "%s: reader=%p, schema=%p", thisfn, reader, schema );
+
+	xmlNode *iter;
+	gboolean ret = TRUE;
+	gboolean applyto = FALSE;
+	gboolean pre_v1_11 = FALSE;
+
+	free_schema_value( reader );
+
+	/* check for the children of the 'schema' node
+	 * we must only found known keys
+	 */
+	for( iter = schema->children ; iter ; iter = iter->next ){
+
+		if( iter->type != XML_ELEMENT_NODE ){
+			continue;
+		}
+
+		if( strxcmp( iter->name, NACT_GCONF_XML_SCHEMA_KEY ) &&
+			strxcmp( iter->name, NACT_GCONF_XML_SCHEMA_APPLYTO ) &&
+			strxcmp( iter->name, NACT_GCONF_XML_SCHEMA_OWNER ) &&
+			strxcmp( iter->name, NACT_GCONF_XML_SCHEMA_TYPE ) &&
+			strxcmp( iter->name, NACT_GCONF_XML_SCHEMA_LIST_TYPE ) &&
+			strxcmp( iter->name, NACT_GCONF_XML_SCHEMA_LOCALE ) &&
+			strxcmp( iter->name, NACT_GCONF_XML_SCHEMA_DFT )){
+
+				add_message( reader, ERR_UNEXPECTED_NODE, ( const char * ) iter->name, iter->line );
+				ret = FALSE;
+				continue;
+		}
+
+		if( !strxcmp( iter->name, NACT_GCONF_XML_SCHEMA_KEY ) ||
+			!strxcmp( iter->name, NACT_GCONF_XML_SCHEMA_OWNER ) ||
+			!strxcmp( iter->name, NACT_GCONF_XML_SCHEMA_TYPE ) ||
+			!strxcmp( iter->name, NACT_GCONF_XML_SCHEMA_LIST_TYPE )){
+
+				pre_v1_11 = TRUE;
+				continue;
+		}
+	}
+
+	if( !ret ){
+		return( ret );
+	}
+
+	g_debug( "%s: pre_v1_11=%s", thisfn, pre_v1_11 ? "True":"False" );
+
+	/* check for an 'applyto' node
+	 * is mandatory
+	 * will determine if we are waiting for locale+default or only default
+	 */
+	reader->private->locale_waited = FALSE;
+
+	for( iter = schema->children ; iter ; iter = iter->next ){
+
+		if( iter->type != XML_ELEMENT_NODE ){
+			continue;
+		}
+
+		if( !strxcmp( iter->name, NACT_GCONF_XML_SCHEMA_APPLYTO )){
+
+			if( applyto ){
+				add_message( reader, ERR_UNEXPECTED_NODE, ( const char * ) iter->name, iter->line );
+				ret = FALSE;
+			}
+
+			applyto = TRUE;
+			ret = gconf_reader_parse_applyto( reader, iter );
+		}
+	}
+
+	if( !applyto ){
+		g_assert( ret );
+		add_message( reader, ERR_NODE_NOT_FOUND, NACT_GCONF_XML_SCHEMA_APPLYTO );
+		ret = FALSE;
+	}
+
+	if( !ret ){
+		return( ret );
+	}
+
+	/* check for and parse locale+default or locale depending of the
+	 * previously found 'applyto' node
+	 */
+	gboolean locale_found = FALSE;
+	gboolean default_found = FALSE;
+
+	for( iter = schema->children ; iter ; iter = iter->next ){
+
+		if( iter->type != XML_ELEMENT_NODE ){
+			continue;
+		}
+
+		if( !strxcmp( iter->name, NACT_GCONF_XML_SCHEMA_LOCALE )){
+
+			if( locale_found ){
+				add_message( reader, ERR_UNEXPECTED_NODE, ( const char * ) iter->name, iter->line );
+				ret = FALSE;
+
+			} else {
+				locale_found = TRUE;
+				if( reader->private->locale_waited ){
+					ret = gconf_reader_parse_locale( reader, iter );
+				}
+			}
+
+		} else if( !strxcmp( iter->name, NACT_GCONF_XML_SCHEMA_DFT )){
+
+			if( default_found ){
+				add_message( reader, ERR_UNEXPECTED_NODE, ( const char * ) iter->name, iter->line );
+				ret = FALSE;
+
+			} else {
+				default_found = TRUE;
+				if( !reader->private->locale_waited ||
+						( pre_v1_11 && !strcmp( reader->private->entry, ACTION_PROFILE_LABEL_ENTRY ))){
+					gconf_reader_parse_default( reader, iter );
+				}
+			}
+		}
+	}
+
+	if( !reader->private->value ){
+		g_assert( ret );
+		add_message( reader, ERR_NO_VALUE_FOUND );
+		ret = FALSE;
+	}
+
+	if( ret ){
+		apply_schema_value( reader );
+	}
+
+	return( ret );
+}
+
+static gboolean
+gconf_reader_parse_applyto( NactGConfReader *reader, xmlNode *node )
+{
+	static const gchar *thisfn = "gconf_reader_parse_applyto";
+	g_debug( "%s: reader=%p, node=%p", thisfn, reader, node );
+
+	gboolean ret = TRUE;
+
+	xmlChar *text = xmlNodeGetContent( node );
+	gchar *uuid = get_uuid_from_key( reader, ( const gchar * ) text, node->line );
+	gchar *profile = NULL;
+	gchar *entry = NULL;
+
+	if( !uuid ){
+		ret = FALSE;
+	}
+
+	if( ret ){
+		if( !reader->private->uuid_set ){
+
+			GObject *object = na_pivot_get_action( reader->private->pivot, uuid );
+			if( object ){
+				add_message( reader, ERR_UUID_ALREADY_EXISTS, uuid );
+				ret = FALSE;
+
+			} else {
+				na_action_set_uuid( reader->private->action, uuid );
+				reader->private->uuid_set = TRUE;
+			}
+
+		} else {
+			gchar *ref = na_action_get_uuid( reader->private->action );
+			if( strcmp(( const char * ) uuid, ( const char * ) ref )){
+				add_message( reader, ERR_INVALID_UUID, ref, uuid, node->line );
+				ret = FALSE;
+			}
+			g_free( ref );
+		}
+	}
+
+	if( ret ){
+		profile = get_profile_name_from_key(( const gchar * ) text, uuid );
+
+		if( profile ){
+			reader->private->profile = NA_ACTION_PROFILE( na_action_get_profile( reader->private->action, profile ));
+
+			if( !reader->private->profile ){
+				reader->private->profile = na_action_profile_new( NA_OBJECT( reader->private->action ), profile );
+				na_action_add_profile( reader->private->action, NA_OBJECT( reader->private->profile ));
+			}
+		}
+
+		entry = get_entry_from_key(( const gchar * ) text );
+		g_assert( entry && strlen( entry ));
+
+		ret = gconf_reader_check_for_entry( reader, node, entry );
+	}
+
+	g_free( entry );
+	g_free( profile );
+	g_free( uuid );
+	xmlFree( text );
+
+	return( ret );
+}
+
+static gboolean
+gconf_reader_check_for_entry( NactGConfReader *reader, xmlNode *node, const char *entry )
+{
+	static const gchar *thisfn = "gconf_reader_check_for_entry";
+	g_debug( "%s: reader=%p, node=%p, entry=%s", thisfn, reader, node, entry );
+
+	gboolean ret = TRUE;
+	gboolean found = FALSE;
+	int i;
+
+	for( i=0 ; reader_str[i].entry ; ++i ){
+		if( !strcmp( reader_str[i].entry, entry )){
+			found = TRUE;
+
+			if( reader_str[i].entry_found ){
+				add_message( reader, ERR_UNEXPECTED_ENTRY, entry, node->line );
+				ret = FALSE;
+
+			} else {
+				reader_str[i].entry_found = TRUE;
+				reader->private->entry  = g_strdup( reader_str[i].entry );
+				reader->private->locale_waited = reader_str[i].locale_waited;
+				reader->private->profile_waited = reader_str[i].profile_waited;
+			}
+		}
+	}
+
+	if( !found ){
+		g_assert( ret );
+		add_message( reader, ERR_UNEXPECTED_ENTRY, entry, node->line );
+		ret = FALSE;
+	}
+
+	return( ret );
+}
+
+/*
+ * we only parse 'locale' when we are waiting for a value inside of
+ * this node
+ */
+static gboolean
+gconf_reader_parse_locale( NactGConfReader *reader, xmlNode *locale )
+{
+	static const gchar *thisfn = "gconf_reader_parse_locale";
+	g_debug( "%s: reader=%p, locale=%p", thisfn, reader, locale );
+
+	gboolean ret = TRUE;
+	xmlNode *iter;
+	gboolean default_found = FALSE;
+
+	for( iter = locale->children ; iter ; iter = iter->next ){
+
+		if( iter->type != XML_ELEMENT_NODE ){
+			continue;
+		}
+
+		if( strxcmp( iter->name, NACT_GCONF_XML_SCHEMA_SHORT ) &&
+			strxcmp( iter->name, NACT_GCONF_XML_SCHEMA_LONG ) &&
+			strxcmp( iter->name, NACT_GCONF_XML_SCHEMA_DFT )){
+
+				add_message( reader, ERR_UNEXPECTED_NODE, ( const char * ) iter->name, iter->line );
+				ret = FALSE;
+				continue;
+		}
+
+		if( !strxcmp( iter->name, NACT_GCONF_XML_SCHEMA_SHORT ) ||
+			!strxcmp( iter->name, NACT_GCONF_XML_SCHEMA_LONG )){
+				continue;
+		}
+
+		if( default_found ){
+			add_message( reader, ERR_UNEXPECTED_NODE, ( const char * ) iter->name, iter->line );
+			ret = FALSE;
+			continue;
+		}
+
+		g_assert( ret );
+		default_found = TRUE;
+		gconf_reader_parse_default( reader, iter );
+	}
+
+	return( ret );
+}
+
+static void
+gconf_reader_parse_default( NactGConfReader *reader, xmlNode *node )
+{
+	if( reader->private->value ){
+		add_message( reader, ERR_VALUE_ALREADY_SET, reader->private->value, node->line );
+		return;
+	}
+
+	xmlChar *text = xmlNodeGetContent( node );
+	reader->private->value = g_strdup(( const gchar * ) text );
+	xmlFree( text );
+	/*g_debug( "gconf_reader_parse_default: set value=%s", reader->private->value );*/
+}
+
+static void
+apply_schema_value( NactGConfReader *reader )
+{
+	static const gchar *thisfn = "gconf_reader_apply_schema_value";
+	g_debug( "%s: reader=%p, entry=%s, value=%s", thisfn, reader, reader->private->entry, reader->private->value );
+
+	GSList *list;
+
+	if( reader->private->entry && strlen( reader->private->entry )){
+		if( !strcmp( reader->private->entry, ACTION_VERSION_ENTRY )){
+			na_action_set_version( reader->private->action, reader->private->value );
+
+		} else if( !strcmp( reader->private->entry, ACTION_LABEL_ENTRY )){
+			na_action_set_label( reader->private->action, reader->private->value );
+
+		} else if( !strcmp( reader->private->entry, ACTION_TOOLTIP_ENTRY )){
+			na_action_set_tooltip( reader->private->action, reader->private->value );
+
+		} else if( !strcmp( reader->private->entry, ACTION_ICON_ENTRY )){
+			na_action_set_icon( reader->private->action, reader->private->value );
+
+		} else if( !strcmp( reader->private->entry, ACTION_PROFILE_LABEL_ENTRY )){
+			na_action_profile_set_label( reader->private->profile, reader->private->value );
+
+		} else if( !strcmp( reader->private->entry, ACTION_PATH_ENTRY )){
+			na_action_profile_set_path( reader->private->profile, reader->private->value );
+
+		} else if( !strcmp( reader->private->entry, ACTION_PARAMETERS_ENTRY )){
+			na_action_profile_set_parameters( reader->private->profile, reader->private->value );
+
+		} else if( !strcmp( reader->private->entry, ACTION_BASENAMES_ENTRY )){
+			list = na_utils_schema_to_gslist( reader->private->entry );
+			na_action_profile_set_basenames( reader->private->profile, list );
+			na_utils_free_string_list( list );
+
+		} else if( !strcmp( reader->private->entry, ACTION_MATCHCASE_ENTRY )){
+			na_action_profile_set_matchcase( reader->private->profile, na_utils_schema_to_boolean( reader->private->entry, TRUE ));
+
+		} else if( !strcmp( reader->private->entry, ACTION_MULTIPLE_ENTRY )){
+			na_action_profile_set_multiple( reader->private->profile, na_utils_schema_to_boolean( reader->private->entry, FALSE ));
+
+		} else if( !strcmp( reader->private->entry, ACTION_ISFILE_ENTRY )){
+			na_action_profile_set_isfile( reader->private->profile, na_utils_schema_to_boolean( reader->private->entry, TRUE ));
+
+		} else if( !strcmp( reader->private->entry, ACTION_ISDIR_ENTRY )){
+			na_action_profile_set_isdir( reader->private->profile, na_utils_schema_to_boolean( reader->private->entry, FALSE ));
+
+		} else if( !strcmp( reader->private->entry, ACTION_MIMETYPES_ENTRY )){
+			list = na_utils_schema_to_gslist( reader->private->entry );
+			na_action_profile_set_mimetypes( reader->private->profile, list );
+			na_utils_free_string_list( list );
+
+		} else if( !strcmp( reader->private->entry, ACTION_SCHEMES_ENTRY )){
+			list = na_utils_schema_to_gslist( reader->private->entry );
+			na_action_profile_set_schemes( reader->private->profile, list );
+			na_utils_free_string_list( list );
+
+		} else {
+			g_assert_not_reached();
+		}
+	}
+}
+
+static void
+add_message( NactGConfReader *reader, const gchar *format, ... )
+{
+	g_debug( "nact_gconf_reader_add_message: format=%s", format );
+
+	va_list va;
+	va_start( va, format );
+	gchar *tmp = g_strdup_vprintf( format, va );
+	va_end( va );
+	reader->private->messages = g_slist_append( reader->private->messages, tmp );
+}
+
+/*
+ * note that up to v 1.10 included, key check was made via a call to
+ * g_ascii_strncasecmp, which was doubly wrong:
+ * - because XML is case sensitive by definition
+ * - because this did not detect a key longer that the reference.
+ */
+static int
+strxcmp( const xmlChar *a, const char *b )
+{
+	xmlChar *xb = xmlCharStrdup( b );
+	int ret = xmlStrcmp( a, xb );
+	xmlFree( xb );
+	return( ret );
+}
+
+static gchar *
+get_uuid_from_key( NactGConfReader *reader, const gchar *key, guint line )
+{
+	if( !g_str_has_prefix( key, NA_GCONF_CONFIG_PATH )){
+		add_message( reader,
+				ERR_INVALID_KEY_PREFIX, NA_GCONF_CONFIG_PATH, key, line );
+		return( NULL );
+	}
+
+	gchar *uuid = g_strdup( key + strlen( NA_GCONF_CONFIG_PATH "/" ));
+	gchar *pos = g_strstr_len( uuid, strlen( uuid ), "/" );
+	if( pos != NULL ){
+		*pos = '\0';
+	}
+
+	if( !is_uuid_valid( uuid )){
+		add_message( reader, ERR_NOT_AN_UUID, uuid, line );
+		g_free( uuid );
+		uuid = NULL;
+	}
+
+	return( uuid );
+}
+
+static gboolean
+is_uuid_valid( const gchar *uuid )
+{
+	uuid_t uu;
+	return( uuid_parse( uuid, uu ) == 0 );
+}
+
+/*
+ * prefix was already been checked when extracting the uuid
+ */
+static gchar *
+get_profile_name_from_key( const gchar *key, const gchar *uuid )
+{
+	gchar *prefix = g_strdup_printf( "%s/%s/%s", NA_GCONF_CONFIG_PATH, uuid, ACTION_PROFILE_PREFIX );
+	gchar *profile_name = NULL;
+
+	if( g_str_has_prefix( key, prefix )){
+		profile_name = g_strdup( key + strlen( prefix ));
+		gchar *pos = g_strrstr( profile_name, "/" );
+		if( pos != NULL ){
+			*pos = '\0';
+		}
+	}
+
+	g_free( prefix );
+	return( profile_name );
+}
+
+static gchar *
+get_entry_from_key( const gchar *key )
+{
+	gchar *pos = g_strrstr( key, "/" );
+	g_assert( pos );
+	gchar *entry = g_strdup( pos+1 );
+	return( entry );
+}
+
+static void
+free_schema_value( NactGConfReader *reader )
+{
+	int i;
+
+	reader->private->profile = NULL;
+	reader->private->locale_waited = FALSE;
+
+	g_free( reader->private->entry );
+	reader->private->entry = NULL;
+
+	g_free( reader->private->value );
+	reader->private->value = NULL;
+
+	for( i=0 ; reader_str[i].entry ; ++i ){
+		reader_str[i].entry_found = FALSE;
+	}
+}
diff --git a/src/nact/nact-gconf-reader.h b/src/nact/nact-gconf-reader.h
new file mode 100644
index 0000000..fff9993
--- /dev/null
+++ b/src/nact/nact-gconf-reader.h
@@ -0,0 +1,77 @@
+/*
+ * 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 __NACT_GCONF_READER_H__
+#define __NACT_GCONF_READER_H__
+
+/*
+ * NactGConfReader class definition.
+ *
+ * This is the base class for importing into and exporting from GConf
+ * storage subsystem.
+ */
+
+#include <glib-object.h>
+
+#include <common/na-action.h>
+#include <common/na-action-profile.h>
+
+G_BEGIN_DECLS
+
+#define NACT_GCONF_READER_TYPE					( nact_gconf_reader_get_type())
+#define NACT_GCONF_READER( object )				( G_TYPE_CHECK_INSTANCE_CAST( object, NACT_GCONF_READER_TYPE, NactGConfReader ))
+#define NACT_GCONF_READER_CLASS( klass )		( G_TYPE_CHECK_CLASS_CAST( klass, NACT_GCONF_READER_TYPE, NactGConfReaderClass ))
+#define NACT_IS_GCONF_READER( object )			( G_TYPE_CHECK_INSTANCE_TYPE( object, NACT_GCONF_READER_TYPE ))
+#define NACT_IS_GCONF_READER_CLASS( klass )		( G_TYPE_CHECK_CLASS_TYPE(( klass ), NACT_GCONF_READER_TYPE ))
+#define NACT_GCONF_READER_GET_CLASS( object )	( G_TYPE_INSTANCE_GET_CLASS(( object ), NACT_GCONF_READER_TYPE, NactGConfReaderClass ))
+
+typedef struct NactGConfReaderPrivate NactGConfReaderPrivate;
+
+typedef struct {
+	GObject                 parent;
+	NactGConfReaderPrivate *private;
+}
+	NactGConfReader;
+
+typedef struct NactGConfReaderClassPrivate NactGConfReaderClassPrivate;
+
+typedef struct {
+	GObjectClass                 parent;
+	NactGConfReaderClassPrivate *private;
+}
+	NactGConfReaderClass;
+
+GType     nact_gconf_reader_get_type( void );
+
+NAAction *nact_gconf_reader_import( GObject *window, const gchar *uri, GSList **msg );
+
+G_END_DECLS
+
+#endif /* __NACT_GCONF_READER_H__ */
diff --git a/src/nact/nact-gconf-schema-writer.c b/src/nact/nact-gconf-writer.c
similarity index 67%
rename from src/nact/nact-gconf-schema-writer.c
rename to src/nact/nact-gconf-writer.c
index 944c70d..9ffd256 100644
--- a/src/nact/nact-gconf-schema-writer.c
+++ b/src/nact/nact-gconf-writer.c
@@ -34,32 +34,46 @@
 
 #include <libxml/tree.h>
 
-#include "nact-gconf-schema-writer.h"
+#include <common/na-gconf-keys.h>
+#include <common/na-utils.h>
+
+#include "nact-gconf-keys.h"
+#include "nact-gconf-writer.h"
 
 /* private class data
  */
-struct NactGConfSchemaWriterClassPrivate {
+struct NactGConfWriterClassPrivate {
 };
 
 /* private instance data
  */
-struct NactGConfSchemaWriterPrivate {
+struct NactGConfWriterPrivate {
 	gboolean  dispose_has_run;
 	gchar    *uuid;
 };
 
-static GObjectClass *st_parent_class = NULL;
+/* instance properties
+ */
+enum {
+	PROP_GCONF_WRITER_UUID = 1
+};
 
-static GType                  register_type( void );
-static void                   class_init( NactGConfSchemaWriterClass *klass );
-static void                   instance_init( GTypeInstance *instance, gpointer klass );
-static void                   instance_dispose( GObject *object );
-static void                   instance_finalize( GObject *object );
+#define PROP_GCONF_WRITER_UUID_STR		"gconf-writer-uuid"
 
-static NactGConfSchemaWriter *gconf_schema_writer_new( void );
-static xmlDocPtr              create_xml( NactGConfSchemaWriter *writer, NAAction *action );
-static void                   create_schema_entry(
-										NactGConfSchemaWriter *writer,
+static GObjectClass *st_parent_class = NULL;
+
+static GType            register_type( void );
+static void             class_init( NactGConfWriterClass *klass );
+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 NactGConfWriter *gconf_writer_new( const gchar *uuid );
+static xmlDocPtr        create_xml( NactGConfWriter *writer, NAAction *action );
+static void             create_schema_entry(
+										NactGConfWriter *writer,
 										const gchar *profile_name,
 										const gchar *key,
 										const gchar *value,
@@ -69,7 +83,7 @@ static void                   create_schema_entry(
 										gboolean is_l10n_value );
 
 GType
-nact_gconf_schema_writer_get_type( void )
+nact_gconf_writer_get_type( void )
 {
 	static GType object_type = 0;
 
@@ -84,26 +98,26 @@ static GType
 register_type( void )
 {
 	static GTypeInfo info = {
-		sizeof( NactGConfSchemaWriterClass ),
+		sizeof( NactGConfWriterClass ),
 		NULL,
 		NULL,
 		( GClassInitFunc ) class_init,
 		NULL,
 		NULL,
-		sizeof( NactGConfSchemaWriter ),
+		sizeof( NactGConfWriter ),
 		0,
 		( GInstanceInitFunc ) instance_init
 	};
 
-	GType type = g_type_register_static( G_TYPE_OBJECT, "NactGConfSchemaWriter", &info, 0 );
+	GType type = g_type_register_static( G_TYPE_OBJECT, "NactGConfWriter", &info, 0 );
 
 	return( type );
 }
 
 static void
-class_init( NactGConfSchemaWriterClass *klass )
+class_init( NactGConfWriterClass *klass )
 {
-	static const gchar *thisfn = "nact_gconf_schema_writer_class_init";
+	static const gchar *thisfn = "nact_gconf_writer_class_init";
 	g_debug( "%s: klass=%p", thisfn, klass );
 
 	st_parent_class = g_type_class_peek_parent( klass );
@@ -111,29 +125,74 @@ class_init( NactGConfSchemaWriterClass *klass )
 	GObjectClass *object_class = G_OBJECT_CLASS( klass );
 	object_class->dispose = instance_dispose;
 	object_class->finalize = instance_finalize;
-
-	klass->private = g_new0( NactGConfSchemaWriterClassPrivate, 1 );
+	object_class->get_property = instance_get_property;
+	object_class->set_property = instance_set_property;
+
+	GParamSpec *spec;
+	spec = g_param_spec_string(
+			PROP_GCONF_WRITER_UUID_STR,
+			PROP_GCONF_WRITER_UUID_STR,
+			"UUID of the action", "",
+			G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS | G_PARAM_READWRITE );
+	g_object_class_install_property( object_class, PROP_GCONF_WRITER_UUID, spec );
+
+	klass->private = g_new0( NactGConfWriterClassPrivate, 1 );
 }
 
 static void
 instance_init( GTypeInstance *instance, gpointer klass )
 {
-	static const gchar *thisfn = "nact_gconf_schema_writer_instance_init";
+	static const gchar *thisfn = "nact_gconf_writer_instance_init";
 	g_debug( "%s: instance=%p, klass=%p", thisfn, instance, klass );
 
-	g_assert( NACT_IS_GCONF_SCHEMA_WRITER( instance ));
-	NactGConfSchemaWriter *self = NACT_GCONF_SCHEMA_WRITER( instance );
+	g_assert( NACT_IS_GCONF_WRITER( instance ));
+	NactGConfWriter *self = NACT_GCONF_WRITER( instance );
 
-	self->private = g_new0( NactGConfSchemaWriterPrivate, 1 );
+	self->private = g_new0( NactGConfWriterPrivate, 1 );
 
 	self->private->dispose_has_run = FALSE;
 }
 
 static void
+instance_get_property( GObject *object, guint property_id, GValue *value, GParamSpec *spec )
+{
+	g_assert( NACT_IS_GCONF_WRITER( object ));
+	NactGConfWriter *self = NACT_GCONF_WRITER( object );
+
+	switch( property_id ){
+		case PROP_GCONF_WRITER_UUID:
+			g_value_set_string( value, self->private->uuid );
+			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_GCONF_WRITER( object ));
+	NactGConfWriter *self = NACT_GCONF_WRITER( object );
+
+	switch( property_id ){
+		case PROP_GCONF_WRITER_UUID:
+			g_free( self->private->uuid );
+			self->private->uuid = g_value_dup_string( value );
+			break;
+
+		default:
+			G_OBJECT_WARN_INVALID_PROPERTY_ID( object, property_id, spec );
+			break;
+	}
+}
+
+static void
 instance_dispose( GObject *object )
 {
-	g_assert( NACT_IS_GCONF_SCHEMA_WRITER( object ));
-	NactGConfSchemaWriter *self = NACT_GCONF_SCHEMA_WRITER( object );
+	g_assert( NACT_IS_GCONF_WRITER( object ));
+	NactGConfWriter *self = NACT_GCONF_WRITER( object );
 
 	if( !self->private->dispose_has_run ){
 
@@ -147,8 +206,8 @@ instance_dispose( GObject *object )
 static void
 instance_finalize( GObject *object )
 {
-	g_assert( NACT_IS_GCONF_SCHEMA_WRITER( object ));
-	NactGConfSchemaWriter *self = NACT_GCONF_SCHEMA_WRITER( object );
+	g_assert( NACT_IS_GCONF_WRITER( object ));
+	NactGConfWriter *self = NACT_GCONF_WRITER( object );
 
 	g_free( self->private->uuid );
 
@@ -160,44 +219,43 @@ instance_finalize( GObject *object )
 	}
 }
 
-static NactGConfSchemaWriter *
-gconf_schema_writer_new( void )
-{
-	return( g_object_new( NACT_GCONF_SCHEMA_WRITER_TYPE, NULL ));
-}
-
-static void
-gconf_schema_writer_set_uuid( NactGConfSchemaWriter *writer, const gchar *uuid )
+static NactGConfWriter *
+gconf_writer_new( const gchar *uuid )
 {
-	g_free( writer->private->uuid );
-	writer->private->uuid = g_strdup( uuid );
+	return( g_object_new( NACT_GCONF_WRITER_TYPE, PROP_GCONF_WRITER_UUID_STR, uuid, NULL ));
 }
 
 /**
  * Export the specified action as a GConf schema.
+ *
+ * Returns the written filename.
  */
-void
-nact_gconf_schema_writer_export( NAAction *action, const gchar *folder, gchar **msg )
+gchar *
+nact_gconf_writer_export( NAAction *action, const gchar *folder, gchar **msg )
 {
-	NactGConfSchemaWriter *writer = gconf_schema_writer_new();
-
 	gchar *uuid = na_action_get_uuid( action );
-	gconf_schema_writer_set_uuid( writer, uuid );
+	NactGConfWriter *writer = gconf_writer_new( uuid );
 	g_free( uuid );
 
 	xmlDocPtr doc = create_xml( writer, action );
 
-	/* generate the filename name and save the schema into it */
-	gchar *filename = g_strdup_printf( "%s/%s.schema", folder, writer->private->uuid );
-	xmlSaveFormatFileEnc( filename, doc, "UTF-8", 1 );
-	g_free( filename );
+	/* generate the filename name and save the xml document into it */
+	gchar *filename = g_strdup_printf( "%s/action-%s.xml", folder, writer->private->uuid );
 
+	if( xmlSaveFormatFileEnc( filename, doc, "UTF-8", 1 ) == -1 ){
+		g_free( filename );
+		filename = NULL;
+	}
 	xmlFreeDoc (doc);
 	xmlCleanupParser();
+
+	g_object_unref( writer );
+
+	return( filename );
 }
 
 static xmlDocPtr
-create_xml( NactGConfSchemaWriter *writer, NAAction *action )
+create_xml( NactGConfWriter *writer, NAAction *action )
 {
 	xmlDocPtr doc = xmlNewDoc( BAD_CAST( "1.0" ));
 	xmlNodePtr root_node = xmlNewNode( NULL, BAD_CAST( NACT_GCONF_XML_ROOT ));
@@ -299,7 +357,7 @@ create_xml( NactGConfSchemaWriter *writer, NAAction *action )
 }
 
 static void
-create_schema_entry( NactGConfSchemaWriter *writer,
+create_schema_entry( NactGConfWriter *writer,
 		const gchar *profile_name, const gchar *key, const gchar *value,
 		xmlDocPtr doc, xmlNodePtr list_node, const gchar *type, gboolean is_l10n_value )
 {
@@ -312,17 +370,17 @@ create_schema_entry( NactGConfSchemaWriter *writer,
 
 	xmlNodePtr schema_node = xmlNewChild( list_node, NULL, BAD_CAST( NACT_GCONF_XML_SCHEMA_ENTRY ), NULL );
 
-	xmlChar *content = BAD_CAST( g_build_path( "/", NACT_GCONF_SCHEMA_PREFIX, path, NULL ));
+	/*xmlChar *content = BAD_CAST( g_build_path( "/", NACT_GCONF_SCHEMA_PREFIX, path, NULL ));
 	xmlNewChild( schema_node, NULL, BAD_CAST( NACT_GCONF_XML_SCHEMA_KEY ), content );
-	xmlFree( content );
+	xmlFree( content );*/
 
 	xmlNewChild( schema_node, NULL, BAD_CAST( NACT_GCONF_XML_SCHEMA_APPLYTO ), BAD_CAST( path ));
 
-	xmlNewChild( schema_node, NULL, BAD_CAST( NACT_GCONF_XML_SCHEMA_TYPE ), BAD_CAST( type ));
+	/*xmlNewChild( schema_node, NULL, BAD_CAST( NACT_GCONF_XML_SCHEMA_TYPE ), BAD_CAST( type ));*/
 
-	if( !g_ascii_strcasecmp( type, "list" )){
+	/*if( !g_ascii_strcasecmp( type, "list" )){
 		xmlNewChild( schema_node, NULL, BAD_CAST( NACT_GCONF_XML_SCHEMA_LIST_TYPE ), BAD_CAST( "string" ));
-	}
+	}*/
 
 	/* if the default value must be localized, put it in the <locale> element
 	 */
diff --git a/src/nact/nact-gconf-writer.h b/src/nact/nact-gconf-writer.h
new file mode 100644
index 0000000..26e10bf
--- /dev/null
+++ b/src/nact/nact-gconf-writer.h
@@ -0,0 +1,77 @@
+/*
+ * 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 __NACT_GCONF_WRITER_H__
+#define __NACT_GCONF_WRITER_H__
+
+/*
+ * NactGConfWriter class definition.
+ *
+ * This is the base class for importing into and exporting from GConf
+ * storage subsystem.
+ */
+
+#include <glib-object.h>
+
+#include <common/na-action.h>
+#include <common/na-action-profile.h>
+
+G_BEGIN_DECLS
+
+#define NACT_GCONF_WRITER_TYPE					( nact_gconf_writer_get_type())
+#define NACT_GCONF_WRITER( object )				( G_TYPE_CHECK_INSTANCE_CAST( object, NACT_GCONF_WRITER_TYPE, NactGConfWriter ))
+#define NACT_GCONF_WRITER_CLASS( klass )		( G_TYPE_CHECK_CLASS_CAST( klass, NACT_GCONF_WRITER_TYPE, NactGConfWriterClass ))
+#define NACT_IS_GCONF_WRITER( object )			( G_TYPE_CHECK_INSTANCE_TYPE( object, NACT_GCONF_WRITER_TYPE ))
+#define NACT_IS_GCONF_WRITER_CLASS( klass )		( G_TYPE_CHECK_CLASS_TYPE(( klass ), NACT_GCONF_WRITER_TYPE ))
+#define NACT_GCONF_WRITER_GET_CLASS( object )	( G_TYPE_INSTANCE_GET_CLASS(( object ), NACT_GCONF_WRITER_TYPE, NactGConfWriterClass ))
+
+typedef struct NactGConfWriterPrivate NactGConfWriterPrivate;
+
+typedef struct {
+	GObject                 parent;
+	NactGConfWriterPrivate *private;
+}
+	NactGConfWriter;
+
+typedef struct NactGConfWriterClassPrivate NactGConfWriterClassPrivate;
+
+typedef struct {
+	GObjectClass                 parent;
+	NactGConfWriterClassPrivate *private;
+}
+	NactGConfWriterClass;
+
+GType  nact_gconf_writer_get_type( void );
+
+gchar *nact_gconf_writer_export( NAAction *action, const gchar *folder, gchar **msg );
+
+G_END_DECLS
+
+#endif /* __NACT_GCONF_WRITER_H__ */
diff --git a/src/nact/nact-iactions-list.c b/src/nact/nact-iactions-list.c
index 797db99..3cbcfab 100644
--- a/src/nact/nact-iactions-list.c
+++ b/src/nact/nact-iactions-list.c
@@ -66,7 +66,7 @@ static void       interface_base_finalize( NactIActionsListInterface *klass );
 
 static void       v_on_selection_changed( GtkTreeSelection *selection, gpointer user_data );
 static gboolean   v_on_button_press_event( GtkWidget *widget, GdkEventButton *event, gpointer data );
-static gboolean   v_on_key_press_event( GtkWidget *widget, GdkEventKey *event, gpointer data );
+static gboolean   v_on_key_pressed_event( GtkWidget *widget, GdkEventKey *event, gpointer data );
 
 static void       do_initial_load_widget( NactWindow *window );
 static void       do_runtime_init_widget( NactWindow *window );
@@ -388,19 +388,20 @@ v_on_button_press_event( GtkWidget *widget, GdkEventButton *event, gpointer user
 }
 
 static gboolean
-v_on_key_press_event( GtkWidget *widget, GdkEventKey *event, gpointer user_data )
+v_on_key_pressed_event( GtkWidget *widget, GdkEventKey *event, gpointer user_data )
 {
-	/*static const gchar *thisfn = "nact_iactions_list_v_on_key_pres_event";
+	/*static const gchar *thisfn = "nact_iactions_list_v_on_key_pressed_event";
 	g_debug( "%s: widget=%p, event=%p, user_data=%p", thisfn, widget, event, user_data );*/
 
 	g_assert( NACT_IS_IACTIONS_LIST( user_data ));
 	g_assert( NACT_IS_WINDOW( user_data ));
+	g_assert( event->type == GDK_KEY_PRESS );
 
 	gboolean stop = FALSE;
 	NactIActionsList *instance = NACT_IACTIONS_LIST( user_data );
 
-	if( NACT_IACTIONS_LIST_GET_INTERFACE( instance )->on_key_press_event ){
-		stop = NACT_IACTIONS_LIST_GET_INTERFACE( instance )->on_key_press_event( widget, event, user_data );
+	if( NACT_IACTIONS_LIST_GET_INTERFACE( instance )->on_key_pressed_event ){
+		stop = NACT_IACTIONS_LIST_GET_INTERFACE( instance )->on_key_pressed_event( widget, event, user_data );
 	}
 
 	if( !stop ){
@@ -465,7 +466,7 @@ do_runtime_init_widget( NactWindow *window )
 			window,
 			G_OBJECT( widget ),
 			"key-press-event",
-			G_CALLBACK( v_on_key_press_event ));
+			G_CALLBACK( v_on_key_pressed_event ));
 
 	/* catch double-click */
 	nact_window_signal_connect(
@@ -473,6 +474,10 @@ do_runtime_init_widget( NactWindow *window )
 			G_OBJECT( widget ),
 			"button-press-event",
 			G_CALLBACK( v_on_button_press_event ));
+
+	/* clear the selection */
+	GtkTreeSelection *selection = gtk_tree_view_get_selection( GTK_TREE_VIEW( widget ));
+	gtk_tree_selection_unselect_all( selection );
 }
 
 static void
diff --git a/src/nact/nact-iactions-list.h b/src/nact/nact-iactions-list.h
index 57a7ee4..a399249 100644
--- a/src/nact/nact-iactions-list.h
+++ b/src/nact/nact-iactions-list.h
@@ -64,7 +64,7 @@ typedef struct {
 	void     ( *fill_actions_list )    ( NactWindow *window );
 	void     ( *on_selection_changed ) ( GtkTreeSelection *selection, gpointer user_data );
 	gboolean ( *on_button_press_event )( GtkWidget *widget, GdkEventButton *event, gpointer data );
-	gboolean ( *on_key_press_event )   ( GtkWidget *widget, GdkEventKey *event, gpointer data );
+	gboolean ( *on_key_pressed_event ) ( GtkWidget *widget, GdkEventKey *event, gpointer data );
 	gboolean ( *on_double_click )      ( GtkWidget *widget, GdkEventButton *event, gpointer data );
 	gboolean ( *on_enter_key_pressed ) ( GtkWidget *widget, GdkEventKey *event, gpointer data );
 }
diff --git a/src/nact/nact-iprefs.c b/src/nact/nact-iprefs.c
index 3a7d719..fbe690a 100644
--- a/src/nact/nact-iprefs.c
+++ b/src/nact/nact-iprefs.c
@@ -51,8 +51,8 @@ struct NactIPrefsInterfacePrivate {
 /* key to read/write the last visited folder when browsing for a file
  */
 #define IPREFS_IPROFILE_CONDITION_FOLDER_URI	"iprofile-conditions-folder-uri"
-#define IPREFS_IMPORT_ACTIONS_FOLDER_URI		"main-window-import-folder-uri"
-#define IPREFS_EXPORT_ACTIONS_FOLDER_URI		"main-window-export-folder-uri"
+#define IPREFS_IMPORT_ACTIONS_FOLDER_URI		"import-folder-uri"
+#define IPREFS_EXPORT_ACTIONS_FOLDER_URI		"export-folder-uri"
 
 static GType   register_type( void );
 static void    interface_base_init( NactIPrefsInterface *klass );
diff --git a/src/nact/nact-main-window.c b/src/nact/nact-main-window.c
index a87828a..545174d 100644
--- a/src/nact/nact-main-window.c
+++ b/src/nact/nact-main-window.c
@@ -46,8 +46,8 @@
 #include "nact-application.h"
 #include "nact-action-conditions-editor.h"
 #include "nact-action-profiles-editor.h"
-#include "nact-action-profiles-editor.h"
-#include "nact-gconf-schema-writer.h"
+#include "nact-assist-export.h"
+#include "nact-assist-import.h"
 #include "nact-iactions-list.h"
 #include "nact-iprefs.h"
 #include "nact-main-window.h"
@@ -61,7 +61,6 @@ struct NactMainWindowClassPrivate {
  */
 struct NactMainWindowPrivate {
 	gboolean  dispose_has_run;
-	gboolean  export_mode;
 	gchar    *current_uuid;
 	gchar    *current_label;
 };
@@ -69,7 +68,6 @@ struct NactMainWindowPrivate {
 /* the GConf key used to read/write size and position of auxiliary dialogs
  */
 #define IPREFS_IMPORT_ACTIONS		"main-window-import-actions"
-#define IPREFS_EXPORT_ACTIONS		"main-window-export-actions"
 
 static GObjectClass *st_parent_class = NULL;
 
@@ -97,19 +95,11 @@ static void     on_duplicate_button_clicked( GtkButton *button, gpointer user_da
 static void     on_delete_button_clicked( GtkButton *button, gpointer user_data );
 static void     on_import_button_clicked( GtkButton *button, gpointer user_data );
 static void     on_export_button_clicked( GtkButton *button, gpointer user_data );
-static void     on_saveas_button_clicked( GtkButton *button, gpointer user_data );
 static gboolean on_dialog_response( GtkDialog *dialog, gint response_id, BaseWindow *window );
 
 static void     on_actions_changed( NAIPivotContainer *instance, gpointer user_data );
-
 static void     set_current_action( NactMainWindow *window, const NAAction *action );
 static void     do_set_current_action( NactWindow *window, const gchar *uuid, const gchar *label );
-static void     set_export_mode( NactWindow *window, gboolean mode );
-static void     setup_buttons( NactWindow *window );
-static void     do_import_actions( NactMainWindow *window, const gchar *filename );
-static void     do_export_actions( NactMainWindow *window, const gchar *folder );
-
-/*static gint     count_actions( BaseWindow *window );*/
 
 GType
 nact_main_window_get_type( void )
@@ -240,9 +230,6 @@ instance_dispose( GObject *window )
 
 		self->private->dispose_has_run = TRUE;
 
-		g_free( self->private->current_uuid );
-		g_free( self->private->current_label );
-
 		/* chain up to the parent class */
 		G_OBJECT_CLASS( st_parent_class )->dispose( window );
 	}
@@ -257,6 +244,9 @@ instance_finalize( GObject *window )
 	g_assert( NACT_IS_MAIN_WINDOW( window ));
 	NactMainWindow *self = ( NactMainWindow * ) window;
 
+	g_free( self->private->current_uuid );
+	g_free( self->private->current_label );
+
 	g_free( self->private );
 
 	/* chain call to parent class */
@@ -331,9 +321,6 @@ on_runtime_init_toplevel( BaseWindow *window )
 	nact_window_signal_connect_by_name( NACT_WINDOW( window ), "DeleteActionButton", "clicked", G_CALLBACK( on_delete_button_clicked ));
 	nact_window_signal_connect_by_name( NACT_WINDOW( window ), "ImportButton", "clicked", G_CALLBACK( on_import_button_clicked ));
 	nact_window_signal_connect_by_name( NACT_WINDOW( window ), "ExportButton", "clicked", G_CALLBACK( on_export_button_clicked ));
-	nact_window_signal_connect_by_name( NACT_WINDOW( window ), "SaveAsButton", "clicked", G_CALLBACK( on_saveas_button_clicked ));
-
-	setup_buttons( NACT_WINDOW( window ));
 }
 
 static void
@@ -345,21 +332,18 @@ on_actions_list_selection_changed( GtkTreeSelection *selection, gpointer user_da
 	g_assert( NACT_IS_MAIN_WINDOW( user_data ));
 	BaseWindow *window = BASE_WINDOW( user_data );
 
-	if( !NACT_MAIN_WINDOW( window )->private->export_mode ){
-
-		GtkWidget *edit_button = base_window_get_widget( window, "EditActionButton" );
-		GtkWidget *delete_button = base_window_get_widget( window, "DeleteActionButton" );
-		GtkWidget *duplicate_button = base_window_get_widget( window, "DuplicateActionButton" );
+	GtkWidget *edit_button = base_window_get_widget( window, "EditActionButton" );
+	GtkWidget *delete_button = base_window_get_widget( window, "DeleteActionButton" );
+	GtkWidget *duplicate_button = base_window_get_widget( window, "DuplicateActionButton" );
 
-		gboolean enabled = ( gtk_tree_selection_count_selected_rows( selection ) > 0 );
+	gboolean enabled = ( gtk_tree_selection_count_selected_rows( selection ) > 0 );
 
-		gtk_widget_set_sensitive( edit_button, enabled );
-		gtk_widget_set_sensitive( delete_button, enabled );
-		gtk_widget_set_sensitive( duplicate_button, enabled );
+	gtk_widget_set_sensitive( edit_button, enabled );
+	gtk_widget_set_sensitive( delete_button, enabled );
+	gtk_widget_set_sensitive( duplicate_button, enabled );
 
-		NAAction *action = NA_ACTION( nact_iactions_list_get_selected_action( NACT_WINDOW( window )));
-		set_current_action( NACT_MAIN_WINDOW( window ), action );
-	}
+	NAAction *action = NA_ACTION( nact_iactions_list_get_selected_action( NACT_WINDOW( window )));
+	set_current_action( NACT_MAIN_WINDOW( window ), action );
 }
 
 static gboolean
@@ -367,9 +351,7 @@ on_actions_list_double_click( GtkWidget *widget, GdkEventButton *event, gpointer
 {
 	g_assert( event->type == GDK_2BUTTON_PRESS );
 
-	if( !NACT_MAIN_WINDOW( user_data )->private->export_mode ){
-		on_edit_button_clicked( NULL, user_data );
-	}
+	on_edit_button_clicked( NULL, user_data );
 
 	return( TRUE );
 }
@@ -377,9 +359,7 @@ on_actions_list_double_click( GtkWidget *widget, GdkEventButton *event, gpointer
 static gboolean
 on_actions_list_enter_key_pressed( GtkWidget *widget, GdkEventKey *event, gpointer user_data )
 {
-	if( !NACT_MAIN_WINDOW( user_data )->private->export_mode ){
-		on_edit_button_clicked( NULL, user_data );
-	}
+	on_edit_button_clicked( NULL, user_data );
 
 	return( TRUE );
 }
@@ -598,8 +578,14 @@ on_import_button_clicked( GtkButton *button, gpointer user_data )
 	static const gchar *thisfn = "nact_main_window_on_import_button_clicked";
 	g_debug( "%s: button=%p, user_data=%p", thisfn, button, user_data );
 
+	nact_assist_import_run( NACT_WINDOW( user_data ));
+
 	g_assert( NACT_IS_MAIN_WINDOW( user_data ));
 	NactWindow *wndmain = NACT_WINDOW( user_data );
+	nact_iactions_list_set_focus( wndmain );
+
+	/*g_assert( NACT_IS_MAIN_WINDOW( user_data ));
+	NactWindow *wndmain = NACT_WINDOW( user_data );
 
 	GtkWidget *dialog = gtk_file_chooser_dialog_new(
 			_( "Importing new actions" ),
@@ -629,7 +615,7 @@ on_import_button_clicked( GtkButton *button, gpointer user_data )
 
 	gtk_widget_destroy( dialog );
 
-	nact_iactions_list_set_focus( wndmain );
+	nact_iactions_list_set_focus( wndmain );*/
 }
 
 /*
@@ -643,53 +629,13 @@ on_export_button_clicked( GtkButton *button, gpointer user_data )
 	static const gchar *thisfn = "nact_main_window_on_export_button_clicked";
 	g_debug( "%s: button=%p, user_data=%p", thisfn, button, user_data );
 
-	gboolean export = gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON( button ));
-	set_export_mode( NACT_WINDOW( user_data ), export );
+	nact_assist_export_run( NACT_WINDOW( user_data ));
 
 	g_assert( NACT_IS_MAIN_WINDOW( user_data ));
 	NactWindow *wndmain = NACT_WINDOW( user_data );
-
 	nact_iactions_list_set_focus( wndmain );
 }
 
-static void
-on_saveas_button_clicked( GtkButton *button, gpointer user_data )
-{
-	static const gchar *thisfn = "nact_main_window_on_saveas_button_clicked";
-	g_debug( "%s: button=%p, user_data=%p", thisfn, button, user_data );
-
-	g_assert( NACT_IS_MAIN_WINDOW( user_data ));
-	NactWindow *wndmain = NACT_WINDOW( user_data );
-
-	GtkWidget *dialog = gtk_file_chooser_dialog_new(
-			_( "Selecting a folder in which selected actions are to be saved" ),
-			NULL,
-			GTK_FILE_CHOOSER_ACTION_CREATE_FOLDER,
-			GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
-			GTK_STOCK_OK, GTK_RESPONSE_OK,
-			NULL
-			);
-
-	nact_iprefs_position_named_window( wndmain, GTK_WINDOW( dialog ), IPREFS_EXPORT_ACTIONS );
-	gchar *uri = nact_iprefs_get_export_folder_uri( wndmain );
-	gtk_file_chooser_set_uri( GTK_FILE_CHOOSER( dialog ), uri );
-	g_free( uri );
-
-	if( gtk_dialog_run( GTK_DIALOG( dialog )) == GTK_RESPONSE_OK ){
-		uri = gtk_file_chooser_get_uri( GTK_FILE_CHOOSER( dialog ));
-		do_export_actions( NACT_MAIN_WINDOW( wndmain ), uri );
-	  }
-
-	nact_iprefs_save_export_folder_uri( wndmain, uri );
-	g_free( uri );
-
-	nact_iprefs_save_named_window_position( wndmain, GTK_WINDOW( dialog ), IPREFS_EXPORT_ACTIONS );
-	gtk_widget_destroy( dialog );
-
-	GtkWidget *export_button = base_window_get_widget( BASE_WINDOW( user_data ), "ExportButton" );
-	gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON( export_button ), FALSE );
-}
-
 static gboolean
 on_dialog_response( GtkDialog *dialog, gint response_id, BaseWindow *window )
 {
@@ -756,101 +702,3 @@ do_set_current_action( NactWindow *window, const gchar *uuid, const gchar *label
 	NACT_MAIN_WINDOW( window )->private->current_uuid = g_strdup( uuid );
 	NACT_MAIN_WINDOW( window )->private->current_label = g_strdup( label );
 }
-
-static void
-set_export_mode( NactWindow *window, gboolean mode )
-{
-	g_assert( NACT_IS_MAIN_WINDOW( window ));
-	NactMainWindow *self = NACT_MAIN_WINDOW( window );
-
-	nact_iactions_list_set_multiple_selection( window, mode );
-	self->private->export_mode = mode;
-	setup_buttons( window );
-}
-
-static void
-setup_buttons( NactWindow *window )
-{
-	g_assert( NACT_IS_MAIN_WINDOW( window ));
-	NactMainWindow *self = NACT_MAIN_WINDOW( window );
-
-	GtkWidget *new_button = base_window_get_widget( BASE_WINDOW( window ), "NewActionButton" );
-	GtkWidget *edit_button = base_window_get_widget( BASE_WINDOW( window ), "EditActionButton" );
-	GtkWidget *duplicate_button = base_window_get_widget( BASE_WINDOW( window ), "DuplicateActionButton" );
-	GtkWidget *delete_button = base_window_get_widget( BASE_WINDOW( window ), "DeleteActionButton" );
-	GtkWidget *import_button = base_window_get_widget( BASE_WINDOW( window ), "ImportButton" );
-	GtkWidget *saveas_button = base_window_get_widget( BASE_WINDOW( window ), "SaveAsButton" );
-	GtkWidget *close_button = base_window_get_widget( BASE_WINDOW( window ), "CloseButton" );
-
-	gtk_widget_set_sensitive( new_button, !self->private->export_mode );
-	gtk_widget_set_sensitive( edit_button, !self->private->export_mode );
-	gtk_widget_set_sensitive( delete_button, !self->private->export_mode );
-	gtk_widget_set_sensitive( duplicate_button, !self->private->export_mode );
-	gtk_widget_set_sensitive( import_button, !self->private->export_mode );
-	gtk_widget_set_sensitive( close_button, !self->private->export_mode );
-
-	gtk_widget_set_sensitive( saveas_button, self->private->export_mode );
-
-	GtkWidget *label = base_window_get_widget( BASE_WINDOW( window ), "ExportModeLabel" );
-	gchar *text = g_strdup( "" );
-	if( self->private->export_mode ){
-		g_free( text );
-		text = g_strdup( _( "Export mode toggled.\n"
-				"Please, select actions to be exported (multiple selection is authorized).\n" ));
-	}
-	gtk_label_set_label( GTK_LABEL( label ), text );
-	g_free( text );
-}
-
-static void
-do_import_actions( NactMainWindow *window, const gchar *filename )
-{
-	static const gchar *thisfn = "nact_main_window_do_import_actions";
-	g_debug( "%s: window=%p, filename=%p", thisfn, window, filename );
-}
-
-static void
-do_export_actions( NactMainWindow *window, const gchar *folder )
-{
-	static const gchar *thisfn = "nact_main_window_do_export_actions";
-	g_debug( "%s: window=%p, folder=%p", thisfn, window, folder );
-
-	GSList *actions = nact_iactions_list_get_selected_actions( NACT_WINDOW( window ));
-	GSList *ia;
-	gchar *msg = NULL;
-	gchar *reason = NULL;
-	gchar *tmp;
-
-	for( ia = actions ; ia ; ia = ia->next ){
-		NAAction *action = NA_ACTION( ia->data );
-		nact_gconf_schema_writer_export( action, folder, &msg );
-		if( msg ){
-			if( reason ){
-				tmp = g_strdup_printf( "%s\n", reason );
-				g_free( reason );
-				reason = tmp;
-			}
-			tmp = g_strdup_printf( "%s%s", reason, msg );
-			g_free( reason );
-			reason = tmp;
-		}
-		g_free( msg );
-	}
-
-	if( reason ){
-		base_window_error_dlg( BASE_WINDOW( window ), GTK_MESSAGE_WARNING,
-				_( "One or more errors have been detected when exporting actions." ), reason );
-		g_free( reason );
-	}
-
-	g_slist_free( actions );
-}
-
-/*static gint
-count_actions( BaseWindow *window )
-{
-	NactApplication *appli = NACT_APPLICATION( base_window_get_application( window ));
-	NAPivot *pivot = NA_PIVOT( nact_application_get_pivot( appli ));
-	GSList *actions = na_pivot_get_actions( pivot );
-	return( g_slist_length( actions ));
-}*/
diff --git a/src/nact/nact-window.c b/src/nact/nact-window.c
index 7566257..83df734 100644
--- a/src/nact/nact-window.c
+++ b/src/nact/nact-window.c
@@ -63,18 +63,19 @@ typedef struct {
 	NactWindowRecordedSignal;
 
 static GObjectClass *st_parent_class = NULL;
+static gboolean      st_debug_signal_connect = FALSE;
 
-static GType  register_type( void );
-static void   class_init( NactWindowClass *klass );
-static void   iprefs_iface_init( NactIPrefsInterface *iface );
-static void   instance_init( GTypeInstance *instance, gpointer klass );
-static void   instance_dispose( GObject *application );
-static void   instance_finalize( GObject *application );
+static GType    register_type( void );
+static void     class_init( NactWindowClass *klass );
+static void     iprefs_iface_init( NactIPrefsInterface *iface );
+static void     instance_init( GTypeInstance *instance, gpointer klass );
+static void     instance_dispose( GObject *application );
+static void     instance_finalize( GObject *application );
 
-static gchar *v_get_iprefs_window_id( NactWindow *window );
+static gchar   *v_get_iprefs_window_id( NactWindow *window );
 
-static void   on_runtime_init_toplevel( BaseWindow *window );
-static void   on_all_widgets_showed( BaseWindow *dialog );
+static void     on_runtime_init_toplevel( BaseWindow *window );
+static void     on_all_widgets_showed( BaseWindow *dialog );
 
 GType
 nact_window_get_type( void )
@@ -137,11 +138,11 @@ class_init( NactWindowClass *klass )
 
 	klass->private = g_new0( NactWindowClassPrivate, 1 );
 
-	klass->get_iprefs_window_id = v_get_iprefs_window_id;
-
 	BaseWindowClass *base_class = BASE_WINDOW_CLASS( klass );
 	base_class->runtime_init_toplevel = on_runtime_init_toplevel;
 	base_class->all_widgets_showed = on_all_widgets_showed;
+
+	klass->get_iprefs_window_id = v_get_iprefs_window_id;
 }
 
 static void
@@ -187,7 +188,9 @@ instance_dispose( GObject *window )
 		for( is = self->private->signals ; is ; is = is->next ){
 			NactWindowRecordedSignal *str = ( NactWindowRecordedSignal * ) is->data;
 			g_signal_handler_disconnect( str->instance, str->handler_id );
-			/*g_debug( "%s: disconnecting signal handler %p:%lu", thisfn, str->instance, str->handler_id );*/
+			if( st_debug_signal_connect ){
+				g_debug( "%s: disconnecting signal handler %p:%lu", thisfn, str->instance, str->handler_id );
+			}
 			g_free( str );
 		}
 		g_slist_free( self->private->signals );
@@ -305,7 +308,7 @@ nact_window_warn_action_modified( NactWindow *window, const NAAction *action )
 	if( label && strlen( label )){
 		first = g_strdup_printf( _( "The action \"%s\" has been modified." ), label );
 	} else {
-		first = g_strdup( _( "The newly created action has been modified" ));
+		first = g_strdup( _( "The newly created action has been modified." ));
 	}
 	gchar *second = g_strdup( _( "Are you sure you want to quit without saving it ?" ));
 
@@ -337,7 +340,7 @@ nact_window_get_actions( NactWindow *window )
 void
 nact_window_signal_connect( NactWindow *window, GObject *instance, const gchar *signal, GCallback fn )
 {
-	/*static const gchar *thisfn = "nact_window_signal_connect";*/
+	static const gchar *thisfn = "nact_window_signal_connect";
 
 	gulong handler_id = g_signal_connect( instance, signal, fn, window );
 
@@ -346,7 +349,9 @@ nact_window_signal_connect( NactWindow *window, GObject *instance, const gchar *
 	str->handler_id = handler_id;
 	window->private->signals = g_slist_prepend( window->private->signals, str );
 
-	/*g_debug( "%s: connecting signal handler %p:%lu", thisfn, instance, handler_id );*/
+	if( st_debug_signal_connect ){
+		g_debug( "%s: connecting signal handler %p:%lu", thisfn, instance, handler_id );
+	}
 }
 
 void
diff --git a/src/nact/nact-window.h b/src/nact/nact-window.h
index 1542730..400368b 100644
--- a/src/nact/nact-window.h
+++ b/src/nact/nact-window.h
@@ -66,8 +66,8 @@ typedef struct {
 	NactWindowClassPrivate *private;
 
 	/* api */
-	gchar * ( *get_iprefs_window_id )( NactWindow *window );
-	void    ( *set_current_action )  ( NactWindow *window, const gchar *uuid, const gchar *label );
+	gchar *  ( *get_iprefs_window_id )( NactWindow *window );
+	void     ( *set_current_action )  ( NactWindow *window, const gchar *uuid, const gchar *label );
 }
 	NactWindowClass;
 
diff --git a/src/nact/nautilus-actions-config.ui b/src/nact/nautilus-actions-config.ui
index 84fc077..e09c352 100644
--- a/src/nact/nautilus-actions-config.ui
+++ b/src/nact/nautilus-actions-config.ui
@@ -38,12 +38,8 @@
               </packing>
             </child>
             <child>
-              <object class="GtkTable" id="table1">
+              <object class="GtkVButtonBox" id="vbuttonbox1">
                 <property name="visible">True</property>
-                <property name="n_rows">4</property>
-                <property name="n_columns">2</property>
-                <property name="column_spacing">4</property>
-                <property name="row_spacing">4</property>
                 <property name="homogeneous">True</property>
                 <child>
                   <object class="GtkButton" id="NewActionButton">
@@ -55,8 +51,9 @@
                     <property name="use_stock">True</property>
                   </object>
                   <packing>
-                    <property name="x_options"></property>
-                    <property name="y_options"></property>
+                    <property name="expand">False</property>
+                    <property name="fill">False</property>
+                    <property name="position">0</property>
                   </packing>
                 </child>
                 <child>
@@ -70,10 +67,24 @@
                     <property name="use_stock">True</property>
                   </object>
                   <packing>
-                    <property name="top_attach">1</property>
-                    <property name="bottom_attach">2</property>
-                    <property name="x_options"></property>
-                    <property name="y_options"></property>
+                    <property name="expand">False</property>
+                    <property name="fill">False</property>
+                    <property name="position">1</property>
+                  </packing>
+                </child>
+                <child>
+                  <object class="GtkButton" id="DuplicateActionButton">
+                    <property name="label" translatable="yes">D_uplicate</property>
+                    <property name="visible">True</property>
+                    <property name="can_focus">True</property>
+                    <property name="receives_default">True</property>
+                    <property name="image">DuplicateButtonImage</property>
+                    <property name="use_underline">True</property>
+                  </object>
+                  <packing>
+                    <property name="expand">False</property>
+                    <property name="fill">False</property>
+                    <property name="position">2</property>
                   </packing>
                 </child>
                 <child>
@@ -87,10 +98,9 @@
                     <property name="use_stock">True</property>
                   </object>
                   <packing>
-                    <property name="top_attach">3</property>
-                    <property name="bottom_attach">4</property>
-                    <property name="x_options"></property>
-                    <property name="y_options"></property>
+                    <property name="expand">False</property>
+                    <property name="fill">False</property>
+                    <property name="position">3</property>
                   </packing>
                 </child>
                 <child>
@@ -103,15 +113,14 @@
                     <property name="use_underline">True</property>
                   </object>
                   <packing>
-                    <property name="left_attach">1</property>
-                    <property name="right_attach">2</property>
-                    <property name="x_options"></property>
-                    <property name="y_options"></property>
+                    <property name="expand">False</property>
+                    <property name="fill">False</property>
+                    <property name="position">4</property>
                   </packing>
                 </child>
                 <child>
-                  <object class="GtkToggleButton" id="ExportButton">
-                    <property name="label" translatable="yes">E_xport mode</property>
+                  <object class="GtkButton" id="ExportButton">
+                    <property name="label" translatable="yes">E_xport...</property>
                     <property name="visible">True</property>
                     <property name="can_focus">True</property>
                     <property name="receives_default">True</property>
@@ -119,50 +128,11 @@
                     <property name="use_underline">True</property>
                   </object>
                   <packing>
-                    <property name="left_attach">1</property>
-                    <property name="right_attach">2</property>
-                    <property name="top_attach">2</property>
-                    <property name="bottom_attach">3</property>
-                    <property name="x_options"></property>
-                    <property name="y_options"></property>
-                  </packing>
-                </child>
-                <child>
-                  <object class="GtkButton" id="SaveAsButton">
-                    <property name="label" translatable="yes">gtk-save-as</property>
-                    <property name="visible">True</property>
-                    <property name="can_focus">True</property>
-                    <property name="receives_default">True</property>
-                    <property name="use_stock">True</property>
-                  </object>
-                  <packing>
-                    <property name="left_attach">1</property>
-                    <property name="right_attach">2</property>
-                    <property name="top_attach">3</property>
-                    <property name="bottom_attach">4</property>
-                    <property name="x_options"></property>
-                    <property name="y_options"></property>
-                  </packing>
-                </child>
-                <child>
-                  <object class="GtkButton" id="DuplicateActionButton">
-                    <property name="label" translatable="yes">D_uplicate</property>
-                    <property name="visible">True</property>
-                    <property name="can_focus">True</property>
-                    <property name="receives_default">True</property>
-                    <property name="image">DuplicateButtonImage</property>
-                    <property name="use_underline">True</property>
-                  </object>
-                  <packing>
-                    <property name="top_attach">2</property>
-                    <property name="bottom_attach">3</property>
-                    <property name="x_options"></property>
-                    <property name="y_options"></property>
+                    <property name="expand">False</property>
+                    <property name="fill">False</property>
+                    <property name="position">5</property>
                   </packing>
                 </child>
-                <child>
-                  <placeholder/>
-                </child>
               </object>
               <packing>
                 <property name="expand">False</property>
@@ -172,21 +142,10 @@
             </child>
           </object>
           <packing>
-            <property name="padding">6</property>
-            <property name="position">2</property>
-          </packing>
-        </child>
-        <child>
-          <object class="GtkLabel" id="ExportModeLabel">
-            <property name="visible">True</property>
-            <property name="xalign">0</property>
-            <property name="yalign">0</property>
-            <property name="xpad">10</property>
-          </object>
-          <packing>
             <property name="expand">False</property>
             <property name="fill">False</property>
-            <property name="position">3</property>
+            <property name="padding">6</property>
+            <property name="position">0</property>
           </packing>
         </child>
         <child internal-child="action_area">
@@ -227,7 +186,7 @@
           <packing>
             <property name="expand">False</property>
             <property name="pack_type">end</property>
-            <property name="position">0</property>
+            <property name="position">1</property>
           </packing>
         </child>
       </object>
@@ -1501,45 +1460,171 @@ file(s)/folder(s)</property>
       <action-widget response="-5">okbutton4</action-widget>
     </action-widgets>
   </object>
+  <object class="GtkAssistant" id="ExportAssistant">
+    <property name="events">GDK_KEY_PRESS_MASK | GDK_STRUCTURE_MASK</property>
+    <property name="border_width">12</property>
+    <property name="title" translatable="yes">Exporting actions</property>
+    <property name="modal">True</property>
+    <child>
+      <object class="GtkLabel" id="label1">
+        <property name="visible">True</property>
+        <property name="label" translatable="yes">This assistant will guide you through the process of exporting actions.</property>
+      </object>
+      <packing>
+        <property name="page_type">intro</property>
+      </packing>
+    </child>
+    <child>
+      <object class="GtkHBox" id="hbox1">
+        <property name="visible">True</property>
+        <child>
+          <object class="GtkScrolledWindow" id="scrolledwindow3">
+            <property name="visible">True</property>
+            <property name="can_focus">True</property>
+            <property name="hscrollbar_policy">automatic</property>
+            <property name="vscrollbar_policy">automatic</property>
+            <property name="shadow_type">in</property>
+            <child>
+              <object class="GtkTreeView" id="ActionsList">
+                <property name="visible">True</property>
+                <property name="can_focus">True</property>
+                <property name="events">GDK_BUTTON_PRESS_MASK | GDK_KEY_PRESS_MASK</property>
+                <property name="headers_visible">False</property>
+                <property name="rules_hint">True</property>
+              </object>
+            </child>
+          </object>
+          <packing>
+            <property name="position">0</property>
+          </packing>
+        </child>
+        <child>
+          <object class="GtkLabel" id="label2">
+            <property name="visible">True</property>
+            <property name="label" translatable="yes">Please select one or more actions
+to be exported.
+
+You may use Ctrl and Shift keys
+to extend a selection.</property>
+          </object>
+          <packing>
+            <property name="position">1</property>
+          </packing>
+        </child>
+      </object>
+      <packing>
+        <property name="title">Selection of the exported actions</property>
+      </packing>
+    </child>
+    <child>
+      <object class="GtkHBox" id="hbox2">
+        <property name="visible">True</property>
+        <child>
+          <object class="GtkFileChooserWidget" id="ExportFolderChooser">
+            <property name="visible">True</property>
+            <property name="orientation">vertical</property>
+            <property name="local_only">False</property>
+            <property name="preview_widget_active">False</property>
+            <property name="use_preview_label">False</property>
+            <property name="action">select-folder</property>
+          </object>
+          <packing>
+            <property name="position">0</property>
+          </packing>
+        </child>
+      </object>
+      <packing>
+        <property name="title">Selection of the target folder</property>
+      </packing>
+    </child>
+    <child>
+      <object class="GtkLabel" id="label3">
+        <property name="visible">True</property>
+        <property name="use_markup">True</property>
+      </object>
+      <packing>
+        <property name="page_type">confirm</property>
+        <property name="title">Summary</property>
+      </packing>
+    </child>
+    <child>
+      <object class="GtkLabel" id="label4">
+        <property name="visible">True</property>
+        <property name="use_markup">True</property>
+      </object>
+      <packing>
+        <property name="page_type">summary</property>
+        <property name="title">Export is done</property>
+      </packing>
+    </child>
+  </object>
+  <object class="GtkAssistant" id="ImportAssistant">
+    <property name="border_width">12</property>
+    <property name="title" translatable="yes">Importing actions</property>
+    <property name="modal">True</property>
+    <child>
+      <object class="GtkLabel" id="label1">
+        <property name="visible">True</property>
+        <property name="label" translatable="yes">This assistant will guide you through the process of importing actions.</property>
+      </object>
+      <packing>
+        <property name="page_type">intro</property>
+      </packing>
+    </child>
+    <child>
+      <object class="GtkFileChooserWidget" id="filechooserwidget1">
+        <property name="visible">True</property>
+        <property name="orientation">vertical</property>
+        <property name="local_only">False</property>
+        <property name="preview_widget_active">False</property>
+        <property name="use_preview_label">False</property>
+        <property name="select_multiple">True</property>
+      </object>
+    </child>
+    <child>
+      <object class="GtkLabel" id="label3">
+        <property name="visible">True</property>
+      </object>
+      <packing>
+        <property name="page_type">confirm</property>
+      </packing>
+    </child>
+    <child>
+      <object class="GtkLabel" id="label2">
+        <property name="visible">True</property>
+      </object>
+      <packing>
+        <property name="page_type">summary</property>
+      </packing>
+    </child>
+  </object>
   <object class="GtkImage" id="LegendButtonImage">
     <property name="visible">True</property>
     <property name="stock">gtk-help</property>
     <property name="icon-size">4</property>
   </object>
-  <object class="GtkImage" id="ImportButtonImage">
+  <object class="GtkImage" id="DuplicateButtonImage">
     <property name="visible">True</property>
-    <property name="stock">gtk-convert</property>
+    <property name="stock">gtk-copy</property>
     <property name="icon-size">4</property>
   </object>
-  <object class="GtkImage" id="ExportButtonImage">
+  <object class="GtkImage" id="ImportButtonImage">
     <property name="visible">True</property>
-    <property name="stock">gtk-execute</property>
+    <property name="stock">gtk-convert</property>
     <property name="icon-size">4</property>
   </object>
-  <object class="GtkImage" id="DuplicateButtonImage">
+  <object class="GtkImage" id="ExportButtonImage">
     <property name="visible">True</property>
-    <property name="stock">gtk-copy</property>
+    <property name="stock">gtk-save</property>
     <property name="icon-size">4</property>
   </object>
   <object class="GtkSizeGroup" id="IProfileConditionsLabelSizeGroup">
     <widgets>
-      <widget name="MenuLabelLabel"/>
-      <widget name="MenuTooltipLabel"/>
-      <widget name="MenuIconLabel"/>
-      <widget name="ActionPathLabel"/>
       <widget name="ActionParametersLabel"/>
-    </widgets>
-  </object>
-  <object class="GtkSizeGroup" id="MainButtonsSizeGroup">
-    <property name="mode">both</property>
-    <widgets>
-      <widget name="NewActionButton"/>
-      <widget name="EditActionButton"/>
-      <widget name="DeleteActionButton"/>
-      <widget name="ImportButton"/>
-      <widget name="ExportButton"/>
-      <widget name="SaveAsButton"/>
-      <widget name="DuplicateActionButton"/>
+      <widget name="ActionPathLabel"/>
+      <widget name="MenuIconLabel"/>
+      <widget name="MenuTooltipLabel"/>
+      <widget name="MenuLabelLabel"/>
     </widgets>
   </object>
 </interface>



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