[nautilus-actions] Review keep last user choice when importing items



commit 1c29f9afb232c4d5daeef7c2b7edb86e282f6cf2
Author: Pierre Wieser <pwieser trychlos org>
Date:   Fri Jul 2 08:00:40 2010 +0200

    Review keep last user choice when importing items

 ChangeLog                              |   34 ++++++
 data/nautilus-actions-prefs.schemas.in |   19 +++-
 src/api/na-iimporter.h                 |   92 ++++++++-------
 src/core/na-iimporter.c                |   36 ++++--
 src/core/na-importer-ask.c             |   50 +++++---
 src/core/na-importer-ask.h             |   16 ++-
 src/core/na-importer.c                 |  205 +++++++++++++++++++++-----------
 src/core/na-importer.h                 |   41 +++++--
 src/core/na-iprefs.h                   |    1 +
 src/core/na-object-id.c                |    7 +-
 src/core/na-object-item.c              |    8 +-
 src/core/na-object-profile.c           |    6 +-
 src/io-xml/naxml-provider.c            |    2 +-
 src/io-xml/naxml-reader.c              |   54 ++++++---
 src/io-xml/naxml-reader.h              |    2 +-
 src/nact/nact-assistant-import.c       |  135 +++++++++------------
 src/nact/nact-tree-model-dnd.c         |   70 +++++++----
 src/test/test-reader.c                 |   22 ++--
 18 files changed, 504 insertions(+), 296 deletions(-)
---
diff --git a/ChangeLog b/ChangeLog
index f326bd8..f1e3a7f 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,37 @@
+2010-07-02 Pierre Wieser <pwieser trychlos org>
+
+	* data/nautilus-actions-prefs.schemas.in:
+	* src/core/na-iprefs.h:
+	* src/core/na-importer-ask.c:
+	* src/core/na-importer-ask.h:
+	Define a new GConf preference 'keep last user choice'.
+
+	* src/api/na-iimporter.h:
+	* src/core/na-iimporter.c:
+	from_uri() interface is renamed as import_from_uri().
+	Only define na_iimporter_import_from_uri() public API.
+
+	* src/core/na-importer.c:
+	* src/core/na-importer.h:
+	Define here na_importer_import_from_list() internal API.
+
+	* src/io-xml/naxml-provider.c:
+	* src/io-xml/naxml-reader.c:
+	* src/io-xml/naxml-reader.h:
+	* src/nact/nact-assistant-import.c:
+	* src/nact/nact-tree-model-dnd.c:
+	* src/test/test-reader.c: Updated accordingly.
+
+	* src/core/na-object-id.c (na_object_id_set_new_id):
+	Fix object type test.
+
+	* src/core/na-object-item.c (object_id_new_id):
+	Fix minor typo.
+
+	* src/core/na-object-profile.c (object_id_new_id):
+	Fix order of validity test.
+	Only get a new profile name when a new parent is provided.
+
 2010-06-29 Pierre Wieser <pwieser trychlos org>
 
 	* src/nact/nact-tree-model-dnd.c (drop_uri_list):
diff --git a/data/nautilus-actions-prefs.schemas.in b/data/nautilus-actions-prefs.schemas.in
index 611a0d0..e40388f 100644
--- a/data/nautilus-actions-prefs.schemas.in
+++ b/data/nautilus-actions-prefs.schemas.in
@@ -129,8 +129,8 @@ Possible values are:
       <type>list</type>
       <list_type>int</list_type>
       <locale name="C">
-        <short>Position and size of the import assistant window</short>
-        <long>Position and size of the import assistant window ; default is set by the window manager.</long>
+        <short>Position and size of the interaction dialog at import time</short>
+        <long>Position and size of the interaction dialog at import time ; default is set by the window manager.</long>
       </locale>
       <default>[]</default>
     </schema>
@@ -155,8 +155,8 @@ Possible values are:
       <type>list</type>
       <list_type>int</list_type>
       <locale name="C">
-        <short>Position and size of the interaction dialog at import time</short>
-        <long>Position and size of the interaction dialog at import time ; default is set by the window manager.</long>
+        <short>Position and size of the import assistant window</short>
+        <long>Position and size of the import assistant window ; default is set by the window manager.</long>
       </locale>
       <default>[]</default>
     </schema>
@@ -173,6 +173,17 @@ Possible values are:
     </schema>
 
     <schema>
+      <key>/schemas/apps/nautilus-actions/preferences/import-keep-choicee</key>
+      <owner>nautilus-actions</owner>
+      <type>bool</type>
+      <locale name="C">
+        <short>Keep last choosen import mode</short>
+        <long>Whether the import system should reuse the last choosen import mode.</long>
+      </locale>
+      <default>false</default>
+    </schema>
+
+    <schema>
       <key>/schemas/apps/nautilus-actions/preferences/import-mode</key>
       <owner>nautilus-actions</owner>
       <type>string</type>
diff --git a/src/api/na-iimporter.h b/src/api/na-iimporter.h
index 32cd145..7a5aace 100644
--- a/src/api/na-iimporter.h
+++ b/src/api/na-iimporter.h
@@ -36,13 +36,11 @@
  * @short_description: #NAIImporter interface definition.
  * @include: nautilus-actions/na-iimporter.h
  *
- * The #NAIImporter interface imports  items from the outside world.
+ * The #NAIImporter interface imports items from the outside world.
  *
  * Nautilus-Actions v 2.30 - API version:  1
  */
 
-#include <gtk/gtk.h>
-
 #include "na-object-item.h"
 
 G_BEGIN_DECLS
@@ -52,11 +50,10 @@ G_BEGIN_DECLS
 #define NA_IS_IIMPORTER( instance )				( G_TYPE_CHECK_INSTANCE_TYPE( instance, NA_IIMPORTER_TYPE ))
 #define NA_IIMPORTER_GET_INTERFACE( instance )	( G_TYPE_INSTANCE_GET_INTERFACE(( instance ), NA_IIMPORTER_TYPE, NAIImporterInterface ))
 
-typedef struct NAIImporter                 NAIImporter;
-typedef struct NAIImporterUriParms         NAIImporterUriParms;
-typedef struct NAIImporterListParms        NAIImporterListParms;
+typedef struct NAIImporter                   NAIImporter;
+typedef struct NAIImporterInterfacePrivate   NAIImporterInterfacePrivate;
 
-typedef struct NAIImporterInterfacePrivate NAIImporterInterfacePrivate;
+typedef struct NAIImporterImportFromUriParms NAIImporterImportFromUriParms;
 
 typedef struct {
 	GTypeInterface               parent;
@@ -70,18 +67,18 @@ typedef struct {
 	 *
 	 * Defaults to 1.
 	 */
-	guint ( *get_version )( const NAIImporter *instance );
+	guint ( *get_version )    ( const NAIImporter *instance );
 
 	/**
 	 * import_from_uri:
 	 * @instance: the #NAIImporter provider.
-	 * @parms: a #NAIImporterUriParms structure.
+	 * @parms: a #NAIImporterImportFromUriParms structure.
 	 *
 	 * Imports an item.
 	 *
 	 * Returns: the return code of the operation.
 	 */
-	guint ( *from_uri )   ( const NAIImporter *instance, NAIImporterUriParms *parms );
+	guint ( *import_from_uri )( const NAIImporter *instance, NAIImporterImportFromUriParms *parms );
 }
 	NAIImporterInterface;
 
@@ -106,50 +103,61 @@ enum {
 	IMPORTER_CODE_CANCELLED
 };
 
-/* the function which should be provided by the caller in order the
- * #NAIImporter provider be able to check for pre-existance of the
- * imported item
- *
- * the function should return the already existing item which has the
+/**
+ * This function may be provided by the caller in order the #NAIImporter
+ * provider be able to check for pre-existence of the imported item.
+ * This function should return the already existing item which has the
  * same id than the currently being imported one, or %NULL if the
- * imported id will be unique
+ * imported id will be unique.
+ * If this function is not provided, then the #NAIImporter provider will not
+ * be able to check for duplicates. In this case, the id of the imported item
+ * should be systematically regenerated as a unique id (uuid), regardless of
+ * the asked import mode.
+ *
+ * (E): - currently imported item
+ *      - fn_data
+ * (S): - already existing item with same id, or %NULL.
  */
-typedef NAObjectItem * ( *NAIImporterCheckFn )( const NAObjectItem *, const void *fn_data );
+typedef NAObjectItem * ( *NAIImporterCheckFn )  ( const NAObjectItem *, void *fn_data );
 
-/* parameters via a structure
- * ... when importing a single uri
+/**
+ * This function may be provided by the caller in order the #NAIImporter
+ * provider be able to ask the user to know what to do in the case of a
+ * duplicate id.
+ * This function should return an mode import (not ASK!).
+ * If this function is not provided, then the #NAIImporter provider will
+ * not be able to ask the user. In this case, the duplicated id should be
+ * systematically regenerated as a unique id (uuid).
+ *
+ * (E): - currently imported item
+ *      - already existing item with same id
+ *      - fn_data
+ * (S): - import mode choosen by the user
  */
-struct NAIImporterUriParms {
-	guint              version;			/* i 1: version of this structure */
-	gchar             *uri;				/* i 1: uri of the file to be imported */
-	guint              mode;			/* i 1: import mode */
-	GtkWindow         *window;			/* i 1: a window which will act as a parent of the ask dialog */
-	NAObjectItem      *imported;		/*  o1: eventually imported NAObjectItem-derived object */
-	NAIImporterCheckFn check_fn;		/* i 1: a function to check the existance of the imported item */
-	void              *check_fn_data;	/* i 1: data function */
-	GSList            *messages;		/* io1: a #GSList list of localized strings;
-										 *       the provider may append messages to this list,
-										 *       but shouldn't reinitialize it. */
-};
+typedef guint          ( *NAIImporterAskUserFn )( const NAObjectItem *, const NAObjectItem *, void *fn_data );
 
-/* ... when importing a list of uris
+/*
+ * parameters used in input/output are passed or received through a single structure
  */
-struct NAIImporterListParms {
-	guint              version;			/* i 1: version of this structure */
-	GSList            *uris;			/* i 1: list of uris of the files to be imported */
-	guint              mode;			/* i 1: import mode */
-	GtkWindow         *window;			/* i 1: a window which will act as a parent of the ask dialog */
-	GList             *imported;		/*  o1: list of eventually imported NAObjectItem-derived objects */
-	NAIImporterCheckFn check_fn;		/* i 1: a function to check the existance of each imported item */
-	void              *check_fn_data;	/* i 1: data function */
-	GSList            *messages;		/* io1: a #GSList list of localized strings;
+struct NAIImporterImportFromUriParms {
+	guint                version;		/* i 1: version of this structure */
+	gchar               *uri;			/* i 1: uri of the file to be imported */
+	guint                asked_mode;	/* i 1: asked import mode */
+	gboolean             exist;			/*  o1: whether the imported Id already existed */
+	guint                import_mode;	/*  o1: actually used import mode */
+	NAObjectItem        *imported;		/*  o1: the imported NAObjectItem-derived object, or %NULL */
+	NAIImporterCheckFn   check_fn;		/* i 1: a function to check the existence of the imported id */
+	void                *check_fn_data;	/* i 1: data function */
+	NAIImporterAskUserFn ask_fn;		/* i 1: a function to ask the user what to do in case of a duplicate id */
+	void                *ask_fn_data;	/* i 1: data function */
+	GSList              *messages;		/* io1: a #GSList list of localized strings;
 										 *       the provider may append messages to this list,
 										 *       but shouldn't reinitialize it. */
 };
 
 GType na_iimporter_get_type( void );
 
-guint na_iimporter_ask_user( const NAIImporter *importer, const NAIImporterUriParms *parms, const NAObjectItem *existing );
+guint na_iimporter_import_from_uri( const NAIImporter *importer, NAIImporterImportFromUriParms *parms );
 
 G_END_DECLS
 
diff --git a/src/core/na-iimporter.c b/src/core/na-iimporter.c
index 1ade8b7..f57eebd 100644
--- a/src/core/na-iimporter.c
+++ b/src/core/na-iimporter.c
@@ -34,8 +34,6 @@
 
 #include <api/na-iimporter.h>
 
-#include "na-importer-ask.h"
-
 /* private interface data
  */
 struct NAIImporterInterfacePrivate {
@@ -112,7 +110,7 @@ interface_base_init( NAIImporterInterface *klass )
 		klass->private = g_new0( NAIImporterInterfacePrivate, 1 );
 
 		klass->get_version = iimporter_get_version;
-		klass->from_uri = NULL;
+		klass->import_from_uri = NULL;
 
 		iimporter_initialized = TRUE;
 	}
@@ -140,22 +138,34 @@ iimporter_get_version( const NAIImporter *instance )
 }
 
 /**
- * na_iimporter_ask_user:
+ * na_iimporter_import_from_uri:
  * @importer: this #NAIImporter instance.
- * @parms: a #NAIImporterUriParms structure.
- * @existing: the #NAObjectItem-derived already existing object.
+ * @parms: a #NAIImporterImportFromUriParms structure.
  *
- * Ask the user for what to do when an imported item has the same ID
- * that an already existing one.
+ * Tries to import a #NAObjectItem from the URI specified in @parms, returning
+ * the result in @parms->imported.
  *
- * Returns: the definitive import mode.
+ * Returns: the return code of the operation.
  */
+
 guint
-na_iimporter_ask_user( const NAIImporter *importer, const NAIImporterUriParms *parms, const NAObjectItem *existing )
+na_iimporter_import_from_uri( const NAIImporter *importer, NAIImporterImportFromUriParms *parms )
 {
-	guint mode;
+	static const gchar *thisfn = "na_iimporter_import_from_uri";
+	guint code;
+
+	g_return_val_if_fail( NA_IS_IIMPORTER( importer ), IMPORTER_CODE_PROGRAM_ERROR );
+
+	code = IMPORTER_CODE_NOT_WILLING_TO;
 
-	mode = na_importer_ask_user( parms, existing );
+	if( iimporter_initialized && !iimporter_finalized ){
+
+		g_debug( "%s: importer=%p, parms=%p", thisfn, ( void * ) importer, ( void * ) parms );
+
+		if( NA_IIMPORTER_GET_INTERFACE( importer )->import_from_uri ){
+			code = NA_IIMPORTER_GET_INTERFACE( importer )->import_from_uri( importer, parms );
+		}
+	}
 
-	return( mode );
+	return( code );
 }
diff --git a/src/core/na-importer-ask.c b/src/core/na-importer-ask.c
index b808c04..e71a1ac 100644
--- a/src/core/na-importer-ask.c
+++ b/src/core/na-importer-ask.c
@@ -36,6 +36,8 @@
 #include <glib/gi18n.h>
 #include <gtk/gtk.h>
 
+#include <api/na-gconf-utils.h>
+#include <api/na-iimporter.h>
 #include <api/na-object-api.h>
 
 #include "na-gtk-utils.h"
@@ -51,14 +53,15 @@ struct NAImporterAskClassPrivate {
 /* private instance data
  */
 struct NAImporterAskPrivate {
-	gboolean          dispose_has_run;
-	GtkBuilder       *builder;
-	GtkWindow        *toplevel;
-	NAIImporterUriParms *parms;
-	NAObjectItem     *existing;
-	guint             mode;
-	GConfClient      *gconf;
-	gint              dialog_code;
+	gboolean                dispose_has_run;
+	GtkBuilder             *builder;
+	GtkWindow              *toplevel;
+	NAObjectItem           *importing;
+	NAObjectItem           *existing;
+	NAImporterAskUserParms *parms;
+	guint                   mode;
+	GConfClient            *gconf;
+	gint                    dialog_code;
 };
 
 static GtkDialogClass *st_parent_class = NULL;
@@ -199,6 +202,7 @@ instance_finalize( GObject *dialog )
 	g_return_if_fail( NA_IS_IMPORTER_ASK( dialog ));
 
 	g_debug( "%s: dialog=%p", thisfn, ( void * ) dialog );
+
 	self = NA_IMPORTER_ASK( dialog );
 
 	g_free( self->private );
@@ -233,24 +237,27 @@ import_ask_new()
  * becomes his preference import mode.
  */
 guint
-na_importer_ask_user( const NAIImporterUriParms *parms, const NAObjectItem *existing )
+na_importer_ask_user( const NAObjectItem *importing, const NAObjectItem *existing, NAImporterAskUserParms *parms )
 {
 	static const gchar *thisfn = "na_importer_ask_user";
 	NAImporterAsk *dialog;
 	guint mode;
 	gint code;
 
+	g_return_val_if_fail( NA_IS_OBJECT_ITEM( importing ), IMPORTER_MODE_NO_IMPORT );
 	g_return_val_if_fail( NA_IS_OBJECT_ITEM( existing ), IMPORTER_MODE_NO_IMPORT );
 
-	g_debug( "%s: parms=%p, existing=%p", thisfn, ( void * ) parms, ( void * ) existing );
+	g_debug( "%s: importing=%p, existing=%p, parms=%p",
+			thisfn, ( void * ) importing, ( void * ) existing, ( void * ) parms );
 
 	mode = IMPORTER_MODE_NO_IMPORT;
 	dialog = import_ask_new();
 
 	if( dialog->private->toplevel ){
 
-		dialog->private->parms = ( NAIImporterUriParms * ) parms;
+		dialog->private->importing = ( NAObjectItem * ) importing;
 		dialog->private->existing = ( NAObjectItem * ) existing;
+		dialog->private->parms = parms;
 		dialog->private->mode = na_iprefs_get_import_mode( dialog->private->gconf, IPREFS_IMPORT_ASK_LAST_MODE );
 
 		init_dialog( dialog );
@@ -286,10 +293,10 @@ init_dialog( NAImporterAsk *editor )
 
 	g_debug( "%s: editor=%p", thisfn, ( void * ) editor );
 
-	imported_label = na_object_get_label( editor->private->parms->imported );
+	imported_label = na_object_get_label( editor->private->importing );
 	existing_label = na_object_get_label( editor->private->existing );
 
-	if( NA_IS_OBJECT_ACTION( editor->private->parms->imported )){
+	if( NA_IS_OBJECT_ACTION( editor->private->importing )){
 		/* i18n: The action <action_label> imported from <file> has the same id than <existing_label> */
 		label = g_strdup_printf(
 				_( "The action \"%s\" imported from \"%s\" has the same identifiant than the already existing \"%s\"." ),
@@ -323,7 +330,7 @@ init_dialog( NAImporterAsk *editor )
 	gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON( button ), TRUE );
 
 	button = na_gtk_utils_search_for_child_widget( GTK_CONTAINER( editor->private->toplevel ), "AskKeepChoiceButton" );
-	gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON( button ), FALSE );
+	gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON( button ), editor->private->parms->keep_choice );
 
 	button = na_gtk_utils_search_for_child_widget( GTK_CONTAINER( editor->private->toplevel ), "OKButton" );
 	g_signal_connect(
@@ -339,8 +346,8 @@ init_dialog( NAImporterAsk *editor )
 			G_CALLBACK( on_cancel_clicked ),
 			editor );
 
-	if( editor->private->parms->window ){
-		gtk_window_set_transient_for( editor->private->toplevel, editor->private->parms->window );
+	if( editor->private->parms->parent ){
+		gtk_window_set_transient_for( editor->private->toplevel, editor->private->parms->parent );
 	}
 
 	gtk_widget_show_all( GTK_WIDGET( editor->private->toplevel ));
@@ -350,7 +357,9 @@ static void
 on_cancel_clicked( GtkButton *button, NAImporterAsk *editor )
 {
 	g_debug( "na_importer_ask_on_cancel_clicked" );
+
 	editor->private->dialog_code = GTK_RESPONSE_CANCEL;
+
 	gtk_dialog_response( GTK_DIALOG( editor ), GTK_RESPONSE_CANCEL );
 }
 
@@ -358,7 +367,9 @@ static void
 on_ok_clicked( GtkButton *button, NAImporterAsk *editor )
 {
 	g_debug( "na_importer_ask_on_ok_clicked" );
+
 	editor->private->dialog_code = GTK_RESPONSE_OK;
+
 	gtk_dialog_response( GTK_DIALOG( editor ), GTK_RESPONSE_OK );
 }
 
@@ -368,6 +379,7 @@ get_selected_mode( NAImporterAsk *editor )
 	guint import_mode;
 	GtkWidget *button;
 	gboolean keep;
+	gchar *path;
 
 	import_mode = IMPORTER_MODE_NO_IMPORT;
 
@@ -387,9 +399,9 @@ get_selected_mode( NAImporterAsk *editor )
 
 	button = na_gtk_utils_search_for_child_widget( GTK_CONTAINER( editor->private->toplevel ), "AskKeepChoiceButton" );
 	keep = gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON( button ));
-	if( keep ){
-		na_iprefs_set_import_mode( editor->private->gconf, IPREFS_IMPORT_ITEMS_IMPORT_MODE, import_mode );
-	}
+	path = gconf_concat_dir_and_key( IPREFS_GCONF_PREFS_PATH, IPREFS_IMPORT_KEEP_CHOICE );
+	na_gconf_utils_write_bool( editor->private->gconf, path, keep, NULL );
+	g_free( path );
 }
 
 /*
diff --git a/src/core/na-importer-ask.h b/src/core/na-importer-ask.h
index fc0fb5e..e8bc8dd 100644
--- a/src/core/na-importer-ask.h
+++ b/src/core/na-importer-ask.h
@@ -41,10 +41,12 @@
  * want to be ask to known what to do with it.
  */
 
-#include <api/na-iimporter.h>
-
 G_BEGIN_DECLS
 
+#include <gtk/gtk.h>
+
+#include <api/na-object-item.h>
+
 #define NA_IMPORTER_ASK_TYPE				( na_importer_ask_get_type())
 #define NA_IMPORTER_ASK( object )			( G_TYPE_CHECK_INSTANCE_CAST( object, NA_IMPORTER_ASK_TYPE, NAImporterAsk ))
 #define NA_IMPORTER_ASK_CLASS( klass )		( G_TYPE_CHECK_CLASS_CAST( klass, NA_IMPORTER_ASK_TYPE, NAImporterAskClass ))
@@ -68,9 +70,17 @@ typedef struct {
 }
 	NAImporterAskClass;
 
+typedef struct {
+	GtkWindow    *parent;
+	gchar        *uri;
+	guint         count;
+	gboolean      keep_choice;
+}
+	NAImporterAskUserParms;
+
 GType na_importer_ask_get_type( void );
 
-guint na_importer_ask_user( const NAIImporterUriParms *parms, const NAObjectItem *existing );
+guint na_importer_ask_user( const NAObjectItem *importing, const NAObjectItem *existing, NAImporterAskUserParms *parms );
 
 G_END_DECLS
 
diff --git a/src/core/na-importer.c b/src/core/na-importer.c
index cf58f56..5a8c0b1 100644
--- a/src/core/na-importer.c
+++ b/src/core/na-importer.c
@@ -34,136 +34,183 @@
 
 #include <string.h>
 
+#include <api/na-core-utils.h>
 #include <api/na-object-api.h>
 
+#include "na-iprefs.h"
 #include "na-importer.h"
+#include "na-importer-ask.h"
+
+typedef struct {
+	GList             *just_imported;
+	NAIImporterCheckFn check_fn;
+	void              *check_fn_data;
+}
+	ImporterExistsStr;
 
 extern gboolean iimporter_initialized;		/* defined in na-iimporter.c */
 extern gboolean iimporter_finalized;		/* defined in na-iimporter.c */
 
-static NAObjectItem *is_importing_already_exists( const NAObjectItem *importing, const NAIImporterListParms *parms );
+static guint         import_from_uri( const NAPivot *pivot, GList *modules, NAImporterParms *parms, const gchar *uri, NAImporterResult **result );
+static NAObjectItem *is_importing_already_exists( const NAObjectItem *importing, ImporterExistsStr *parms );
+static guint         ask_user_for_mode( const NAObjectItem *importing, const NAObjectItem *existing, NAImporterAskUserParms *parms );
 
 /**
- * na_importer_import_from_uri:
+ * na_importer_import_from_list:
  * @pivot: the #NAPivot pivot for this application.
- * @parms: a #NAIImporterUriParms structure.
+ * @parms: a #NAImporterParms structure.
+ *
+ * Imports a list of URIs.
+ *
+ * For each URI to import, we search through the available #NAIImporter
+ * providers until the first which respond something different from
+ * "not_willing_to" code.
+ *
+ * Each import operation will have its corresponding newly allocated
+ * #NAImporterResult structure which will contain:
+ * - the imported URI
+ * - a #NAObjectItem item if import was successfull, or %NULL
+ * - a list of error messages, or %NULL.
  *
- * Returns: the import operation code.
+ * Returns: the last import operation code.
+ */
+/*
+ * Importing a list of URIs:
+ * if asked mode is 'ask', then ask the user at least the first time
+ * the 'keep my choice' is active or not, depending of the last time used
+ * then the 'keep my chose' is kept for other times
+ * so preferences are:
+ * - asked import mode (may be 'ask') -> import-mode
+ * - keep my choice                   -> import-keep-choice
+ * - last choosen import mode         -> import-ask-user-last-mode
  */
 guint
-na_importer_import_from_uri( const NAPivot *pivot, NAIImporterUriParms *parms )
+na_importer_import_from_list( const NAPivot *pivot, NAImporterParms *parms )
 {
-	static const gchar *thisfn = "na_importer_import_from_uri";
-	GList *modules, *im;
+	static const gchar *thisfn = "na_importer_import_from_list";
+	GList *modules;
+	GSList *iuri;
+	NAImporterResult *result;
 	guint code;
 
 	g_return_val_if_fail( NA_IS_PIVOT( pivot ), IMPORTER_CODE_PROGRAM_ERROR );
 
-	code = IMPORTER_CODE_PROGRAM_ERROR;
+	code = IMPORTER_CODE_NOT_WILLING_TO;
+	parms->results = NULL;
 
 	if( iimporter_initialized && !iimporter_finalized ){
 
 		g_debug( "%s: pivot=%p, parms=%p", thisfn, ( void * ) pivot, ( void * ) parms );
 
-		code = IMPORTER_CODE_NOT_WILLING_TO;
 		modules = na_pivot_get_providers( pivot, NA_IIMPORTER_TYPE );
 
-		for( im = modules ; im && code == IMPORTER_CODE_NOT_WILLING_TO ; im = im->next ){
-
-			if( NA_IIMPORTER_GET_INTERFACE( NA_IIMPORTER( im->data ))->from_uri ){
-				code = NA_IIMPORTER_GET_INTERFACE( NA_IIMPORTER( im->data ))->from_uri( NA_IIMPORTER( im->data ), parms );
-			}
+		for( iuri = parms->uris ; iuri ; iuri = iuri->next ){
+			code = import_from_uri( pivot, modules, parms, ( const gchar * ) iuri->data, &result );
+			parms->results = g_list_prepend( parms->results, result );
 		}
 
 		na_pivot_free_providers( modules );
+		parms->results = g_list_reverse( parms->results );
 	}
 
 	return( code );
 }
 
 /**
- * na_importer_import_from_list:
- * @pivot: the #NAPivot pivot for this application.
- * @parms: a #NAIImporterListParms structure.
- *
- * Imports a list of URIs.
- *
- * Each successfully imported #NAObjectItem-derived object is added to
- * the 'imported' list of the structure, in the same order than the URIs.
- *
- * Messages which may be generated by each individual import operation
- * are added to the 'messages' member of @parms.
+ * na_importer_free_result:
+ * @result: the #NAImporterResult structure to be released.
  *
- * Returns: the last import operation code.
+ * Release the structure.
  */
-guint
-na_importer_import_from_list( const NAPivot *pivot, NAIImporterListParms *parms )
+void
+na_importer_free_result( NAImporterResult *result )
 {
-	static const gchar *thisfn = "na_importer_import_from_list";
-	GSList *iuri;
-	NAIImporterUriParms uri_parms;
-	guint code;
-
-	g_return_val_if_fail( NA_IS_PIVOT( pivot ), IMPORTER_CODE_PROGRAM_ERROR );
+	g_free( result->uri );
+	na_core_utils_slist_free( result->messages );
 
-	code = IMPORTER_CODE_PROGRAM_ERROR;
-	parms->imported = NULL;
-
-	if( iimporter_initialized && !iimporter_finalized ){
-
-		g_debug( "%s: pivot=%p, parms=%p", thisfn, ( void * ) pivot, ( void * ) parms );
-
-		code = IMPORTER_CODE_NOT_WILLING_TO;
-
-		uri_parms.version = 1;
-		uri_parms.mode = parms->mode;
-		uri_parms.window = parms->window;
-		uri_parms.check_fn = ( NAIImporterCheckFn ) is_importing_already_exists;
-		uri_parms.check_fn_data = parms;
-		uri_parms.messages = parms->messages;
-
-		for( iuri = parms->uris ; iuri ; iuri = iuri->next ){
-
-			uri_parms.uri = ( gchar * ) iuri->data;
-			uri_parms.imported = NULL;
-
-			code = na_importer_import_from_uri( pivot, &uri_parms );
-
-			if( uri_parms.imported ){
-				parms->imported = g_list_prepend( parms->imported, uri_parms.imported );
-			}
-		}
+	g_free( result );
+}
 
-		parms->imported = g_list_reverse( parms->imported );
+static guint
+import_from_uri( const NAPivot *pivot, GList *modules, NAImporterParms *parms, const gchar *uri, NAImporterResult **result )
+{
+	guint code;
+	GList *im;
+	NAIImporterImportFromUriParms provider_parms;
+	ImporterExistsStr exists_parms;
+	NAImporterAskUserParms ask_parms;
+
+	code = IMPORTER_CODE_NOT_WILLING_TO;
+
+	memset( &exists_parms, '\0', sizeof( ImporterExistsStr ));
+	exists_parms.just_imported = parms->results;
+	exists_parms.check_fn = parms->check_fn;
+	exists_parms.check_fn_data = parms->check_fn_data;
+
+	memset( &ask_parms, '\0', sizeof( NAImporterAskUserParms ));
+	ask_parms.parent = parms->parent;
+	ask_parms.uri = ( gchar * ) uri;
+	ask_parms.count = g_list_length( parms->results );
+	ask_parms.keep_choice = na_iprefs_read_bool( NA_IPREFS( pivot ), IPREFS_IMPORT_KEEP_CHOICE, FALSE );
+
+	memset( &provider_parms, '\0', sizeof( NAIImporterImportFromUriParms ));
+	provider_parms.version = 1;
+	provider_parms.uri = ( gchar * ) uri;
+	provider_parms.asked_mode = parms->mode;
+	provider_parms.check_fn = ( NAIImporterCheckFn ) is_importing_already_exists;
+	provider_parms.check_fn_data = &exists_parms;
+	provider_parms.ask_fn = ( NAIImporterAskUserFn ) ask_user_for_mode;
+	provider_parms.ask_fn_data = &ask_parms;
+
+	for( im = modules ; im && code == IMPORTER_CODE_NOT_WILLING_TO ; im = im->next ){
+		code = na_iimporter_import_from_uri( NA_IIMPORTER( im->data ), &provider_parms );
 	}
 
+	*result = g_new0( NAImporterResult, 1 );
+	( *result )->uri = g_strdup( uri );
+	( *result )->mode = provider_parms.import_mode;
+	( *result )->exist = provider_parms.exist;
+	( *result )->imported = provider_parms.imported;
+	( *result )->messages = provider_parms.messages;
+
 	return( code );
 }
 
+/*
+ * to see if an imported item already exists, we have to check
+ * - the current list of just imported items
+ * - the main window (if any), which contains the in-memory list of items
+ * - the tree in pivot which contains the 'actual' items
+ */
 static NAObjectItem *
-is_importing_already_exists( const NAObjectItem *importing, const NAIImporterListParms *parms )
+is_importing_already_exists( const NAObjectItem *importing, ImporterExistsStr *parms )
 {
+	static const gchar *thisfn = "na_importer_is_importing_already_exists";
 	NAObjectItem *exists;
 	GList *ip;
 
 	exists = NULL;
 	gchar *importing_id = na_object_get_id( importing );
-	g_debug( "na_importer_is_importing_already_exists: importing_id=%s", importing_id );
+	g_debug( "%s: importing=%p, id=%s", thisfn, ( void * ) importing, importing_id );
 
 	/* is the importing item already in the current importation list ?
 	 */
-	for( ip = parms->imported ; ip && !exists ; ip = ip->next ){
-		gchar *id = na_object_get_id( ip->data );
-		if( !strcmp( importing_id, id )){
-			exists = NA_OBJECT_ITEM( ip->data );
+	for( ip = parms->just_imported ; ip && !exists ; ip = ip->next ){
+		NAImporterResult *result = ( NAImporterResult * ) ip->data;
+
+		if( result->imported ){
+			gchar *id = na_object_get_id( result->imported );
+			if( !strcmp( importing_id, id )){
+				exists = NA_OBJECT_ITEM( result->imported );
+			}
+			g_free( id );
 		}
-		g_free( id );
 	}
 
 	g_free( importing_id );
 
 	/* if not found in our current importation list,
-	 * then check the via provided function and data
+	 * then check the existence via provided function and data
 	 */
 	if( !exists ){
 		exists = parms->check_fn( importing, parms->check_fn_data );
@@ -171,3 +218,21 @@ is_importing_already_exists( const NAObjectItem *importing, const NAIImporterLis
 
 	return( exists );
 }
+
+static guint
+ask_user_for_mode( const NAObjectItem *importing, const NAObjectItem *existing, NAImporterAskUserParms *parms )
+{
+	guint mode;
+	GConfClient *gconf;
+
+	if( parms->count == 0 || !parms->keep_choice ){
+		mode = na_importer_ask_user( importing, existing, parms );
+
+	} else {
+		gconf = gconf_client_get_default();
+		mode = na_iprefs_get_import_mode( gconf, IPREFS_IMPORT_ASK_LAST_MODE );
+		g_object_unref( gconf );
+	}
+
+	return( mode );
+}
diff --git a/src/core/na-importer.h b/src/core/na-importer.h
index 12b6e9d..dfb3a9a 100644
--- a/src/core/na-importer.h
+++ b/src/core/na-importer.h
@@ -28,26 +28,49 @@
  *   ... and many others (see AUTHORS)
  */
 
-#ifndef __NACT_NA_IMPORTER_H__
-#define __NACT_NA_IMPORTER_H__
+#ifndef __CORE_NA_IMPORTER_H__
+#define __CORE_NA_IMPORTER_H__
 
 /**
- * SECTION: na_iimport
- * @short_description: #NAIImport internal functions.
- * @include: nact/na-import.h
+ * SECTION: na_iimporter
+ * @short_description: #NAIImporter internal functions.
+ * @include: core/na-importer.h
  */
 
-#include <api/na-object-item.h>
+#include <gtk/gtk.h>
+
 #include <api/na-iimporter.h>
+#include <api/na-object-item.h>
 
 #include <core/na-pivot.h>
 
 G_BEGIN_DECLS
 
-guint na_importer_import_from_uri ( const NAPivot *pivot, NAIImporterUriParms *parms );
+typedef struct {
+	GtkWindow         *parent;			/* the parent window, if any */
+	GSList            *uris;			/* the list of uris of the files to be imported */
+	guint              mode;			/* asked import mode */
+	NAIImporterCheckFn check_fn;		/* a function to check the existence of the imported id */
+	void              *check_fn_data;	/* data function */
+	GList             *results;			/* a #GList of newly allocated NAImporterResult structures,
+										   one for each imported uri, which should be
+										   na_importer_free_result() by the caller */
+}
+	NAImporterParms;
+
+typedef struct {
+	gchar             *uri;				/* the imported uri */
+	guint              mode;			/* the actual import mode in effect for this import */
+	gboolean           exist;			/* whether the imported Id already existed */
+	NAObjectItem      *imported;		/* eventually imported NAObjectItem-derived object, or %NULL */
+	GSList            *messages;		/* a #GSList list of localized strings */
+}
+	NAImporterResult;
+
+guint na_importer_import_from_list( const NAPivot *pivot, NAImporterParms *parms );
 
-guint na_importer_import_from_list( const NAPivot *pivot, NAIImporterListParms *parms );
+void  na_importer_free_result( NAImporterResult *result );
 
 G_END_DECLS
 
-#endif /* __NACT_NA_IMPORTER_H__ */
+#endif /* __CORE_NA_IMPORTER_H__ */
diff --git a/src/core/na-iprefs.h b/src/core/na-iprefs.h
index 07df107..bfc3c0e 100644
--- a/src/core/na-iprefs.h
+++ b/src/core/na-iprefs.h
@@ -103,6 +103,7 @@ typedef struct {
 #define IPREFS_RELABEL_PROFILES				"iprefs-relabel-profiles"
 
 #define IPREFS_IMPORT_ITEMS_IMPORT_MODE		"import-mode"
+#define IPREFS_IMPORT_KEEP_CHOICE			"import-keep-choice"
 #define IPREFS_IMPORT_ASK_LAST_MODE			"import-ask-user-last-mode"
 
 /* alphabetical order values
diff --git a/src/core/na-object-id.c b/src/core/na-object-id.c
index ee8cb79..239843b 100644
--- a/src/core/na-object-id.c
+++ b/src/core/na-object-id.c
@@ -362,13 +362,18 @@ na_object_id_set_copy_of_label( NAObjectId *object )
 void
 na_object_id_set_new_id( NAObjectId *object, const NAObjectId *new_parent )
 {
+	static const gchar *thisfn = "na_object_id_set_new_id";
 	gchar *id;
 
 	g_return_if_fail( NA_IS_OBJECT_ID( object ));
-	g_return_if_fail( !new_parent || NA_IS_OBJECT_ID( new_parent ));
+	g_return_if_fail( !new_parent || NA_IS_OBJECT_ITEM( new_parent ));
 
 	if( !object->private->dispose_has_run ){
 
+		g_debug( "%s: object=%p (%s), new_parent=%p (%s)",
+				thisfn, ( void * ) object, G_OBJECT_TYPE_NAME( object ),
+				( void * ) new_parent, new_parent ? G_OBJECT_TYPE_NAME( new_parent ) : "n/a" );
+
 		id = v_new_id( object, new_parent );
 
 		if( id ){
diff --git a/src/core/na-object-item.c b/src/core/na-object-item.c
index 2256a0d..534d08a 100644
--- a/src/core/na-object-item.c
+++ b/src/core/na-object-item.c
@@ -243,7 +243,7 @@ object_copy( NAObject *target, const NAObject *source, gboolean recursive )
 static gchar *
 object_id_new_id( const NAObjectId *item, const NAObjectId *new_parent )
 {
-	GList *childs, *it;
+	GList *children, *it;
 	uuid_t uuid;
 	gchar uuid_str[64];
 	gchar *new_uuid = NULL;
@@ -252,11 +252,11 @@ object_id_new_id( const NAObjectId *item, const NAObjectId *new_parent )
 
 	if( !NA_OBJECT_ITEM( item )->private->dispose_has_run ){
 
-		/* recurse into NAObjectItems childs
+		/* recurse into NAObjectItems children
 		 * i.e., if a menu, recurse into embedded actions
 		 */
-		childs = na_object_get_items( item );
-		for( it = childs ; it ; it = it->next ){
+		children = na_object_get_items( item );
+		for( it = children ; it ; it = it->next ){
 			na_object_set_new_id( it->data, new_parent );
 		}
 
diff --git a/src/core/na-object-profile.c b/src/core/na-object-profile.c
index c56a330..b37833a 100644
--- a/src/core/na-object-profile.c
+++ b/src/core/na-object-profile.c
@@ -420,11 +420,13 @@ object_id_new_id( const NAObjectId *item, const NAObjectId *new_parent )
 	gchar *id = NULL;
 
 	g_return_val_if_fail( NA_IS_OBJECT_PROFILE( item ), NULL );
-	g_return_val_if_fail( new_parent && NA_IS_OBJECT_ACTION( new_parent ), NULL );
+	g_return_val_if_fail( !new_parent || NA_IS_OBJECT_ACTION( new_parent ), NULL );
 
 	if( !NA_OBJECT_PROFILE( item )->private->dispose_has_run ){
 
-		id = na_object_action_get_new_profile_name( NA_OBJECT_ACTION( new_parent ));
+		if( new_parent ){
+			id = na_object_action_get_new_profile_name( NA_OBJECT_ACTION( new_parent ));
+		}
 	}
 
 	return( id );
diff --git a/src/io-xml/naxml-provider.c b/src/io-xml/naxml-provider.c
index a049846..fd05dd1 100644
--- a/src/io-xml/naxml-provider.c
+++ b/src/io-xml/naxml-provider.c
@@ -203,7 +203,7 @@ iimporter_iface_init( NAIImporterInterface *iface )
 	g_debug( "%s: iface=%p", thisfn, ( void * ) iface );
 
 	iface->get_version = iimporter_get_version;
-	iface->from_uri = naxml_reader_import_from_uri;
+	iface->import_from_uri = naxml_reader_import_from_uri;
 }
 
 static guint
diff --git a/src/io-xml/naxml-reader.c b/src/io-xml/naxml-reader.c
index 95874e0..8ec44a7 100644
--- a/src/io-xml/naxml-reader.c
+++ b/src/io-xml/naxml-reader.c
@@ -74,24 +74,24 @@ typedef struct {
  * to import. We thus have one NAXMLReader object per import operation.
  */
 struct NAXMLReaderPrivate {
-	gboolean          dispose_has_run;
+	gboolean                       dispose_has_run;
 
 	/* data provided by the caller
 	 */
-	NAIImporter      *importer;
-	NAIImporterUriParms *parms;
+	NAIImporter                   *importer;
+	NAIImporterImportFromUriParms *parms;
 
 	/* data dynamically set during the import operation
 	 */
-	gboolean      type_found;
-	GList        *nodes;
-	RootNodeStr  *root_node_str;
-	gchar        *item_id;
+	gboolean                       type_found;
+	GList                         *nodes;
+	RootNodeStr                   *root_node_str;
+	gchar                         *item_id;
 
 	/* following values are reset and reused while iterating on each
 	 * element nodes of the imported item (cf. reset_node_data())
 	 */
-	gboolean      node_ok;
+	gboolean                       node_ok;
 };
 
 extern NAXMLKeyStr naxml_schema_key_schema_str[];
@@ -315,7 +315,7 @@ reader_new( void )
  * Returns: the import operation code.
  */
 guint
-naxml_reader_import_from_uri( const NAIImporter *instance, NAIImporterUriParms *parms )
+naxml_reader_import_from_uri( const NAIImporter *instance, NAIImporterImportFromUriParms *parms )
 {
 	static const gchar *thisfn = "naxml_reader_import_from_uri";
 	NAXMLReader *reader;
@@ -329,6 +329,8 @@ naxml_reader_import_from_uri( const NAIImporter *instance, NAIImporterUriParms *
 	reader->private->importer = ( NAIImporter * ) instance;
 	reader->private->parms = parms;
 
+	parms->exist = FALSE;
+	parms->import_mode = IMPORTER_MODE_NO_IMPORT;
 	parms->imported = NULL;
 
 	code = reader_parse_xmldoc( reader );
@@ -1301,30 +1303,52 @@ manage_import_mode( NAXMLReader *reader )
 
 	code = IMPORTER_CODE_OK;
 	exists = NULL;
+	mode = 0;
 
 	if( reader->private->parms->check_fn ){
 		exists = ( *reader->private->parms->check_fn )
 						( reader->private->parms->imported, reader->private->parms->check_fn_data );
+
+	} else {
+		renumber_label_item( reader );
+		add_message( reader, "%s", _( "Item was renumbered because the caller did not provide any check function." ));
+		reader->private->parms->import_mode = IMPORTER_MODE_RENUMBER;
 	}
 
 	if( exists ){
-		if( reader->private->parms->mode == IMPORTER_MODE_ASK ){
-			mode = na_iimporter_ask_user( reader->private->importer, reader->private->parms, exists );
+		reader->private->parms->exist = TRUE;
+
+		if( reader->private->parms->asked_mode == IMPORTER_MODE_ASK ){
+			if( reader->private->parms->ask_fn ){
+				mode = ( *reader->private->parms->ask_fn )( reader->private->parms->imported, exists, reader->private->parms->ask_fn_data );
+
+			} else {
+				renumber_label_item( reader );
+				add_message( reader, "%s", _( "Item was renumbered because the caller did not provide any ask user function." ));
+				reader->private->parms->import_mode = IMPORTER_MODE_RENUMBER;
+			}
 
 		} else {
-			mode = reader->private->parms->mode;
+			mode = reader->private->parms->asked_mode;
 		}
+	}
+
+	/* mode is only set if asked mode is ask user and an ask function was provided
+	 * or if asked mode was not ask user
+	 */
+	if( mode ){
+		reader->private->parms->import_mode = mode;
 
 		switch( mode ){
 			case IMPORTER_MODE_RENUMBER:
 				renumber_label_item( reader );
-				if( reader->private->parms->mode == IMPORTER_MODE_ASK ){
+				if( reader->private->parms->asked_mode == IMPORTER_MODE_ASK ){
 					add_message( reader, "%s", _( "Item was renumbered due to user request." ));
 				}
 				break;
 
 			case IMPORTER_MODE_OVERRIDE:
-				if( reader->private->parms->mode == IMPORTER_MODE_ASK ){
+				if( reader->private->parms->asked_mode == IMPORTER_MODE_ASK ){
 					add_message( reader, "%s", _( "Existing item was overriden due to user request." ));
 				}
 				break;
@@ -1333,7 +1357,7 @@ manage_import_mode( NAXMLReader *reader )
 			default:
 				id = na_object_get_id( reader->private->parms->imported );
 				add_message( reader, ERR_ITEM_ID_ALREADY_EXISTS, id );
-				if( reader->private->parms->mode == IMPORTER_MODE_ASK ){
+				if( reader->private->parms->asked_mode == IMPORTER_MODE_ASK ){
 					add_message( reader, "%s", _( "Import was canceled due to user request." ));
 				}
 				g_free( id );
diff --git a/src/io-xml/naxml-reader.h b/src/io-xml/naxml-reader.h
index 0479619..cb996f9 100644
--- a/src/io-xml/naxml-reader.h
+++ b/src/io-xml/naxml-reader.h
@@ -75,7 +75,7 @@ typedef struct {
 
 GType        naxml_reader_get_type( void );
 
-guint        naxml_reader_import_from_uri( const NAIImporter *instance, NAIImporterUriParms *parms );
+guint        naxml_reader_import_from_uri( const NAIImporter *instance, NAIImporterImportFromUriParms *parms );
 
 void         naxml_reader_read_start( const NAIFactoryProvider *provider, void *reader_data, const NAIFactoryObject *object, GSList **messages  );
 NADataBoxed *naxml_reader_read_data ( const NAIFactoryProvider *provider, void *reader_data, const NAIFactoryObject *object, const NADataDef *def, GSList **messages );
diff --git a/src/nact/nact-assistant-import.c b/src/nact/nact-assistant-import.c
index 84247b8..0dc6921 100644
--- a/src/nact/nact-assistant-import.c
+++ b/src/nact/nact-assistant-import.c
@@ -66,23 +66,6 @@ enum {
 	ASSIST_PAGE_DONE
 };
 
-/* a structure which hosts successfully imported files
- */
-typedef struct {
-	gchar        *uri;
-	NAObjectItem *item;
-	GSList       *msg;
-}
-	ImportUriStruct;
-
-/* a structure to check for existance of imported items
- */
-typedef struct {
-	NactMainWindow *window;
-	GList          *imported;
-}
-	ImportCheck;
-
 /* private class data
  */
 struct NactAssistantImportClassPrivate {
@@ -94,8 +77,7 @@ struct NactAssistantImportClassPrivate {
 struct NactAssistantImportPrivate {
 	gboolean     dispose_has_run;
 	GConfClient *gconf;
-	GSList      *results;
-	GList       *items;
+	GList       *results;
 };
 
 static BaseAssistantClass *st_parent_class = NULL;
@@ -125,9 +107,9 @@ static void          prepare_confirm( NactAssistantImport *window, GtkAssistant
 static gint          get_import_mode( NactAssistantImport *window );
 static gchar        *add_import_mode( NactAssistantImport *window, const gchar *text );
 static void          assistant_apply( BaseAssistant *window, GtkAssistant *assistant );
-static NAObjectItem *check_for_existance( const NAObjectItem *, ImportCheck *check );
+static NAObjectItem *check_for_existence( const NAObjectItem *, NactMainWindow *window );
 static void          prepare_importdone( NactAssistantImport *window, GtkAssistant *assistant, GtkWidget *page );
-static void          free_results( GSList *list );
+static void          free_results( GList *list );
 
 GType
 nact_assistant_import_get_type( void )
@@ -673,38 +655,51 @@ assistant_apply( BaseAssistant *wnd, GtkAssistant *assistant )
 {
 	static const gchar *thisfn = "nact_assistant_import_assistant_apply";
 	NactAssistantImport *window;
+	NAImporterParms import_parms;
 	GtkWidget *chooser;
-	GSList *uris, *is;
-	ImportUriStruct *str;
+	BaseWindow *main_window;
+	GList *it;
 	GList *imported_items;
-	BaseWindow *mainwnd;
-	guint mode;
+	NAImporterResult *result;
 	NactApplication *application;
 	NAUpdater *updater;
-	NAIImporterUriParms parms;
-	guint code;
-	ImportCheck check_str;
+
+	g_return_if_fail( NACT_IS_ASSISTANT_IMPORT( wnd ));
 
 	g_debug( "%s: window=%p, assistant=%p", thisfn, ( void * ) wnd, ( void * ) assistant );
-	g_assert( NACT_IS_ASSISTANT_IMPORT( wnd ));
 	window = NACT_ASSISTANT_IMPORT( wnd );
 
+	imported_items = NULL;
+	memset( &import_parms, '\0', sizeof( NAImporterParms ));
+
+	g_object_get( G_OBJECT( wnd ), BASE_WINDOW_PROP_PARENT, &main_window, NULL );
+	import_parms.parent = base_window_get_toplevel( main_window );
+
 	chooser = base_window_get_widget( BASE_WINDOW( window ), "ImportFileChooser" );
-	uris = gtk_file_chooser_get_uris( GTK_FILE_CHOOSER( chooser ));
-	mode = get_import_mode( window );
+	import_parms.uris = gtk_file_chooser_get_uris( GTK_FILE_CHOOSER( chooser ));
+	import_parms.mode = get_import_mode( window );
 
-	g_object_get( G_OBJECT( wnd ), BASE_WINDOW_PROP_PARENT, &mainwnd, NULL );
+	import_parms.check_fn = ( NAIImporterCheckFn ) check_for_existence;
+	import_parms.check_fn_data = main_window;
 
-	application = NACT_APPLICATION( base_window_get_application( BASE_WINDOW( wnd )));
+	application = NACT_APPLICATION( base_window_get_application( main_window ));
 	updater = nact_application_get_updater( application );
-	imported_items = NULL;
-	check_str.window = NACT_MAIN_WINDOW( mainwnd );
-	check_str.imported = imported_items;
+	na_importer_import_from_list( NA_PIVOT( updater ), &import_parms );
+
+	for( it = import_parms.results ; it ; it = it->next ){
+		result = ( NAImporterResult * ) it->data;
+
+		if( result->imported ){
+			na_object_check_status( result->imported );
+			imported_items = g_list_prepend( imported_items, result->imported );
+		}
+	}
 
 	/* import actions
 	 * getting results in the same order than uris
 	 * simultaneously building the actions list
 	 */
+#if 0
 	for( is = uris ; is ; is = is->next ){
 
 		parms.version = 1;
@@ -713,8 +708,6 @@ assistant_apply( BaseAssistant *wnd, GtkAssistant *assistant )
 		parms.window = base_window_get_toplevel( base_application_get_main_window( BASE_APPLICATION( application )));
 		parms.messages = NULL;
 		parms.imported = NULL;
-		parms.check_fn = ( NAIImporterCheckFn ) check_for_existance;
-		parms.check_fn_data = &check_str;
 
 		code = na_importer_import_from_uri( NA_PIVOT( updater ), &parms );
 
@@ -731,41 +724,31 @@ assistant_apply( BaseAssistant *wnd, GtkAssistant *assistant )
 
 		window->private->results = g_slist_prepend( window->private->results, str );
 	}
-	na_core_utils_slist_free( uris );
-	window->private->results = g_slist_reverse( window->private->results );
+#endif
+
+	na_core_utils_slist_free( import_parms.uris );
+	window->private->results = import_parms.results;
 
 	/* then insert the list
 	 * assuring that actions will be inserted in the same order as uris
 	 */
 	imported_items = g_list_reverse( imported_items );
-	nact_iactions_list_bis_insert_items( NACT_IACTIONS_LIST( mainwnd ), imported_items, NULL );
+	nact_iactions_list_bis_insert_items( NACT_IACTIONS_LIST( main_window ), imported_items, NULL );
 	na_object_unref_items( imported_items );
 }
 
 static NAObjectItem *
-check_for_existance( const NAObjectItem *item, ImportCheck *check )
+check_for_existence( const NAObjectItem *item, NactMainWindow *window )
 {
+	static const gchar *thisfn = "nact_assistant_import_check_for_existence";
 	NAObjectItem *exists;
-	GList *ip;
+	gchar *importing_id;
 
-	exists = NULL;
-	gchar *importing_id = na_object_get_id( item );
-	g_debug( "nact_assistant_import_check_for_existance: item=%p (%s), importing_id=%s",
-			( void * ) item, G_OBJECT_TYPE_NAME( item ), importing_id );
+	importing_id = na_object_get_id( item );
+	g_debug( "%s: item=%p (%s), importing_id=%s",
+			thisfn, ( void * ) item, G_OBJECT_TYPE_NAME( item ), importing_id );
 
-	/* is the importing item already in the current importation list ?
-	 */
-	for( ip = check->imported ; ip && !exists ; ip = ip->next ){
-		gchar *id = na_object_get_id( ip->data );
-		if( !strcmp( importing_id, id )){
-			exists = NA_OBJECT_ITEM( ip->data );
-		}
-		g_free( id );
-	}
-
-	if( !exists ){
-		exists = nact_main_window_get_item( check->window, importing_id );
-	}
+	exists = nact_main_window_get_item( window, importing_id );
 
 	g_free( importing_id );
 
@@ -778,8 +761,9 @@ prepare_importdone( NactAssistantImport *window, GtkAssistant *assistant, GtkWid
 	static const gchar *thisfn = "nact_assistant_import_prepare_importdone";
 	gchar *text, *tmp, *text2;
 	gchar *bname, *uuid, *label;
-	GSList *is, *im;
-	ImportUriStruct *str;
+	GList *is;
+	GSList *im;
+	NAImporterResult *result;
 	GFile *file;
 	guint mode;
 	GtkLabel *summary_label;
@@ -794,9 +778,9 @@ prepare_importdone( NactAssistantImport *window, GtkAssistant *assistant, GtkWid
 	text = tmp;
 
 	for( is = window->private->results ; is ; is = is->next ){
-		str = ( ImportUriStruct * ) is->data;
+		result = ( NAImporterResult * ) is->data;
 
-		file = g_file_new_for_uri( str->uri );
+		file = g_file_new_for_uri( result->uri );
 		bname = g_file_get_basename( file );
 		g_object_unref( file );
 		tmp = g_strdup_printf( "%s\t%s\n", text, bname );
@@ -804,13 +788,13 @@ prepare_importdone( NactAssistantImport *window, GtkAssistant *assistant, GtkWid
 		text = tmp;
 		g_free( bname );
 
-		if( str->item ){
+		if( result->imported ){
 			/* i18n: indicate that the file has been successfully imported */
 			tmp = g_strdup_printf( "%s\t\t%s\n", text, _( "Import OK" ));
 			g_free( text );
 			text = tmp;
-			uuid = na_object_get_id( str->item );
-			label = na_object_get_label( str->item );
+			uuid = na_object_get_id( result->imported );
+			label = na_object_get_label( result->imported );
 			/* i18n: this is the globally unique identifier and the label of the newly imported action */
 			text2 = g_strdup_printf( _( "UUID: %s\t%s" ), uuid, label);
 			g_free( label );
@@ -819,8 +803,6 @@ prepare_importdone( NactAssistantImport *window, GtkAssistant *assistant, GtkWid
 			g_free( text );
 			text = tmp;
 
-			window->private->items = g_list_prepend( window->private->items, str->item );
-
 		} else {
 			/* i18n: indicate that the file was not imported */
 			tmp = g_strdup_printf( "%s\t\t%s\n", text, _( "Not imported" ));
@@ -829,7 +811,7 @@ prepare_importdone( NactAssistantImport *window, GtkAssistant *assistant, GtkWid
 		}
 
 		/* add messages if any */
-		for( im = str->msg ; im ; im = im->next ){
+		for( im = result->messages ; im ; im = im->next ){
 			tmp = g_strdup_printf( "%s\t\t%s\n", text, ( const char * ) im->data );
 			g_free( text );
 			text = tmp;
@@ -854,16 +836,13 @@ prepare_importdone( NactAssistantImport *window, GtkAssistant *assistant, GtkWid
 }
 
 static void
-free_results( GSList *list )
+free_results( GList *list )
 {
-	GSList *is;
-	ImportUriStruct *str;
+	GList *it;
 
-	for( is = list ; is ; is = is->next ){
-		str = ( ImportUriStruct * ) is->data;
-		g_free( str->uri );
-		na_core_utils_slist_free( str->msg );
+	for( it = list ; it ; it = it->next ){
+		na_importer_free_result(( NAImporterResult * ) it->data );
 	}
 
-	g_slist_free( list );
+	g_list_free( list );
 }
diff --git a/src/nact/nact-tree-model-dnd.c b/src/nact/nact-tree-model-dnd.c
index 1c54959..2bf439e 100644
--- a/src/nact/nact-tree-model-dnd.c
+++ b/src/nact/nact-tree-model-dnd.c
@@ -795,9 +795,13 @@ drop_uri_list( NactTreeModel *model, GtkTreePath *dest, GtkSelectionData  *selec
 	NactApplication *application;
 	NAUpdater *updater;
 	NactMainWindow *main_window;
-	NAIImporterListParms parms;
+	NAImporterParms parms;
 	GConfClient *gconf;
 	GList *it;
+	guint count;
+	GString *str;
+	GSList *im;
+	GList *imported;
 
 	gchar *dest_str = gtk_tree_path_to_string( dest );
 	g_debug( "%s: model=%p, dest=%p (%s), selection_data=%p",
@@ -815,61 +819,81 @@ drop_uri_list( NactTreeModel *model, GtkTreePath *dest, GtkSelectionData  *selec
 	updater = nact_application_get_updater( application );
 	main_window = NACT_MAIN_WINDOW( base_application_get_main_window( BASE_APPLICATION( application )));
 
-	parms.version = 1;
 	g_debug( "%s", ( const gchar * ) selection_data->data );
+
+	parms.parent = base_window_get_toplevel( BASE_WINDOW( main_window ));
 	parms.uris = g_slist_reverse( na_core_utils_slist_from_split(( const gchar * ) selection_data->data, "\r\n" ));
 
 	gconf = gconf_client_get_default();
 	parms.mode = na_iprefs_get_import_mode( gconf, IPREFS_IMPORT_ITEMS_IMPORT_MODE );
 	g_object_unref( gconf );
 
-	parms.window = base_window_get_toplevel( BASE_WINDOW( main_window ));
-	parms.imported = NULL;
 	parms.check_fn = ( NAIImporterCheckFn ) is_dropped_already_exists;
 	parms.check_fn_data = main_window;
-	parms.messages = NULL;
+	parms.results = NULL;
 
 	na_importer_import_from_list( NA_PIVOT( updater ), &parms );
 
-	/* display first message in status bar
+	/* analysing output results
+	 * - first line of first message is displayed in status bar
+	 * - simultaneously build the concatenation of all lines of messages
+	 * - simultaneously build the list of imported items
 	 */
-	if( parms.messages ){
-		nact_main_statusbar_display_with_timeout(
-				main_window,
-				TREE_MODEL_STATUSBAR_CONTEXT,
-				parms.messages->data );
+	count = 0;
+	str = g_string_new( "" );
+	imported = NULL;
+
+	for( it = parms.results ; it ; it = it->next ){
+		NAImporterResult *result = ( NAImporterResult * ) it->data;
+
+		if( result->messages ){
+			if( count == 0 ){
+				nact_main_statusbar_display_with_timeout(
+						main_window,
+						TREE_MODEL_STATUSBAR_CONTEXT,
+						result->messages->data );
+			}
+			count += 1;
+			for( im = result->messages ; im ; im = im->next ){
+				g_string_append_printf( str, "%s\n", ( const gchar * ) im->data );
+			}
+		}
+
+		if( result->imported ){
+			imported = g_list_prepend( imported, result->imported );
+		}
 	}
 
 	/* if there is more than one message, display them in a dialog box
 	 */
-	if( parms.messages && g_slist_length( parms.messages ) > 1 ){
+	if( count > 1 ){
 		GtkMessageDialog *dialog = GTK_MESSAGE_DIALOG( gtk_message_dialog_new(
-				parms.window,
+				parms.parent,
 				GTK_DIALOG_MODAL, GTK_MESSAGE_WARNING, GTK_BUTTONS_CLOSE,
 				"%s", _( "Some messages have occurred during drop operation." )));
-		GString *str = g_string_new( "" );
-		GSList *im;
-		for( im = parms.messages ; im ; im = im->next ){
-			g_string_append_printf( str, "%s\n", ( const gchar * ) im->data );
-		}
 		gtk_message_dialog_format_secondary_markup( dialog, "%s", str->str );
-		g_string_free( str, TRUE );
 	}
 
+	g_string_free( str, TRUE );
+
 	/* check status of newly imported items, and insert them in the list view
 	 */
-	for( it = parms.imported ; it ; it = it->next ){
+	for( it = imported ; it ; it = it->next ){
 		na_object_check_status( it->data );
 		na_object_dump( it->data );
 		drop_done = TRUE;
 	}
 
-	nact_iactions_list_bis_insert_at_path( NACT_IACTIONS_LIST( main_window ), parms.imported, dest );
+	nact_iactions_list_bis_insert_at_path( NACT_IACTIONS_LIST( main_window ), imported, dest );
 	nact_tree_model_dump( model );
 
-	na_object_unref_items( parms.imported );
+	na_object_unref_items( imported );
 	na_core_utils_slist_free( parms.uris );
-	na_core_utils_slist_free( parms.messages );
+
+	for( it = parms.results ; it ; it = it->next ){
+		na_importer_free_result( it->data );
+	}
+	g_list_free( parms.results );
 
 	return( drop_done );
 }
diff --git a/src/test/test-reader.c b/src/test/test-reader.c
index fc42b3d..a33df11 100755
--- a/src/test/test-reader.c
+++ b/src/test/test-reader.c
@@ -64,7 +64,8 @@ static void             exit_with_usage( void );
 int
 main( int argc, char **argv )
 {
-	NAIImporterUriParms parms;
+	NAImporterParms parms;
+	NAImporterResult *result;
 
 	g_type_init();
 
@@ -79,25 +80,24 @@ main( int argc, char **argv )
 	na_pivot_load_items( pivot );
 	/* for test - end */
 
-	parms.version = 1;
-	parms.uri = uri;
+	parms.parent = NULL;
+	parms.uris = g_slist_prepend( NULL, uri );
 	parms.mode = IMPORTER_MODE_ASK;
-	parms.imported = NULL;
 	parms.check_fn = NULL;
 	parms.check_fn_data = NULL;
-	parms.messages = NULL;
 
-	guint code = na_importer_import_from_uri( pivot, &parms );
+	guint code = na_importer_import_from_list( pivot, &parms );
 
 	g_print( "%s: return code from import is %u.\n", g_get_prgname(), code );
 
-	if( parms.imported ){
-		na_object_dump( parms.imported );
-		g_object_unref( parms.imported );
+	result = parms.results->data;
+	if( result->imported ){
+		na_object_dump( result->imported );
+		g_object_unref( result->imported );
 	}
 
-	na_core_utils_slist_dump( parms.messages );
-	na_core_utils_slist_free( parms.messages );
+	na_core_utils_slist_dump( result->messages );
+	na_core_utils_slist_free( result->messages );
 
 	return( 0 );
 }



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