[nautilus-actions] Drag and drop code - not entirely ok yet



commit 8c3cf421152cb5868de16d4e4738a4ca0b5d0f73
Author: Pierre Wieser <pwieser trychlos org>
Date:   Fri Oct 2 01:11:01 2009 +0200

    Drag and drop code - not entirely ok yet

 ChangeLog                                |   24 +
 src/nact/base-application.c              |   28 ++
 src/nact/base-application.h              |    1 +
 src/nact/nact-clipboard.c                |  486 ++++++++++++-------
 src/nact/nact-clipboard.h                |   23 +-
 src/nact/nact-iactions-list.c            |   63 +++-
 src/nact/nact-iactions-list.h            |    3 +
 src/nact/nact-main-statusbar.c           |   17 +
 src/nact/nact-main-statusbar.h           |    1 +
 src/nact/nact-main-window.c              |   26 +
 src/nact/nact-main-window.h              |    1 +
 src/nact/nact-tree-model.c               |  752 ++++++++++++++++++++++--------
 src/nact/nact-tree-model.h               |    2 +-
 src/nact/nact-xml-reader.c               |    2 +-
 src/nact/nautilus-actions-config-tool.ui |   12 +-
 15 files changed, 1042 insertions(+), 399 deletions(-)
---
diff --git a/ChangeLog b/ChangeLog
index 6b87967..05475c8 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,27 @@
+2009-10-02 Pierre Wieser <pwieser trychlos org>
+
+	* src/nact/base-application.c:
+	* src/nact/base-application.h (base_application_message_dlg):
+	New function.
+
+	* src/nact/nact-clipboard.c:
+	* src/nact/nact-clipboard.h (nact_clipboard_dnd_set,
+	nact_clipboard_dnd_get_data, nact_clipboard_dnd_get_text,
+	nact_clipboard_dnd_drag_end, nact_clipboard_dnd_clear): New functions.
+
+	* src/nact/nact-iactions-list.c:
+	* src/nact/nact-iactions-list.h (nact_iactions_list_insert_at_path):
+	New function.
+
+	* src/nact/nact-main-statusbar.c:
+	* src/nact/nact-main-statusbar.h
+	(nact_main_statusbar_display_with_timeout): New function.
+
+	* nact/nact-main-window.c:
+	* nact/nact-main-window.h (nact_main_window_prepare_object_for_copy):
+	New function. This is a temporary place, waiting for (another)
+	reorganization of the code.
+
 2009-10-01 Pierre Wieser <pwieser trychlos org>
 
 	* src/common/na-utils.c:
diff --git a/src/nact/base-application.c b/src/nact/base-application.c
index c504ce5..4db4243 100644
--- a/src/nact/base-application.c
+++ b/src/nact/base-application.c
@@ -644,6 +644,34 @@ base_application_get_main_window( BaseApplication *application )
 }
 
 /**
+ * base_application_message_dlg:
+ * @application: this #BaseApplication instance.
+ * @message: the message to be displayed.
+ *
+ * Displays a dialog with only an OK button.
+ */
+void
+base_application_message_dlg( BaseApplication *application, GSList *msg )
+{
+	GString *string;
+	GSList *im;
+
+	if( !application->private->dispose_has_run ){
+
+		string = g_string_new( "" );
+		for( im = msg ; im ; im = im->next ){
+			if( g_utf8_strlen( string->str, -1 )){
+				string = g_string_append( string, "\n" );
+			}
+			string = g_string_append( string, ( gchar * ) im->data );
+		}
+		display_dlg( application, GTK_MESSAGE_INFO, GTK_BUTTONS_OK, string->str, NULL );
+
+		g_string_free( string, TRUE );
+	}
+}
+
+/**
  * base_application_error_dlg:
  * @application: this #BaseApplication instance.
  * @type:
diff --git a/src/nact/base-application.h b/src/nact/base-application.h
index 6bb5c75..e18521c 100644
--- a/src/nact/base-application.h
+++ b/src/nact/base-application.h
@@ -119,6 +119,7 @@ gchar       *base_application_get_ui_filename( BaseApplication *application );
 BaseBuilder *base_application_get_builder( BaseApplication *application );
 BaseWindow  *base_application_get_main_window( BaseApplication *application );
 
+void         base_application_message_dlg( BaseApplication *application, GSList *message );
 void         base_application_error_dlg( BaseApplication *application, GtkMessageType type, const gchar *first, const gchar *second );
 gboolean     base_application_yesno_dlg( BaseApplication *application, GtkMessageType type, const gchar *first, const gchar *second );
 
diff --git a/src/nact/nact-clipboard.c b/src/nact/nact-clipboard.c
index 4e3aed9..2da9583 100644
--- a/src/nact/nact-clipboard.c
+++ b/src/nact/nact-clipboard.c
@@ -41,8 +41,10 @@
 #include <common/na-object-profile.h>
 #include <common/na-xml-names.h>
 #include <common/na-xml-writer.h>
+#include <common/na-utils.h>
 
 #include "base-iprefs.h"
+#include "nact-tree-model.h"
 #include "nact-clipboard.h"
 
 /* private class data
@@ -55,6 +57,7 @@ struct NactClipboardClassPrivate {
  */
 struct NactClipboardPrivate {
 	gboolean      dispose_has_run;
+	GtkClipboard *dnd;
 	GtkClipboard *primary;
 };
 
@@ -68,7 +71,8 @@ enum {
 };
 
 /* clipboard formats
- * - a special XdndNautilusAction format for internal move/copy
+ * - a special ClipboardNautilusAction format for internal move/copy
+ *   and also used by drag and drop operations
  * - a XdndDirectSave, suitable for exporting to a file manager
  *   (note that Nautilus recognized the "XdndDirectSave0" format as XDS
  *   protocol)
@@ -81,31 +85,38 @@ static GtkTargetEntry clipboard_formats[] = {
 };
 
 typedef struct {
+	guint    target;
+	gchar   *folder;
+	GList   *rows;
+	gboolean copy;
+}
+	NactClipboardDndData;
+
+typedef struct {
 	guint  nb_actions;
 	guint  nb_profiles;
 	guint  nb_menus;
 	GList *items;
 }
-	NactClipboardData;
+	NactClipboardPrimaryData;
 
 static GObjectClass *st_parent_class = NULL;
 
-static GType         register_type( void );
-static void          class_init( NactClipboardClass *klass );
-static void          iprefs_base_iface_init( BaseIPrefsInterface *iface );
-static void          instance_init( GTypeInstance *instance, gpointer klass );
-static void          instance_dispose( GObject *application );
-static void          instance_finalize( GObject *application );
-
-static GtkClipboard *get_nact_clipboard( void );
-static GtkClipboard *get_primary_clipboard( void );
-static void          add_item_to_clipboard0( NAObject *object, gboolean copy_data, gboolean only_profiles, GList **copied );
-/*static void          add_item_to_clipboard( NAObject *object, GList **copied );*/
-static void          export_action( const gchar *uri, const NAObject *action, GSList **exported );
-static gchar        *get_action_xml_buffer( const NAObject *action, GSList **exported );
-static void          get_from_clipboard_callback( GtkClipboard *clipboard, GtkSelectionData *selection_data, guint info, guchar *data );
-static void          clear_clipboard_callback( GtkClipboard *clipboard, NactClipboardData *data );
-static void          renumber_items( NactClipboard *clipboard, GList *items );
+static GType  register_type( void );
+static void   class_init( NactClipboardClass *klass );
+static void   iprefs_iface_init( BaseIPrefsInterface *iface );
+static void   instance_init( GTypeInstance *instance, gpointer klass );
+static void   instance_dispose( GObject *application );
+static void   instance_finalize( GObject *application );
+
+static void   get_from_dnd_clipboard_callback( GtkClipboard *clipboard, GtkSelectionData *selection_data, guint info, guchar *data );
+static void   clear_dnd_clipboard_callback( GtkClipboard *clipboard, NactClipboardDndData *data );
+static gchar *get_action_xml_buffer( const NAObject *object, GList **exported, NAObjectAction **action );
+static void   export_rows( NactClipboard *clipboard, NactClipboardDndData *data );
+
+static void   get_from_primary_clipboard_callback( GtkClipboard *clipboard, GtkSelectionData *selection_data, guint info, guchar *data );
+static void   clear_primary_clipboard_callback( GtkClipboard *clipboard, NactClipboardPrimaryData *data );
+static void   renumber_items( NactClipboard *clipboard, GList *items );
 
 GType
 nact_clipboard_get_type( void )
@@ -137,8 +148,8 @@ register_type( void )
 		( GInstanceInitFunc ) instance_init
 	};
 
-	static const GInterfaceInfo iprefs_base_iface_info = {
-		( GInterfaceInitFunc ) iprefs_base_iface_init,
+	static const GInterfaceInfo iprefs_iface_info = {
+		( GInterfaceInitFunc ) iprefs_iface_init,
 		NULL,
 		NULL
 	};
@@ -147,7 +158,7 @@ register_type( void )
 
 	type = g_type_register_static( G_TYPE_OBJECT, "NactClipboard", &info, 0 );
 
-	g_type_add_interface_static( type, BASE_IPREFS_TYPE, &iprefs_base_iface_info );
+	g_type_add_interface_static( type, BASE_IPREFS_TYPE, &iprefs_iface_info );
 
 	return( type );
 }
@@ -170,9 +181,9 @@ class_init( NactClipboardClass *klass )
 }
 
 static void
-iprefs_base_iface_init( BaseIPrefsInterface *iface )
+iprefs_iface_init( BaseIPrefsInterface *iface )
 {
-	static const gchar *thisfn = "nact_main_window_iprefs_base_iface_init";
+	static const gchar *thisfn = "nact_main_window_iprefs_iface_init";
 
 	g_debug( "%s: iface=%p", thisfn, ( void * ) iface );
 }
@@ -182,6 +193,7 @@ instance_init( GTypeInstance *instance, gpointer klass )
 {
 	static const gchar *thisfn = "nact_clipboard_instance_init";
 	NactClipboard *self;
+	GdkDisplay *display;
 
 	g_debug( "%s: instance=%p, klass=%p", thisfn, ( void * ) instance, ( void * ) klass );
 	g_assert( NACT_IS_CLIPBOARD( instance ));
@@ -190,7 +202,10 @@ instance_init( GTypeInstance *instance, gpointer klass )
 	self->private = g_new0( NactClipboardPrivate, 1 );
 
 	self->private->dispose_has_run = FALSE;
-	self->private->primary = get_primary_clipboard();
+
+	display = gdk_display_get_default();
+	self->private->dnd = gtk_clipboard_get_for_display( display, NACT_CLIPBOARD_ATOM );
+	self->private->primary = gtk_clipboard_get_for_display( display, GDK_SELECTION_PRIMARY );
 }
 
 static void
@@ -207,6 +222,7 @@ instance_dispose( GObject *window )
 
 		self->private->dispose_has_run = TRUE;
 
+		gtk_clipboard_clear( self->private->dnd );
 		gtk_clipboard_clear( self->private->primary );
 
 		/* chain up to the parent class */
@@ -250,42 +266,103 @@ nact_clipboard_new( void )
 }
 
 /**
- * nact_clipboard_get_data_for_intern_use:
- *
- * Set the selected items into our custom clipboard.
+ * nact_clipboard_dnd_set:
+ * @clipboard: this #NactClipboard instance.
+ * @rows: the list of row references of dragged items.
+ * @folder: the target folder if any (XDS protocol to outside).
+ * @copy_data: %TRUE if data is to be copied, %FALSE else
+ *  (only relevant when drag and drop occurs inside of the tree view).
  *
- * Note that we take a copy of the selected items, so that we will be
- * able to paste them when needed.
+ * Set the selected items into our dnd clipboard.
  */
 void
-nact_clipboard_get_data_for_intern_use( GList *selected_items, gboolean copy_data )
+nact_clipboard_dnd_set( NactClipboard *clipboard, guint target, GList *rows, const gchar *folder, gboolean copy_data )
 {
-	static const gchar *thisfn = "nact_clipboard_get_data_for_intern_use";
-	GtkClipboard *clipboard;
-	NactClipboardData *data;
+	static const gchar *thisfn = "nact_clipboard_dnd_set";
+	NactClipboardDndData *data;
+	GtkTreeModel *model;
 	GList *it;
 
-	clipboard = get_nact_clipboard();
+	g_return_if_fail( NACT_IS_CLIPBOARD( clipboard ));
+	g_return_if_fail( rows && g_list_length( rows ));
+
+	if( !clipboard->private->dispose_has_run ){
 
-	data = g_new0( NactClipboardData, 1 );
-	/*data->only_profiles = have_only_profiles( selected_items );*/
+		data = g_new0( NactClipboardDndData, 1 );
 
-	for( it = selected_items ; it ; it = it->next ){
-		NAObject *item_object = NA_OBJECT( it->data );
-		add_item_to_clipboard0( item_object, copy_data, FALSE /*data->only_profiles*/, &data->items );
-	}
-	data->items = g_list_reverse( data->items );
+		data->target = target;
+		data->folder = g_strdup( folder );
+		data->rows = NULL;
+		data->copy = copy_data;
 
-	gtk_clipboard_set_with_data( clipboard,
-			clipboard_formats, G_N_ELEMENTS( clipboard_formats ),
-			( GtkClipboardGetFunc ) get_from_clipboard_callback,
-			( GtkClipboardClearFunc ) clear_clipboard_callback,
-			data );
+		model = gtk_tree_row_reference_get_model(( GtkTreeRowReference * ) rows->data );
 
-	g_debug( "%s: clipboard=%p, data=%p", thisfn, ( void * ) clipboard, ( void * ) data );
+		for( it = rows ; it ; it = it->next ){
+			data->rows = g_list_append(
+					data->rows,
+					gtk_tree_row_reference_copy(( GtkTreeRowReference * ) it->data ));
+		}
+
+		gtk_clipboard_set_with_data( clipboard->private->dnd,
+				clipboard_formats, G_N_ELEMENTS( clipboard_formats ),
+				( GtkClipboardGetFunc ) get_from_dnd_clipboard_callback,
+				( GtkClipboardClearFunc ) clear_dnd_clipboard_callback,
+				data );
+
+		g_debug( "%s: clipboard=%p, data=%p", thisfn, ( void * ) clipboard, ( void * ) data );
+	}
 }
 
 /**
+ * nact_clipboard_dnd_get_data:
+ * @clipboard: this #NactClipboard instance.
+ * @copy_data: will be set to the original value of the drag and drop.
+ *
+ * Returns the list of rows references privously stored.
+ *
+ * The returned list should be gtk_tree_row_reference_free() by the
+ * caller.
+ */
+GList *
+nact_clipboard_dnd_get_data( NactClipboard *clipboard, gboolean *copy_data )
+{
+	static const gchar *thisfn = "nact_clipboard_dnd_get_data";
+	GList *rows = NULL;
+	GtkSelectionData *selection;
+	NactClipboardDndData *data;
+	GtkTreeModel *model;
+	GList *it;
+
+	g_debug( "%s: clipboard=%p", thisfn, ( void * ) clipboard );
+	g_return_val_if_fail( NACT_IS_CLIPBOARD( clipboard ), NULL );
+
+	if( copy_data ){
+		*copy_data = FALSE;
+	}
+
+	if( !clipboard->private->dispose_has_run ){
+
+		selection = gtk_clipboard_wait_for_contents( clipboard->private->dnd, NACT_CLIPBOARD_NACT_ATOM );
+		if( selection ){
+
+			data = ( NactClipboardDndData * ) selection->data;
+			if( data->target == NACT_XCHANGE_FORMAT_NACT ){
+
+				model = gtk_tree_row_reference_get_model(( GtkTreeRowReference * ) data->rows->data );
+
+				for( it = data->rows ; it ; it = it->next ){
+					rows = g_list_append( rows,
+							gtk_tree_row_reference_copy(( GtkTreeRowReference * ) it->data ));
+				}
+				*copy_data = data->copy;
+			}
+		}
+	}
+
+	return( rows );
+}
+
+/*
  * Get text/plain from selected actions.
  *
  * This is called when we drop or paste a selection onto an application
@@ -293,41 +370,166 @@ nact_clipboard_get_data_for_intern_use( GList *selected_items, gboolean copy_dat
  * mime types.
  *
  * Selected items may include menus, actions and profiles.
- * For now, we only exports actions as XML files.
+ * For now, we only exports actions (and profiles) as XML files.
+ *
+ * FIXME: na_xml_writer_get_xml_buffer() returns a valid XML document,
+ * which includes the <?xml ...?> header. Concatenating several valid
+ * XML documents doesn't provide a valid global XML doc, because of
+ * the presence of several <?xml ?> headers inside.
  */
-char *
-nact_clipboard_get_data_for_extern_use( GList *selected_items )
+gchar *
+nact_clipboard_dnd_get_text( NactClipboard *clipboard, GList *rows )
 {
+	GtkTreeModel *model;
+	GtkTreePath *path;
+	GtkTreeIter iter;
+	NAObject *object;
+	NAObjectAction *action;
 	GList *it;
-	GSList *exported = NULL;
+	GList *exported;
 	GString *data;
 	gchar *chunk;
 
+	g_return_val_if_fail( NACT_IS_CLIPBOARD( clipboard ), NULL );
+	g_return_val_if_fail( rows && g_list_length( rows ), NULL );
+
 	data = g_string_new( "" );
 
-	for( it = selected_items ; it ; it = it->next ){
-		NAObject *item_object = NA_OBJECT( it->data );
-		chunk = NULL;
+	if( !clipboard->private->dispose_has_run ){
 
-		if( NA_IS_OBJECT_ACTION( item_object )){
-			chunk = get_action_xml_buffer( item_object, &exported );
+		exported = NULL;
+		model = gtk_tree_row_reference_get_model(( GtkTreeRowReference * ) rows->data );
 
-		} else if( NA_IS_OBJECT_PROFILE( item_object )){
-			NAObjectAction *action = na_object_profile_get_action( NA_OBJECT_PROFILE( item_object ));
-			chunk = get_action_xml_buffer( NA_OBJECT( action ), &exported );
-		}
+		for( it = rows ; it ; it = it->next ){
+
+			path = gtk_tree_row_reference_get_path(( GtkTreeRowReference * ) it->data );
+			if( path ){
+				gtk_tree_model_get_iter( model, &iter, path );
+				gtk_tree_path_free( path );
+
+				gtk_tree_model_get( model, &iter, IACTIONS_LIST_NAOBJECT_COLUMN, &object, -1 );
+				chunk = NULL;
+
+				if( NA_IS_OBJECT_ACTION( object )){
+					chunk = get_action_xml_buffer( object, &exported, &action );
+
+				} else if( NA_IS_OBJECT_PROFILE( object )){
+					chunk = get_action_xml_buffer( object, &exported, &action );
+				}
 
-		if( chunk && strlen( chunk )){
-			data = g_string_append( data, chunk );
+				if( chunk ){
+					g_assert( strlen( chunk ));
+					data = g_string_append( data, chunk );
+					g_free( chunk );
+				}
+
+				g_object_unref( object );
+			}
 		}
-		g_free( chunk );
+
+		g_list_free( exported );
 	}
 
-	g_slist_free( exported );
 	return( g_string_free( data, FALSE ));
 }
 
 /**
+ * nact_clipboard_dnd_drag_end:
+ * @clipboard: this #NactClipboard instance.
+ *
+ * On drag-end, exports the objects if needed.
+ */
+void
+nact_clipboard_dnd_drag_end( NactClipboard *clipboard )
+{
+	static const gchar *thisfn = "nact_clipboard_dnd_drag_end";
+	GtkSelectionData *selection;
+	NactClipboardDndData *data;
+
+	g_debug( "%s: clipboard=%p", thisfn, ( void * ) clipboard );
+	g_return_if_fail( NACT_IS_CLIPBOARD( clipboard ));
+
+	if( !clipboard->private->dispose_has_run ){
+
+		selection = gtk_clipboard_wait_for_contents( clipboard->private->dnd, NACT_CLIPBOARD_NACT_ATOM );
+		if( selection ){
+
+			data = ( NactClipboardDndData * ) selection->data;
+			if( data->target == NACT_XCHANGE_FORMAT_XDS ){
+				export_rows( clipboard, data );
+			}
+		}
+	}
+}
+
+/**
+ * nact_clipboard_dnd_clear:
+ * @clipboard: this #NactClipboard instance.
+ *
+ * Clears the drag-and-drop clipboard.
+ *
+ * At least called on drag-begin.
+ */
+void
+nact_clipboard_dnd_clear( NactClipboard *clipboard )
+{
+	gtk_clipboard_clear( clipboard->private->dnd );
+}
+
+static void
+get_from_dnd_clipboard_callback( GtkClipboard *clipboard, GtkSelectionData *selection_data, guint info, guchar *data )
+{
+	static const gchar *thisfn = "nact_clipboard_get_from_dnd_clipboard_callback";
+
+	g_debug( "%s: clipboard=%p, selection_data=%p, target=%s, info=%d, data=%p",
+			thisfn, ( void * ) clipboard,
+			( void * ) selection_data, gdk_atom_name( selection_data->target ), info, ( void * ) data );
+
+	gtk_selection_data_set( selection_data, selection_data->target, 8, data, sizeof( NactClipboardDndData ));
+}
+
+static void
+clear_dnd_clipboard_callback( GtkClipboard *clipboard, NactClipboardDndData *data )
+{
+	static const gchar *thisfn = "nact_clipboard_clear_dnd_clipboard_callback";
+
+	g_debug( "%s: clipboard=%p, data=%p", thisfn, ( void * ) clipboard, ( void * ) data );
+
+	g_free( data->folder );
+	g_list_foreach( data->rows, ( GFunc ) gtk_tree_row_reference_free, NULL );
+	g_list_free( data->rows );
+	g_free( data );
+}
+
+static gchar *
+get_action_xml_buffer( const NAObject *object, GList **exported, NAObjectAction **action )
+{
+	gchar *buffer = NULL;
+	gint index;
+
+	g_return_val_if_fail( action, NULL );
+
+	*action = NULL;
+
+	if( NA_IS_OBJECT_ACTION( object )){
+		*action = NA_OBJECT_ACTION( object );
+	}
+	if( NA_IS_OBJECT_PROFILE( object )){
+		*action = na_object_profile_get_action( NA_OBJECT_PROFILE( object ));
+	}
+
+	if( *action ){
+		index = g_list_index( *exported, ( gconstpointer ) *action );
+		if( index == -1 ){
+			buffer = na_xml_writer_get_xml_buffer( *action, FORMAT_GCONFENTRY );
+			*exported = g_list_prepend( *exported, ( gpointer ) *action );
+		}
+	}
+
+	return( buffer );
+}
+
+/*
  * Exports selected actions.
  *
  * This is called when we drop or paste a selection onto an application
@@ -336,25 +538,44 @@ nact_clipboard_get_data_for_extern_use( GList *selected_items )
  * Selected items may include menus, actions and profiles.
  * For now, we only exports actions as XML files.
  */
-void
-nact_clipboard_export_items( const gchar *uri, GList *items )
+static void
+export_rows( NactClipboard *clipboard, NactClipboardDndData *data )
 {
+	GtkTreeModel *model;
+	GtkTreePath *path;
+	GtkTreeIter iter;
+	NAObject *object;
+	NAObjectAction *action;
 	GList *it;
-	GSList *exported = NULL;
+	GList *exported;
+	gchar *buffer;
+	gchar *fname;
 
-	for( it = items ; it ; it = it->next ){
-		NAObject *item_object = NA_OBJECT( it->data );
+	exported = NULL;
+	model = gtk_tree_row_reference_get_model(( GtkTreeRowReference * ) data->rows->data );
+
+	for( it = data->rows ; it ; it = it->next ){
 
-		if( NA_IS_OBJECT_ACTION( item_object )){
-			export_action( uri, item_object, &exported );
+		path = gtk_tree_row_reference_get_path(( GtkTreeRowReference * ) it->data );
+		if( path ){
+			gtk_tree_model_get_iter( model, &iter, path );
+			gtk_tree_path_free( path );
+			gtk_tree_model_get( model, &iter, IACTIONS_LIST_NAOBJECT_COLUMN, &object, -1 );
 
-		} else if( NA_IS_OBJECT_PROFILE( item_object )){
-			NAObjectAction *action = na_object_profile_get_action( NA_OBJECT_PROFILE( item_object ));
-			export_action( uri, NA_OBJECT( action ), &exported );
+			buffer = get_action_xml_buffer( object, &exported, &action );
+			if( buffer ){
+
+				fname = na_xml_writer_get_output_fname( NA_OBJECT_ACTION( action ), data->folder, FORMAT_GCONFENTRY );
+				na_xml_writer_output_xml( buffer, fname );
+				g_free( fname );
+				g_free( buffer );
+			}
+
+			g_object_unref( object );
 		}
 	}
 
-	g_slist_free( exported );
+	g_list_free( exported );
 }
 
 /**
@@ -381,14 +602,14 @@ nact_clipboard_export_items( const gchar *uri, GList *items )
 void
 nact_clipboard_primary_set( NactClipboard *clipboard, GList *items, gboolean renumber )
 {
-	NactClipboardData *data;
+	NactClipboardPrimaryData *data;
 	GList *it;
 
 	g_return_if_fail( NACT_IS_CLIPBOARD( clipboard ));
 
 	if( !clipboard->private->dispose_has_run ){
 
-		data = g_new0( NactClipboardData, 1 );
+		data = g_new0( NactClipboardPrimaryData, 1 );
 
 		for( it = items ; it ; it = it->next ){
 			data->items = g_list_prepend( data->items, na_object_duplicate( it->data ));
@@ -411,8 +632,8 @@ nact_clipboard_primary_set( NactClipboard *clipboard, GList *items, gboolean ren
 
 		gtk_clipboard_set_with_data( clipboard->private->primary,
 				clipboard_formats, G_N_ELEMENTS( clipboard_formats ),
-				( GtkClipboardGetFunc ) get_from_clipboard_callback,
-				( GtkClipboardClearFunc ) clear_clipboard_callback,
+				( GtkClipboardGetFunc ) get_from_primary_clipboard_callback,
+				( GtkClipboardClearFunc ) clear_primary_clipboard_callback,
 				data );
 	}
 }
@@ -431,7 +652,7 @@ GList *
 nact_clipboard_primary_get( NactClipboard *clipboard )
 {
 	GtkSelectionData *selection;
-	NactClipboardData *data;
+	NactClipboardPrimaryData *data;
 	GList *items = NULL;
 	GList *it;
 	NAObject *obj;
@@ -443,7 +664,7 @@ nact_clipboard_primary_get( NactClipboard *clipboard )
 		selection = gtk_clipboard_wait_for_contents( clipboard->private->primary, NACT_CLIPBOARD_NACT_ATOM );
 
 		if( selection ){
-			data = ( NactClipboardData * ) selection->data;
+			data = ( NactClipboardPrimaryData * ) selection->data;
 
 			for( it = data->items ; it ; it = it->next ){
 				obj = na_object_duplicate( it->data );
@@ -469,7 +690,7 @@ void
 nact_clipboard_primary_counts( NactClipboard *clipboard, guint *actions, guint *profiles, guint *menus )
 {
 	GtkSelectionData *selection;
-	NactClipboardData *data;
+	NactClipboardPrimaryData *data;
 
 	g_return_if_fail( NACT_IS_CLIPBOARD( clipboard ));
 	g_return_if_fail( actions && profiles && menus );
@@ -483,7 +704,7 @@ nact_clipboard_primary_counts( NactClipboard *clipboard, guint *actions, guint *
 		selection = gtk_clipboard_wait_for_contents( clipboard->private->primary, NACT_CLIPBOARD_NACT_ATOM );
 
 		if( selection ){
-			data = ( NactClipboardData * ) selection->data;
+			data = ( NactClipboardPrimaryData * ) selection->data;
 
 			*actions = data->nb_actions;
 			*profiles = data->nb_profiles;
@@ -492,111 +713,22 @@ nact_clipboard_primary_counts( NactClipboard *clipboard, guint *actions, guint *
 	}
 }
 
-static GtkClipboard *
-get_nact_clipboard( void )
-{
-	GdkDisplay *display;
-	GtkClipboard *clipboard;
-
-	display = gdk_display_get_default();
-	clipboard = gtk_clipboard_get_for_display( display, NACT_CLIPBOARD_ATOM );
-
-	return( clipboard );
-}
-
-static GtkClipboard *
-get_primary_clipboard( void )
-{
-	GdkDisplay *display;
-	GtkClipboard *clipboard;
-
-	display = gdk_display_get_default();
-	clipboard = gtk_clipboard_get_for_display( display, GDK_SELECTION_PRIMARY );
-
-	return( clipboard );
-}
-
-static void
-add_item_to_clipboard0( NAObject *object, gboolean copy_data, gboolean only_profiles, GList **items_list )
-{
-	NAObject *source;
-	gint index;
-
-	source = object;
-	if( !only_profiles && NA_IS_OBJECT_PROFILE( object )){
-		source = NA_OBJECT( na_object_profile_get_action( NA_OBJECT_PROFILE( object )));
-	}
-
-	index = g_list_index( *items_list, ( gconstpointer ) source );
-	if( index != -1 ){
-		return;
-	}
-
-	*items_list = g_list_prepend( *items_list, na_object_ref( source ));
-}
-
-/*static void
-add_item_to_clipboard( NAObject *object, GList **items_list )
-{
-	*items_list = g_list_prepend( *items_list, na_object_ref( object ));
-}*/
-
-static void
-export_action( const gchar *uri, const NAObject *action, GSList **exported )
-{
-	gint index;
-	gchar *fname, *buffer;
-
-	index = g_slist_index( *exported, ( gconstpointer ) action );
-	if( index != -1 ){
-		return;
-	}
-
-	fname = na_xml_writer_get_output_fname( NA_OBJECT_ACTION( action ), uri, FORMAT_GCONFENTRY );
-	buffer = na_xml_writer_get_xml_buffer( NA_OBJECT_ACTION( action ), FORMAT_GCONFENTRY );
-
-	na_xml_writer_output_xml( buffer, fname );
-
-	g_free( buffer );
-	g_free( fname );
-
-	*exported = g_slist_prepend( *exported, ( gpointer ) action );
-}
-
-static gchar *
-get_action_xml_buffer( const NAObject *action, GSList **exported )
-{
-	gint index;
-	gchar *buffer;
-
-	index = g_slist_index( *exported, ( gconstpointer ) action );
-	if( index != -1 ){
-		return( NULL );
-	}
-
-	buffer = na_xml_writer_get_xml_buffer( NA_OBJECT_ACTION( action ), FORMAT_GCONFENTRY );
-
-	*exported = g_slist_prepend( *exported, ( gpointer ) action );
-
-	return( buffer );
-}
-
 static void
-get_from_clipboard_callback( GtkClipboard *clipboard, GtkSelectionData *selection_data, guint info, guchar *data )
+get_from_primary_clipboard_callback( GtkClipboard *clipboard, GtkSelectionData *selection_data, guint info, guchar *data )
 {
-	static const gchar *thisfn = "nact_clipboard_get_from_clipboard_callback";
+	static const gchar *thisfn = "nact_clipboard_get_from_primary_clipboard_callback";
 
 	g_debug( "%s: clipboard=%p, selection_data=%p, target=%s, info=%d, data=%p",
 			thisfn, ( void * ) clipboard,
 			( void * ) selection_data, gdk_atom_name( selection_data->target ), info, ( void * ) data );
 
-	gtk_selection_data_set( selection_data, selection_data->target, 8, data, sizeof( NactClipboardData ));
+	gtk_selection_data_set( selection_data, selection_data->target, 8, data, sizeof( NactClipboardPrimaryData ));
 }
 
 static void
-clear_clipboard_callback( GtkClipboard *clipboard, NactClipboardData *data )
+clear_primary_clipboard_callback( GtkClipboard *clipboard, NactClipboardPrimaryData *data )
 {
-	static const gchar *thisfn = "nact_clipboard_clear_clipboard_callback";
+	static const gchar *thisfn = "nact_clipboard_clear_primary_clipboard_callback";
 
 	g_debug( "%s: clipboard=%p, data=%p", thisfn, ( void * ) clipboard, ( void * ) data );
 
diff --git a/src/nact/nact-clipboard.h b/src/nact/nact-clipboard.h
index 0092226..c3aa459 100644
--- a/src/nact/nact-clipboard.h
+++ b/src/nact/nact-clipboard.h
@@ -41,7 +41,7 @@
  * clipboard buffers.
  */
 
-#include <glib-object.h>
+#include <gtk/gtk.h>
 
 G_BEGIN_DECLS
 
@@ -68,21 +68,30 @@ typedef struct {
 }
 	NactClipboardClass;
 
+/* drag and drop formats
+ */
+enum {
+	NACT_XCHANGE_FORMAT_NACT = 0,
+	NACT_XCHANGE_FORMAT_XDS,
+	NACT_XCHANGE_FORMAT_APPLICATION_XML,
+	NACT_XCHANGE_FORMAT_TEXT_PLAIN,
+	NACT_XCHANGE_FORMAT_URI_LIST
+};
+
 GType          nact_clipboard_get_type( void );
 
 NactClipboard *nact_clipboard_new( void );
 
-void           nact_clipboard_get_data_for_intern_use( GList *selected_items, gboolean copy_data );
-char          *nact_clipboard_get_data_for_extern_use( GList *selected_items );
+void           nact_clipboard_dnd_set( NactClipboard *clipboard, guint target, GList *rows, const gchar *folder, gboolean copy );
+GList         *nact_clipboard_dnd_get_data( NactClipboard *clipboard, gboolean *copy );
+gchar         *nact_clipboard_dnd_get_text( NactClipboard *clipboard, GList *rows );
+void           nact_clipboard_dnd_drag_end( NactClipboard *clipboard );
+void           nact_clipboard_dnd_clear( NactClipboard *clipboard );
 
 void           nact_clipboard_primary_set( NactClipboard *clipboard, GList *items, gboolean renumber_items );
 GList         *nact_clipboard_primary_get( NactClipboard *clipboard );
 void           nact_clipboard_primary_counts( NactClipboard *clipboard, guint *actions, guint *profiles, guint *menus );
 
-void           nact_clipboard_free_items( GSList *items );
-
-void           nact_clipboard_export_items( const gchar *uri, GList *items );
-
 G_END_DECLS
 
 #endif /* __NACT_CLIPBOARD_H__ */
diff --git a/src/nact/nact-iactions-list.c b/src/nact/nact-iactions-list.c
index e6550a0..87e093e 100644
--- a/src/nact/nact-iactions-list.c
+++ b/src/nact/nact-iactions-list.c
@@ -116,7 +116,7 @@ static void         interface_base_init( NactIActionsListInterface *klass );
 static void         interface_base_finalize( NactIActionsListInterface *klass );
 
 static void         free_items_callback( NactIActionsList *instance, GList *items );
-static GtkTreePath *do_insert_items( GtkTreeView *treeview, GtkTreeModel *model, GList *items, GtkTreePath *path, gint level, GList **parents );
+static GtkTreePath *do_insert_items( GtkTreeView *treeview, GtkTreeModel *model, GList *items, GtkTreePath *path, gint level, GList **parents, gboolean inside );
 static GList       *do_insert_items_add_parent( GList *parents, GtkTreeView *treeview, GtkTreeModel *model, NAObject *parent );
 
 static gchar       *v_get_treeview_name( NactIActionsList *instance );
@@ -818,10 +818,7 @@ nact_iactions_list_insert_items( NactIActionsList *instance, GList *items, NAObj
 	GtkTreeModel *model;
 	GtkTreeSelection *selection;
 	GList *list_selected;
-	GtkTreePath *insert_path = NULL;
-	GtkTreePath *last_path = NULL;
-	GList *parents = NULL;
-	GList *it;
+	GtkTreePath *insert_path;
 
 	g_debug( "%s: instance=%p, items=%p (%d items)",
 			thisfn, ( void * ) instance, ( void * ) items, g_list_length( items ));
@@ -830,6 +827,7 @@ nact_iactions_list_insert_items( NactIActionsList *instance, GList *items, NAObj
 
 	if( st_initialized && !st_finalized ){
 
+		insert_path = NULL;
 		treeview = get_actions_list_treeview( instance );
 		model = gtk_tree_view_get_model( treeview );
 		g_return_if_fail( NACT_IS_TREE_MODEL( model ));
@@ -847,7 +845,46 @@ nact_iactions_list_insert_items( NactIActionsList *instance, GList *items, NAObj
 			g_list_free( list_selected );
 		}
 
-		last_path = do_insert_items( treeview, model, items, insert_path, 0, &parents );
+		nact_iactions_list_insert_at_path( instance, items, insert_path, TRUE );
+
+		gtk_tree_path_free( insert_path );
+	}
+}
+
+/**
+ * nact_iactions_list_insert_at_path:
+ * @instance: this #NactIActionsList instance.
+ * @items: a list of items to be inserted (e.g. from a paste).
+ * @path: insertion path.
+ * @inside: %TRUE if the item may be inserted inside of the give path.
+ *
+ * Inserts the provided @items list in the treeview.
+ *
+ * This function takes care of repositionning a new selection if
+ * possible, and refilter the display model.
+ */
+void
+nact_iactions_list_insert_at_path( NactIActionsList *instance, GList *items, GtkTreePath *insert_path, gboolean inside )
+{
+	static const gchar *thisfn = "nact_iactions_list_insert_at_path";
+	GtkTreeView *treeview;
+	GtkTreeModel *model;
+	GtkTreePath *last_path = NULL;
+	GList *parents = NULL;
+	GList *it;
+
+	g_debug( "%s: instance=%p, items=%p (%d items)",
+			thisfn, ( void * ) instance, ( void * ) items, g_list_length( items ));
+	g_return_if_fail( NACT_IS_IACTIONS_LIST( instance ));
+	g_return_if_fail( NACT_IS_WINDOW( instance ));
+
+	if( st_initialized && !st_finalized ){
+
+		treeview = get_actions_list_treeview( instance );
+		model = gtk_tree_view_get_model( treeview );
+		g_return_if_fail( NACT_IS_TREE_MODEL( model ));
+
+		last_path = do_insert_items( treeview, model, items, insert_path, 0, &parents, inside );
 
 		for( it = parents ; it ; it = it->next ){
 			na_object_check_edition_status( it->data );
@@ -857,12 +894,17 @@ nact_iactions_list_insert_items( NactIActionsList *instance, GList *items, NAObj
 		select_row_at_path( instance, treeview, model, last_path );
 
 		gtk_tree_path_free( last_path );
-		gtk_tree_path_free( insert_path );
 	}
 }
 
 static GtkTreePath *
-do_insert_items( GtkTreeView *treeview, GtkTreeModel *model, GList *items, GtkTreePath *path, gint level, GList **parents )
+do_insert_items( GtkTreeView *treeview,
+					GtkTreeModel *model,
+					GList *items,
+					GtkTreePath *path,
+					gint level,
+					GList **parents,
+					gboolean inside )
 {
 	static const gchar *thisfn = "nact_iactions_list_do_insert_items";
 	guint nb_profiles, nb_actions, nb_menus;
@@ -889,7 +931,8 @@ do_insert_items( GtkTreeView *treeview, GtkTreeModel *model, GList *items, GtkTr
 			 * from store to filter_model, and ran through filter_visible function
 			 * we so cannot rely on it if object is a profile inserted at level > 0
 			 */
-			inserted_path_str = nact_tree_model_insert( NACT_TREE_MODEL( model ), NA_OBJECT( it->data ), path, &obj_parent );
+			inserted_path_str = nact_tree_model_insert(
+					NACT_TREE_MODEL( model ), NA_OBJECT( it->data ), path, &obj_parent, inside );
 			g_debug( "%s: inserted_path=%s", thisfn, inserted_path_str );
 
 			inserted_path = gtk_tree_path_new_from_string( inserted_path_str );
@@ -906,7 +949,7 @@ do_insert_items( GtkTreeView *treeview, GtkTreeModel *model, GList *items, GtkTr
 			 */
 			if( NA_IS_OBJECT_ITEM( it->data )){
 				subitems = na_object_get_items( it->data );
-				do_insert_items( treeview, model, subitems, inserted_path, level+1, parents );
+				do_insert_items( treeview, model, subitems, inserted_path, level+1, parents, inside );
 				na_object_free_items( subitems );
 			}
 
diff --git a/src/nact/nact-iactions-list.h b/src/nact/nact-iactions-list.h
index 36d8af9..da5e2cf 100644
--- a/src/nact/nact-iactions-list.h
+++ b/src/nact/nact-iactions-list.h
@@ -40,6 +40,8 @@
  * and in the export assistant (export mode).
  */
 
+#include <gtk/gtk.h>
+
 #include <common/na-object-class.h>
 
 G_BEGIN_DECLS
@@ -121,6 +123,7 @@ GList    *nact_iactions_list_get_selected_items( NactIActionsList *instance );
 gboolean  nact_iactions_list_has_exportable( NactIActionsList *instance );
 gboolean  nact_iactions_list_has_modified_items( NactIActionsList *instance );
 void      nact_iactions_list_insert_items( NactIActionsList *instance, GList *items, NAObject *sibling );
+void      nact_iactions_list_insert_at_path( NactIActionsList *instance, GList *items, GtkTreePath *path, gboolean inside );
 gboolean  nact_iactions_list_is_expanded( NactIActionsList *instance, const NAObject *item );
 void      nact_iactions_list_set_management_mode( NactIActionsList *instance, gint mode );
 void      nact_iactions_list_toggle_collapse( NactIActionsList *instance, const NAObject *item );
diff --git a/src/nact/nact-main-statusbar.c b/src/nact/nact-main-statusbar.c
index 2ae4346..064ebef 100644
--- a/src/nact/nact-main-statusbar.c
+++ b/src/nact/nact-main-statusbar.c
@@ -54,6 +54,23 @@ nact_main_statusbar_display_status( NactMainWindow *window, const gchar *context
 }
 
 void
+nact_main_statusbar_display_with_timeout( NactMainWindow *window, const gchar *context, const gchar *status )
+{
+	GtkStatusbar *bar;
+
+	if( !status || !g_utf8_strlen( status, -1 )){
+		return;
+	}
+
+	bar = get_statusbar( window );
+
+	if( bar ){
+		guint context_id = gtk_statusbar_get_context_id( bar, context );
+		gtk_statusbar_push( bar, context_id, status );
+	}
+}
+
+void
 nact_main_statusbar_hide_status( NactMainWindow *window, const gchar *context )
 {
 	GtkStatusbar *bar;
diff --git a/src/nact/nact-main-statusbar.h b/src/nact/nact-main-statusbar.h
index 35f8cb1..83c4854 100644
--- a/src/nact/nact-main-statusbar.h
+++ b/src/nact/nact-main-statusbar.h
@@ -42,6 +42,7 @@
 G_BEGIN_DECLS
 
 void  nact_main_statusbar_display_status( NactMainWindow *window, const gchar *context, const gchar *status );
+void  nact_main_statusbar_display_with_timeout( NactMainWindow *window, const gchar *context, const gchar *status );
 void  nact_main_statusbar_hide_status( NactMainWindow *window, const gchar *context );
 
 G_END_DECLS
diff --git a/src/nact/nact-main-window.c b/src/nact/nact-main-window.c
index 624e24c..55db4d4 100644
--- a/src/nact/nact-main-window.c
+++ b/src/nact/nact-main-window.c
@@ -765,6 +765,32 @@ nact_main_window_remove_deleted( NactMainWindow *window )
 	}
 }
 
+/**
+ * nact_main_window_prepare_object_for_copy:
+ * @window: this #NactMainWindow instance.
+ * @object: the #NAObject to be prepared.
+ * @new_parent: if @object is a profile, then the new id will be computed
+ * depending of already existing profiles in the @new_parent.
+ *
+ * Gives a new id to the object,
+ * possibly relabeling it depending on current preferences.
+ */
+void
+nact_main_window_prepare_object_for_copy( NactMainWindow *window, NAObject *object, NAObjectAction *new_parent )
+{
+	gboolean relabel = FALSE;
+
+	if( NA_IS_OBJECT_MENU( object )){
+		relabel = base_iprefs_get_bool( BASE_IPREFS( window ), BASE_IPREFS_RELABEL_MENUS );
+	} else if( NA_IS_OBJECT_ACTION( object )){
+		relabel = base_iprefs_get_bool( BASE_IPREFS( window ), BASE_IPREFS_RELABEL_ACTIONS );
+	} else if( NA_IS_OBJECT_PROFILE( object )){
+		relabel = base_iprefs_get_bool( BASE_IPREFS( window ), BASE_IPREFS_RELABEL_PROFILES );
+	}
+
+	na_object_set_new_id( object );
+}
+
 /*
  * If the deleted item is a profile, then do nothing because the parent
  * action has been marked as modified when the profile has been deleted,
diff --git a/src/nact/nact-main-window.h b/src/nact/nact-main-window.h
index 15b1b8f..bbadbc0 100644
--- a/src/nact/nact-main-window.h
+++ b/src/nact/nact-main-window.h
@@ -77,6 +77,7 @@ gboolean        nact_main_window_has_modified_items( const NactMainWindow *windo
 void            nact_main_window_move_to_deleted( NactMainWindow *window, GList *items );
 void            nact_main_window_reload( NactMainWindow *window );
 void            nact_main_window_remove_deleted( NactMainWindow *window );
+void            nact_main_window_prepare_object_for_copy( NactMainWindow *window, NAObject *object, NAObjectAction *new_parent );
 
 G_END_DECLS
 
diff --git a/src/nact/nact-tree-model.c b/src/nact/nact-tree-model.c
index d879d19..2bb423e 100644
--- a/src/nact/nact-tree-model.c
+++ b/src/nact/nact-tree-model.c
@@ -40,12 +40,16 @@
 #include <common/na-object-profile.h>
 #include <common/na-iprefs.h>
 #include <common/na-utils.h>
+#include <common/na-xml-writer.h>
 
 #include "egg-tree-multi-dnd.h"
 #include "nact-application.h"
 #include "nact-iactions-list.h"
+#include "nact-main-statusbar.h"
+#include "nact-main-window.h"
 #include "nact-clipboard.h"
 #include "nact-tree-model.h"
+#include "nact-xml-reader.h"
 
 /*
  * call once egg_tree_multi_drag_add_drag_support( treeview ) at init time (before gtk_main)
@@ -61,10 +65,17 @@
  *   call once nact_clipboard_on_drag_begin( treeview, context, main_window )
  *
  * when we drop (e.g. in Nautilus)
- *   call once egg_tree_multi_drag_drag_data_get( treeview, context, selection_data, info=0, time )
+ *   call once egg_tree_multi_dnd_on_drag_data_get( treeview, context, selection_data, info=0, time )
  *   call once nact_tree_model_imulti_drag_source_drag_data_get( drag_source, context, selection_data, path_list, atom=XdndDirectSave0 )
  *   call once nact_tree_model_idrag_dest_drag_data_received
  *   call once nact_clipboard_on_drag_end( treeview, context, main_window )
+ *
+ * when we drop in Nautilus Actions
+ *   call once egg_tree_multi_dnd_on_drag_data_get( treeview, context, selection_data, info=0, time )
+ *   call once nact_tree_model_imulti_drag_source_drag_data_get( drag_source, context, selection_data, path_list, atom=XdndNautilusActions )
+ *   call once nact_clipboard_get_data_for_intern_use
+ *   call once nact_tree_model_idrag_dest_drag_data_received
+ *   call once nact_clipboard_on_drag_end( treeview, context, main_window )
  */
 
 /* private class data
@@ -76,13 +87,15 @@ struct NactTreeModelClassPrivate {
 /* private instance data
  */
 struct NactTreeModelPrivate {
-	gboolean     dispose_has_run;
-	BaseWindow  *window;
-	GtkTreeView *treeview;
-	gboolean     have_dnd;
-	gboolean     only_actions;
-	gchar       *drag_dest_uri;
-	GList       *drag_items;
+	gboolean       dispose_has_run;
+	BaseWindow    *window;
+	GtkTreeView   *treeview;
+	gboolean       have_dnd;
+	gboolean       only_actions;
+	NactClipboard *clipboard;
+	gboolean       drag_has_profiles;
+	gboolean       drag_highlight;		/* defined for on_drag_motion handler */
+	gboolean       drag_drop;			/* defined for on_drag_motion handler */
 };
 
 #define MAX_XDS_ATOM_VAL_LEN			4096
@@ -90,15 +103,7 @@ struct NactTreeModelPrivate {
 #define XDS_ATOM						gdk_atom_intern( "XdndDirectSave0", FALSE )
 #define XDS_FILENAME					"xds.txt"
 
-#define TREE_MODEL_ORDER_MODE			"nact-tree-model-order-mode"
-
-enum {
-	NACT_XCHANGE_FORMAT_NACT = 0,
-	NACT_XCHANGE_FORMAT_XDS,
-	NACT_XCHANGE_FORMAT_APPLICATION_XML,
-	NACT_XCHANGE_FORMAT_TEXT_PLAIN,
-	NACT_XCHANGE_FORMAT_URI_LIST
-};
+#define NACT_ATOM						gdk_atom_intern( "XdndNautilusActions", FALSE )
 
 /* as a dnd source, we provide
  * - a special XdndNautilusAction format for internal move/copy
@@ -114,8 +119,12 @@ static GtkTargetEntry dnd_source_formats[] = {
 	{ "text/plain",          GTK_TARGET_OTHER_APP,   NACT_XCHANGE_FORMAT_TEXT_PLAIN },
 };
 
-#define NACT_ATOM						gdk_atom_intern( "XdndNautilusActions", FALSE )
-
+/* as a dnd dest, we accept
+ * - of course, the same special XdndNautilusAction format for internal move/copy
+ * - a list of uris, to be imported
+ * - a XML buffer, to be imported
+ * - a plain text, which we are goint to try to import as a XML description
+ */
 static GtkTargetEntry dnd_dest_targets[] = {
 	{ "XdndNautilusActions", 0, NACT_XCHANGE_FORMAT_NACT },
 	{ "text/uri-list",       0, NACT_XCHANGE_FORMAT_URI_LIST },
@@ -145,6 +154,10 @@ typedef struct {
 }
 	ntmSearchIdStruct;
 
+#define TREE_MODEL_ORDER_MODE			"nact-tree-model-order-mode"
+
+#define TREE_MODEL_STATUSBAR_CONTEXT	"nact-tree-model-statusbar-context"
+
 static GtkTreeModelFilterClass *st_parent_class = NULL;
 
 static GType          register_type( void );
@@ -159,9 +172,9 @@ static NactTreeModel *tree_model_new( BaseWindow *window, GtkTreeView *treeview
 
 static void           fill_tree_store( GtkTreeStore *model, GtkTreeView *treeview, GList *items, gboolean only_actions, GtkTreeIter *parent );
 
-static void           insert_get_iters_action( GtkTreeModel *model, const NAObject *select_object, GtkTreePath *select_path, const NAObject *object, GtkTreeIter *parent_iter, gboolean *has_parent_iter, GtkTreeIter *sibling_iter, gboolean *has_sibling_iter, NAObject **parent_object );
-static void           insert_get_iters_profile( GtkTreeModel *model, const NAObject *select_object, GtkTreePath *select_path, const NAObject *object, GtkTreeIter *parent_iter, gboolean *has_parent_iter, GtkTreeIter *sibling_iter, gboolean *has_sibling_iter, NAObject **parent_object );
-static void           insert_get_iters_menu( GtkTreeModel *model, const NAObject *select_object, GtkTreePath *select_path, const NAObject *object, GtkTreeIter *parent_iter, gboolean *has_parent_iter, GtkTreeIter *sibling_iter, gboolean *has_sibling_iter, NAObject **parent_object );
+static void           insert_get_iters_action( GtkTreeModel *model, const NAObject *select_object, GtkTreePath *select_path, const NAObject *object, GtkTreeIter *parent_iter, gboolean *has_parent_iter, GtkTreeIter *sibling_iter, gboolean *has_sibling_iter, NAObject **parent_object, gboolean inside );
+static void           insert_get_iters_profile( GtkTreeModel *model, const NAObject *select_object, GtkTreePath *select_path, const NAObject *object, GtkTreeIter *parent_iter, gboolean *has_parent_iter, GtkTreeIter *sibling_iter, gboolean *has_sibling_iter, NAObject **parent_object, gboolean inside );
+static void           insert_get_iters_menu( GtkTreeModel *model, const NAObject *select_object, GtkTreePath *select_path, const NAObject *object, GtkTreeIter *parent_iter, gboolean *has_parent_iter, GtkTreeIter *sibling_iter, gboolean *has_sibling_iter, NAObject **parent_object, gboolean inside );
 static void           insert_before_get_iters( GtkTreeModel *model,  GtkTreePath *select_path, const NAObject *object, GtkTreeIter *parent_iter, gboolean *has_parent_iter, GtkTreeIter *sibling_iter, gboolean *has_sibling_iter, NAObject **parent_object );
 static void           insert_before_parent_get_iters( GtkTreeModel *model,  GtkTreePath *select_path, const NAObject *object, GtkTreeIter *parent_iter, gboolean *has_parent_iter, GtkTreeIter *sibling_iter, gboolean *has_sibling_iter, NAObject **parent_object );
 static void           insert_as_last_child_get_iters( GtkTreeModel *model,  GtkTreePath *select_path, const NAObject *object, GtkTreeIter *parent_iter, gboolean *has_parent_iter, GtkTreeIter *sibling_iter, gboolean *has_sibling_iter, NAObject **parent_object );
@@ -188,15 +201,16 @@ static GdkDragAction  imulti_drag_source_get_drag_actions( EggTreeMultiDragSourc
 static gboolean       idrag_dest_drag_data_received( GtkTreeDragDest *drag_dest, GtkTreePath *dest, GtkSelectionData  *selection_data );
 static gboolean       idrag_dest_row_drop_possible( GtkTreeDragDest *drag_dest, GtkTreePath *dest_path, GtkSelectionData *selection_data );
 
-static gboolean       on_drag_begin( GtkWidget *widget, GdkDragContext *context, BaseWindow *window );
+static void           on_drag_begin( GtkWidget *widget, GdkDragContext *context, BaseWindow *window );
+/*static gboolean       on_drag_motion( GtkWidget *widget, GdkDragContext *context, gint x, gint y, guint time, BaseWindow *window );*/
+/*static gboolean       on_drag_drop( GtkWidget *widget, GdkDragContext *context, gint x, gint y, guint time, BaseWindow *window );*/
 static void           on_drag_end( GtkWidget *widget, GdkDragContext *context, BaseWindow *window );
 
-/*static gboolean       on_drag_drop( GtkWidget *widget, GdkDragContext *context, gint x, gint y, guint time, BaseWindow *window );
-static void           on_drag_data_received( GtkWidget *widget, GdkDragContext *drag_context, gint x, gint y, GtkSelectionData *data, guint info, guint time, BaseWindow *window );*/
+static char          *get_xds_atom_value( GdkDragContext *context );
+static guint          target_atom_to_id( GdkAtom atom );
 
 static gint           sort_actions_list( GtkTreeModel *model, GtkTreeIter *a, GtkTreeIter *b, gpointer user_data );
 static gboolean       filter_visible( GtkTreeModel *store, GtkTreeIter *iter, NactTreeModel *model );
-static char          *get_xds_atom_value( GdkDragContext *context );
 
 GType
 nact_tree_model_get_type( void )
@@ -323,6 +337,8 @@ instance_dispose( GObject *object )
 
 		self->private->dispose_has_run = TRUE;
 
+		g_object_unref( self->private->clipboard );
+
 		/* chain up to the parent class */
 		if( G_OBJECT_CLASS( st_parent_class )->dispose ){
 			G_OBJECT_CLASS( st_parent_class )->dispose( object );
@@ -340,9 +356,6 @@ instance_finalize( GObject *object )
 	g_return_if_fail( NACT_IS_TREE_MODEL( object ));
 	self = NACT_TREE_MODEL( object );
 
-	g_free( self->private->drag_dest_uri );
-	g_list_free( self->private->drag_items );
-
 	g_free( self->private );
 
 	/* chain call to parent class */
@@ -396,6 +409,7 @@ tree_model_new( BaseWindow *window, GtkTreeView *treeview )
 
 	model->private->window = window;
 	model->private->treeview = treeview;
+	model->private->clipboard = nact_clipboard_new();
 
 	return( model );
 }
@@ -470,23 +484,26 @@ nact_tree_model_runtime_init( NactTreeModel *model, gboolean have_dnd )
 					"drag-begin",
 					G_CALLBACK( on_drag_begin ));
 
+			/* connect: implies that we have to do all hard stuff
+			 * connect_after: no more triggers drag-drop signal
+			 */
+			/*base_window_signal_connect_after(
+					BASE_WINDOW( model->private->window ),
+					G_OBJECT( model->private->treeview ),
+					"drag-motion",
+					G_CALLBACK( on_drag_motion ));*/
+
+			/*base_window_signal_connect(
+					BASE_WINDOW( model->private->window ),
+					G_OBJECT( model->private->treeview ),
+					"drag-drop",
+					G_CALLBACK( on_drag_drop ));*/
+
 			base_window_signal_connect(
 					BASE_WINDOW( model->private->window ),
 					G_OBJECT( model->private->treeview ),
 					"drag-end",
 					G_CALLBACK( on_drag_end ));
-
-			/*nact_window_signal_connect(
-					NACT_WINDOW( window ),
-					G_OBJECT( treeview ),
-					"drag_drop",
-					G_CALLBACK( on_drag_drop ));
-
-			nact_window_signal_connect(
-					NACT_WINDOW( window ),
-					G_OBJECT( treeview ),
-					"drag_data-received",
-					G_CALLBACK( on_drag_data_received ));*/
 		}
 	}
 }
@@ -562,7 +579,7 @@ nact_tree_model_display_order_change( NactTreeModel *model, gint order_mode )
 
 		switch( order_mode ){
 
-			case PREFS_ORDER_ALPHA_ASCENDING:
+			case IPREFS_ORDER_ALPHA_ASCENDING:
 
 				gtk_tree_sortable_set_sort_column_id(
 						GTK_TREE_SORTABLE( store ),
@@ -577,7 +594,7 @@ nact_tree_model_display_order_change( NactTreeModel *model, gint order_mode )
 						NULL );
 				break;
 
-			case PREFS_ORDER_ALPHA_DESCENDING:
+			case IPREFS_ORDER_ALPHA_DESCENDING:
 
 				gtk_tree_sortable_set_sort_column_id(
 						GTK_TREE_SORTABLE( store ),
@@ -592,7 +609,7 @@ nact_tree_model_display_order_change( NactTreeModel *model, gint order_mode )
 						NULL );
 				break;
 
-			case PREFS_ORDER_MANUAL:
+			case IPREFS_ORDER_MANUAL:
 			default:
 
 				gtk_tree_sortable_set_sort_column_id(
@@ -722,6 +739,7 @@ fill_tree_store( GtkTreeStore *model, GtkTreeView *treeview,
  * @path: the #GtkTreePath of the beginning of the current selection,
  * or NULL.
  * @obj_parent: set to the parent or the object itself.
+ * @inside: %TRUE if the item may be inserted inside of the given path.
  *
  * Insert a new row at the given position.
  *
@@ -740,7 +758,8 @@ fill_tree_store( GtkTreeStore *model, GtkTreeView *treeview,
  * |                    |                      |                      |                      |
  * |   profile          | insert_before_parent |    insert_before     | insert_before_parent |
  * |                    |                      |                      |                      |
- * |    menu            | insert_as_last_child |          n/a         | insert_as_last_child |
+ * |    menu            |    insert_before     |          n/a         |    insert_before     |
+ * |                    | insert_as_last_child |                      | insert_as_last_child |
  * +-----------------------------------------------------------------------------------------+
  *
  * insert_before       : parent=NULL     , sibling_from_path (or null if path was null)
@@ -752,7 +771,11 @@ fill_tree_store( GtkTreeStore *model, GtkTreeView *treeview,
  * string path
  */
 gchar *
-nact_tree_model_insert( NactTreeModel *model, const NAObject *object, GtkTreePath *path, NAObject **obj_parent )
+nact_tree_model_insert( NactTreeModel *model,
+						const NAObject *object,
+						GtkTreePath *path,
+						NAObject **obj_parent,
+						gboolean inside )
 {
 	static const gchar *thisfn = "nact_tree_model_insert";
 	gchar *path_str = NULL;
@@ -785,22 +808,25 @@ nact_tree_model_insert( NactTreeModel *model, const NAObject *object, GtkTreePat
 		remove_if_exists( model, store, object );
 
 		if( path ){
-			gtk_tree_model_get_iter( GTK_TREE_MODEL( model ), &select_iter, path );
+			if( !gtk_tree_model_get_iter( GTK_TREE_MODEL( model ), &select_iter, path )){
+				return( NULL );
+			}
+
 			gtk_tree_model_get( GTK_TREE_MODEL( model ), &select_iter, IACTIONS_LIST_NAOBJECT_COLUMN, &select_object, -1 );
 
 			g_return_val_if_fail( select_object, NULL );
 			g_return_val_if_fail( NA_IS_OBJECT( select_object ), NULL );
 
 			if( NA_IS_OBJECT_ACTION( object )){
-				insert_get_iters_action( store, select_object, path, object, &parent_iter, &has_parent_iter, &sibling_iter, &has_sibling_iter, obj_parent );
+				insert_get_iters_action( store, select_object, path, object, &parent_iter, &has_parent_iter, &sibling_iter, &has_sibling_iter, obj_parent, inside );
 			}
 
 			if( NA_IS_OBJECT_PROFILE( object )){
-				insert_get_iters_profile( store, select_object, path, object, &parent_iter, &has_parent_iter, &sibling_iter, &has_sibling_iter, obj_parent );
+				insert_get_iters_profile( store, select_object, path, object, &parent_iter, &has_parent_iter, &sibling_iter, &has_sibling_iter, obj_parent, inside );
 			}
 
 			if( NA_IS_OBJECT_MENU( object )){
-				insert_get_iters_menu( store, select_object, path, object, &parent_iter, &has_parent_iter, &sibling_iter, &has_sibling_iter, obj_parent );
+				insert_get_iters_menu( store, select_object, path, object, &parent_iter, &has_parent_iter, &sibling_iter, &has_sibling_iter, obj_parent, inside );
 			}
 
 			g_object_unref( select_object );
@@ -823,8 +849,19 @@ nact_tree_model_insert( NactTreeModel *model, const NAObject *object, GtkTreePat
  * inserts an action
  */
 static void
-insert_get_iters_action( GtkTreeModel *model, const NAObject *select_object, GtkTreePath *select_path, const NAObject *object, GtkTreeIter *parent_iter, gboolean *has_parent_iter, GtkTreeIter *sibling_iter, gboolean *has_sibling_iter, NAObject **parent_object )
+insert_get_iters_action( GtkTreeModel *model,
+							const NAObject *select_object,
+							GtkTreePath *select_path,
+							const NAObject *object,
+							GtkTreeIter *parent_iter,
+							gboolean *has_parent_iter,
+							GtkTreeIter *sibling_iter,
+							gboolean *has_sibling_iter,
+							NAObject **parent_object,
+							gboolean inside )
 {
+	gint count;
+
 	g_return_if_fail( NA_IS_OBJECT_ACTION( object ));
 
 	/* (insert_before)
@@ -847,10 +884,16 @@ insert_get_iters_action( GtkTreeModel *model, const NAObject *select_object, Gtk
 		insert_before_parent_get_iters( model, select_path, object, parent_iter, has_parent_iter, sibling_iter, has_sibling_iter, parent_object );
 	}
 
-	/* (insert_as_last_child)
+	/* insert_as_last_child if there is no child at all
+	 * insert_before else
 	 */
 	if( NA_IS_OBJECT_MENU( select_object )){
-		insert_as_last_child_get_iters( model, select_path, object, parent_iter, has_parent_iter, sibling_iter, has_sibling_iter, parent_object );
+		count = na_object_get_items_count( select_object );
+		if( count == 0 && inside ){
+			insert_as_last_child_get_iters( model, select_path, object, parent_iter, has_parent_iter, sibling_iter, has_sibling_iter, parent_object );
+		} else {
+			insert_before_get_iters( model, select_path, object, parent_iter, has_parent_iter, sibling_iter, has_sibling_iter, parent_object );
+		}
 	}
 }
 
@@ -858,7 +901,16 @@ insert_get_iters_action( GtkTreeModel *model, const NAObject *select_object, Gtk
  * insert a profile
  */
 static void
-insert_get_iters_profile( GtkTreeModel *model, const NAObject *select_object, GtkTreePath *select_path, const NAObject *object, GtkTreeIter *parent_iter, gboolean *has_parent_iter, GtkTreeIter *sibling_iter, gboolean *has_sibling_iter, NAObject **parent_object )
+insert_get_iters_profile( GtkTreeModel *model,
+		const NAObject *select_object,
+		GtkTreePath *select_path,
+		const NAObject *object,
+		GtkTreeIter *parent_iter,
+		gboolean *has_parent_iter,
+		GtkTreeIter *sibling_iter,
+		gboolean *has_sibling_iter,
+		NAObject **parent_object,
+		gboolean inside )
 {
 	g_return_if_fail( NA_IS_OBJECT_PROFILE( object ));
 
@@ -879,8 +931,19 @@ insert_get_iters_profile( GtkTreeModel *model, const NAObject *select_object, Gt
  * insert a menu
  */
 static void
-insert_get_iters_menu( GtkTreeModel *model, const NAObject *select_object, GtkTreePath *select_path, const NAObject *object, GtkTreeIter *parent_iter, gboolean *has_parent_iter, GtkTreeIter *sibling_iter, gboolean *has_sibling_iter, NAObject **parent_object )
+insert_get_iters_menu( GtkTreeModel *model,
+		const NAObject *select_object,
+		GtkTreePath *select_path,
+		const NAObject *object,
+		GtkTreeIter *parent_iter,
+		gboolean *has_parent_iter,
+		GtkTreeIter *sibling_iter,
+		gboolean *has_sibling_iter,
+		NAObject **parent_object,
+		gboolean inside )
 {
+	gint count;
+
 	g_return_if_fail( NA_IS_OBJECT_MENU( object ));
 
 	if( NA_IS_OBJECT_ACTION( select_object )){
@@ -891,8 +954,16 @@ insert_get_iters_menu( GtkTreeModel *model, const NAObject *select_object, GtkTr
 		insert_before_parent_get_iters( model, select_path, object, parent_iter, has_parent_iter, sibling_iter, has_sibling_iter, parent_object );
 	}
 
+	/* insert_as_last_child if there is no child at all
+	 * insert_before else
+	 */
 	if( NA_IS_OBJECT_MENU( select_object )){
-		insert_as_last_child_get_iters( model, select_path, object, parent_iter, has_parent_iter, sibling_iter, has_sibling_iter, parent_object );
+		count = na_object_get_items_count( select_object );
+		if( count == 0 && inside ){
+			insert_as_last_child_get_iters( model, select_path, object, parent_iter, has_parent_iter, sibling_iter, has_sibling_iter, parent_object );
+		} else {
+			insert_before_get_iters( model, select_path, object, parent_iter, has_parent_iter, sibling_iter, has_sibling_iter, parent_object );
+		}
 	}
 }
 
@@ -1265,71 +1336,94 @@ search_for_object_id_iter( NactTreeModel *model, GtkTreePath *path, NAObject *ob
 }
 
 /*
- * all rows are draggable
+ * all selectable rows are draggable
+ * nonetheless, it's a good place to store the dragged row references
+ * we only make use of them in on_drag_motion handler
  */
 static gboolean
-imulti_drag_source_row_draggable( EggTreeMultiDragSource *drag_source, GList *path_list )
+imulti_drag_source_row_draggable( EggTreeMultiDragSource *drag_source, GList *rows )
 {
 	static const gchar *thisfn = "nact_tree_model_imulti_drag_source_row_draggable";
-	/*FrWindow     *window;
-	GtkTreeModel *model;
-	GList        *scan;*/
+	NactTreeModel *model;
+	GtkTreeModel *store;
+	GtkTreePath *path;
+	GtkTreeIter iter;
+	NAObject *object;
+	GList *it;
 
-	g_debug( "%s: drag_source=%p, path_list=%p", thisfn, ( void * ) drag_source, ( void * ) path_list );
+	g_debug( "%s: drag_source=%p, rows=%p (%d items)",
+			thisfn, ( void * ) drag_source, ( void * ) rows, g_list_length( rows ));
 
-	/*window = g_object_get_data (G_OBJECT (drag_source), "FrWindow");
-	g_return_val_if_fail (window != NULL, FALSE);
+	g_return_val_if_fail( NACT_IS_TREE_MODEL( drag_source ), FALSE );
+	model = NACT_TREE_MODEL( drag_source );
 
-	model = fr_window_get_list_store (window);
+	if( !model->private->dispose_has_run ){
 
-	for (scan = path_list; scan; scan = scan->next) {
-		GtkTreeRowReference *reference = scan->data;
-		GtkTreePath         *path;
-		GtkTreeIter          iter;
-		FileData            *fdata;
+		model->private->drag_has_profiles = FALSE;
+		store = gtk_tree_model_filter_get_model( GTK_TREE_MODEL_FILTER( model ));
 
-		path = gtk_tree_row_reference_get_path (reference);
-		if (path == NULL)
-			continue;
+		for( it = rows ; it && !model->private->drag_has_profiles ; it = it->next ){
 
-		if (! gtk_tree_model_get_iter (model, &iter, path))
-			continue;
+			path = gtk_tree_row_reference_get_path(( GtkTreeRowReference * ) it->data );
+			gtk_tree_model_get_iter( store, &iter, path );
+			gtk_tree_model_get( store, &iter, IACTIONS_LIST_NAOBJECT_COLUMN, &object, -1 );
 
-		gtk_tree_model_get (model, &iter,
-				    COLUMN_FILE_DATA, &fdata,
-				    -1);
+			if( NA_IS_OBJECT_PROFILE( object )){
+				model->private->drag_has_profiles = TRUE;
+			}
 
-		if (fdata != NULL)
-			return TRUE;
-	}*/
+			g_object_unref( object );
+			gtk_tree_path_free( path );
+		}
+	}
 
 	return( TRUE );
 }
 
 /*
- * drag_data_get is called when we release the selected items onto the
+ * imulti_drag_source_drag_data_get:
+ * @context: contains
+ *  - the suggested action, as choosen by the drop site,
+ *    between those we have provided in imulti_drag_source_get_drag_actions()
+ *  - the target folder (XDS protocol)
+ * @selection_data:
+ * @rows: list of row references which are to be dropped
+ * @info: the suggested format, as choosen by the drop site, between those
+ *  we have provided in imulti_drag_source_get_target_list()
+ *
+ * This function is called when we release the selected items onto the
  * destination
  *
- * if some rows are selected
- * here, we only provide id. of dragged rows :
- * 		M:uuid
- * 		A:uuid
- * 		P:uuid/name
- * this is suitable and sufficient for the internal clipboard
+ * NACT_XCHANGE_FORMAT_NACT:
+ * internal format for drag and drop inside the treeview:
+ * - copy in the clipboard the list of row references
+ * - selection data is empty
  *
- * when exporting to the outside, we should prepare to export the items
+ * NACT_XCHANGE_FORMAT_XDS:
+ * exchange format to drop to outside:
+ * - copy in the clipboard the list of row references
+ * - set the destination folder
+ * - selection data is 'success' or 'failure'
+ *
+ * NACT_XCHANGE_FORMAT_APPLICATION_XML:
+ * NACT_XCHANGE_FORMAT_TEXT_PLAIN:
+ * exchange format to export to outside:
+ * - do not use dnd clipboard
+ * - selection data receives the export in text format
+ *
+ * Returns: %TRUE if required data was actually provided by the source,
+ * %FALSE else.
  */
 static gboolean
 imulti_drag_source_drag_data_get( EggTreeMultiDragSource *drag_source,
 				   GdkDragContext         *context,
 				   GtkSelectionData       *selection_data,
-				   GList                  *path_list,
+				   GList                  *rows,
 				   guint                   info )
 {
 	static const gchar *thisfn = "nact_tree_model_imulti_drag_source_drag_data_get";
 	gchar *atom_name;
 	NactTreeModel *model;
-	GList *selected_items;
 	gchar *data;
 	gboolean ret = FALSE;
 	gchar *dest_folder, *folder;
@@ -1337,67 +1431,63 @@ imulti_drag_source_drag_data_get( EggTreeMultiDragSource *drag_source,
 	gboolean copy_data;
 
 	atom_name = gdk_atom_name( selection_data->target );
-	g_debug( "%s: drag_source=%p, context=%p, action=%d, selection_data=%p, path_list=%p, atom=%s",
-			thisfn, ( void * ) drag_source, ( void * ) context, ( int ) context->suggested_action, ( void * ) selection_data, ( void * ) path_list,
+	g_debug( "%s: drag_source=%p, context=%p, action=%d, selection_data=%p, rows=%p, atom=%s",
+			thisfn, ( void * ) drag_source, ( void * ) context, ( int ) context->suggested_action, ( void * ) selection_data, ( void * ) rows,
 			atom_name );
 	g_free( atom_name );
 
 	model = NACT_TREE_MODEL( drag_source );
-	g_assert( model->private->window );
+	g_return_val_if_fail( model->private->window, FALSE );
 
-	selected_items = nact_iactions_list_get_selected_items( NACT_IACTIONS_LIST( model->private->window ));
-	if( !selected_items ){
-		return( FALSE );
-	}
-	if( !g_list_length( selected_items )){
-		g_list_free( selected_items );
-		return( FALSE );
-	}
+	if( !model->private->dispose_has_run ){
 
-	switch( info ){
-		case NACT_XCHANGE_FORMAT_NACT:
-			copy_data = ( context->suggested_action == GDK_ACTION_COPY );
-			nact_clipboard_get_data_for_intern_use( selected_items, copy_data );
-			gtk_selection_data_set( selection_data, selection_data->target, 8, ( guchar * ) "", 0 );
-			ret = TRUE;
-			break;
+		if( !rows || !g_list_length( rows )){
+			return( FALSE );
+		}
 
-		case NACT_XCHANGE_FORMAT_XDS:
-			folder = get_xds_atom_value( context );
-			dest_folder = na_utils_remove_last_level_from_path( folder );
-			g_free( folder );
-			is_writable = na_utils_is_writable_dir( dest_folder );
-			gtk_selection_data_set( selection_data, selection_data->target, 8, ( guchar * )( is_writable ? "S" : "F" ), 1 );
-			if( is_writable ){
-				model->private->drag_dest_uri = g_strdup( dest_folder );
-				model->private->drag_items = g_list_copy( selected_items );
-			}
-			g_free( dest_folder );
-			ret = TRUE;
-			break;
+		switch( info ){
+			case NACT_XCHANGE_FORMAT_NACT:
+				copy_data = ( context->action == GDK_ACTION_COPY );
+				gtk_selection_data_set( selection_data, selection_data->target, 8, ( guchar * ) "", 0 );
+				nact_clipboard_dnd_set( model->private->clipboard, info, rows, NULL, copy_data );
+				ret = TRUE;
+				break;
 
-		case NACT_XCHANGE_FORMAT_APPLICATION_XML:
-		case NACT_XCHANGE_FORMAT_TEXT_PLAIN:
-			data = nact_clipboard_get_data_for_extern_use( selected_items );
-			gtk_selection_data_set( selection_data, selection_data->target, 8, ( guchar * ) data, strlen( data ));
-			g_free( data );
-			ret = TRUE;
-			break;
+			case NACT_XCHANGE_FORMAT_XDS:
+				folder = get_xds_atom_value( context );
+				dest_folder = na_utils_remove_last_level_from_path( folder );
+				g_free( folder );
+				is_writable = na_utils_is_writable_dir( dest_folder );
+				gtk_selection_data_set( selection_data, selection_data->target, 8, ( guchar * )( is_writable ? "S" : "F" ), 1 );
+				if( is_writable ){
+					nact_clipboard_dnd_set( model->private->clipboard, info, rows, dest_folder, TRUE );
+				}
+				g_free( dest_folder );
+				ret = is_writable;
+				break;
 
-		default:
-			break;
+			case NACT_XCHANGE_FORMAT_APPLICATION_XML:
+			case NACT_XCHANGE_FORMAT_TEXT_PLAIN:
+				data = nact_clipboard_dnd_get_text( model->private->clipboard, rows );
+				gtk_selection_data_set( selection_data, selection_data->target, 8, ( guchar * ) data, strlen( data ));
+				g_free( data );
+				ret = TRUE;
+				break;
+
+			default:
+				break;
+		}
 	}
 
-	na_object_free_items( selected_items );
 	return( ret );
 }
 
 static gboolean
-imulti_drag_source_drag_data_delete( EggTreeMultiDragSource *drag_source, GList *path_list )
+imulti_drag_source_drag_data_delete( EggTreeMultiDragSource *drag_source, GList *rows )
 {
 	static const gchar *thisfn = "nact_tree_model_imulti_drag_source_drag_data_delete";
 
-	g_debug( "%s: drag_source=%p, path_list=%p", thisfn, ( void * ) drag_source, ( void * ) path_list );
+	g_debug( "%s: drag_source=%p, path_list=%p", thisfn, ( void * ) drag_source, ( void * ) rows );
 
 	return( TRUE );
 }
@@ -1419,18 +1509,199 @@ imulti_drag_source_get_drag_actions( EggTreeMultiDragSource *drag_source )
 }
 
 /*
- * TODO: empty the internal clipboard at drop time
+ * called when a drop from the outside occurs in the treeview
+ * this may be an import action, or a move/copy inside of the tree
+ *
+ * Returns: %TRUE if the specified rows were successfully inserted at
+ * the given dest, %FALSE else.
+ *
+ * When importing:
+ * - selection=XdndSelection
+ * - target=text/uri-list
+ * - type=text/uri-list
+ *
+ * When moving/copy from the treeview to the treeview:
+ * - selection=XdndSelection
+ * - target=XdndNautilusActions
+ * - type=XdndNautilusActions
  */
 static gboolean
 idrag_dest_drag_data_received( GtkTreeDragDest *drag_dest, GtkTreePath *dest, GtkSelectionData  *selection_data )
 {
 	static const gchar *thisfn = "nact_tree_model_idrag_dest_drag_data_received";
+	gboolean result = FALSE;
+	NactApplication *application;
+	NAPivot *pivot;
+	gchar *atom_name;
+	guint info;
+	GList *rows;
+	gboolean copy_data;
+	GSList *uri_list, *is, *msg;
+	gint import_mode;
+	NAObjectAction *action;
+	gchar *path_str;
+	GtkTreeIter iter;
+	NAObject *current;
+	gboolean inside_an_action;
+	GList *object_list, *it;
+	NactMainWindow *main_window;
+	gboolean drop_ok = TRUE;
+	NAObjectAction *parent = NULL;
+	GtkTreePath *path;
 
 	g_debug( "%s: drag_dest=%p, dest=%p, selection_data=%p", thisfn, ( void * ) drag_dest, ( void * ) dest, ( void * ) selection_data );
+	g_return_val_if_fail( NACT_IS_TREE_MODEL( drag_dest ), FALSE );
 
-	return( FALSE );
+	atom_name = gdk_atom_name( selection_data->selection );
+	g_debug( "%s: selection=%s", thisfn, atom_name );
+	g_free( atom_name );
+
+	atom_name = gdk_atom_name( selection_data->target );
+	g_debug( "%s: target=%s", thisfn, atom_name );
+	g_free( atom_name );
+
+	atom_name = gdk_atom_name( selection_data->type );
+	g_debug( "%s: type=%s", thisfn, atom_name );
+	g_free( atom_name );
+
+	g_debug( "%s: format=%d, length=%d", thisfn, selection_data->format, selection_data->length );
+
+	info = target_atom_to_id( selection_data->type );
+	g_debug( "%s: info=%u", thisfn, info );
+
+	application = NACT_APPLICATION( base_window_get_application( NACT_TREE_MODEL( drag_dest )->private->window ));
+	pivot = nact_application_get_pivot( application );
+	main_window = NACT_MAIN_WINDOW( base_application_get_main_window( BASE_APPLICATION( application )));
+
+	path_str = gtk_tree_path_to_string( dest );
+	g_debug( "%s: dest_path=%s", thisfn, path_str );
+	g_free( path_str );
+
+	/*
+	 * NACT format (may embed profiles, or not)
+	 * 	with profiles: only valid dest is inside an action
+	 *  without profile: only valid dest is outside (besides of) an action
+	 * URI format only involves actions
+	 *  ony valid dest in outside (besides of) an action
+	 */
+	inside_an_action = FALSE;
+	if( gtk_tree_model_get_iter( GTK_TREE_MODEL( drag_dest ), &iter, dest )){
+		gtk_tree_model_get( GTK_TREE_MODEL( drag_dest ), &iter, IACTIONS_LIST_NAOBJECT_COLUMN, &current, -1 );
+		g_debug( "%s: current object at dest is %s", thisfn, G_OBJECT_TYPE_NAME( current ));
+		if( NA_IS_OBJECT_PROFILE( current )){
+			inside_an_action = TRUE;
+			parent = na_object_profile_get_action( NA_OBJECT_PROFILE( current ));
+		}
+		g_object_unref( current );
+	}
+
+	switch( info ){
+		case NACT_XCHANGE_FORMAT_NACT:
+			if( NACT_TREE_MODEL( drag_dest )->private->drag_has_profiles ){
+				if( !inside_an_action ){
+					drop_ok = FALSE;
+					nact_main_statusbar_display_with_timeout(
+							main_window,
+							TREE_MODEL_STATUSBAR_CONTEXT,
+							_( "Unable to drop a profile outside of an action" ));
+				}
+			} else {
+				if( inside_an_action ){
+					drop_ok = FALSE;
+					nact_main_statusbar_display_with_timeout(
+							main_window,
+							TREE_MODEL_STATUSBAR_CONTEXT,
+							_( "Unable to drop an action or a menu inside of an action" ));
+				}
+			}
+			if( drop_ok ){
+				rows = nact_clipboard_dnd_get_data( NACT_TREE_MODEL( drag_dest )->private->clipboard, &copy_data );
+				g_debug( "%s: rows has %d items, copy_data=%s", thisfn, g_list_length( rows ), copy_data ? "True":"False" );
+				object_list = NULL;
+				for( it = rows ; it ; it = it->next ){
+					path = gtk_tree_row_reference_get_path(( GtkTreeRowReference * ) it->data );
+					if( path ){
+						if( gtk_tree_model_get_iter( GTK_TREE_MODEL( drag_dest ), &iter, path )){
+							gtk_tree_model_get( GTK_TREE_MODEL( drag_dest ), &iter, IACTIONS_LIST_NAOBJECT_COLUMN, &current, -1 );
+							if( copy_data ){
+								nact_main_window_prepare_object_for_copy( main_window, current, parent );
+							}
+							object_list = g_list_prepend( object_list, current );
+							g_object_unref( current );
+						}
+						gtk_tree_path_free( path );
+					}
+				}
+				object_list = g_list_reverse( object_list );
+				nact_iactions_list_insert_at_path( NACT_IACTIONS_LIST( main_window ), object_list, dest, FALSE );
+
+				if( !copy_data ){
+					nact_iactions_list_delete( NACT_IACTIONS_LIST( main_window ), object_list );
+				}
+
+				g_list_free( object_list );
+				g_list_foreach( rows, ( GFunc ) gtk_tree_row_reference_free, NULL );
+				g_list_free( rows );
+				result = TRUE;
+			}
+			break;
+
+		/* drop some actions from outside
+		 * most probably from the file manager as a list of uris
+		 */
+		case NACT_XCHANGE_FORMAT_URI_LIST:
+			if( inside_an_action ){
+
+				nact_main_statusbar_display_with_timeout(
+						main_window,
+						TREE_MODEL_STATUSBAR_CONTEXT,
+						_( "Unable to drop an action inside of another one" ));
+
+			} else {
+				uri_list = na_utils_lines_to_string_list(( const gchar * ) selection_data->data );
+				import_mode = na_iprefs_get_import_mode( NA_IPREFS( pivot ));
+				for( is = uri_list ; is ; is = is->next ){
+
+					action = nact_xml_reader_import(
+							NACT_TREE_MODEL( drag_dest )->private->window,
+							( const gchar * ) is->data,
+							import_mode,
+							&msg );
+
+					if( msg ){
+						nact_main_statusbar_display_with_timeout(
+								main_window,
+								TREE_MODEL_STATUSBAR_CONTEXT,
+								msg->data );
+						na_utils_free_string_list( msg );
+
+					} else {
+						g_return_val_if_fail( NA_IS_OBJECT_ACTION( action ), FALSE );
+						object_list = g_list_prepend( NULL, action );
+						nact_iactions_list_insert_at_path( NACT_IACTIONS_LIST( main_window ), object_list, dest, FALSE );
+						g_list_free( object_list );
+					}
+
+					if( action ){
+						g_return_val_if_fail( NA_IS_OBJECT_ACTION( action ), FALSE );
+						g_object_unref( action );
+					}
+				}
+				na_utils_free_string_list( uri_list );
+				result = TRUE;
+			}
+			break;
+
+		default:
+			break;
+	}
+
+	return( result );
 }
 
+/*
+ * called when the source and the dest are not at the same tree level ?
+ */
 static gboolean
 idrag_dest_row_drop_possible( GtkTreeDragDest *drag_dest, GtkTreePath *dest_path, GtkSelectionData *selection_data )
 {
@@ -1441,77 +1712,187 @@ idrag_dest_row_drop_possible( GtkTreeDragDest *drag_dest, GtkTreePath *dest_path
 	return( TRUE );
 }
 
-static gboolean
+static void
 on_drag_begin( GtkWidget *widget, GdkDragContext *context, BaseWindow *window )
 {
-	static const gchar *thisfn = "nact_clipboard_on_drag_begin";
+	static const gchar *thisfn = "nact_tree_model_on_drag_begin";
 	NactTreeModel *model;
 
 	g_debug( "%s: widget=%p, context=%p, window=%p",
 			thisfn, ( void * ) widget, ( void * ) context, ( void * ) window );
 
 	model = NACT_TREE_MODEL( gtk_tree_view_get_model( GTK_TREE_VIEW( widget )));
+	g_return_if_fail( NACT_IS_TREE_MODEL( model ));
 
-	g_free( model->private->drag_dest_uri );
-	model->private->drag_dest_uri = NULL;
+	if( !model->private->dispose_has_run ){
 
-	g_list_free( model->private->drag_items );
-	model->private->drag_items = NULL;
+		model->private->drag_highlight = FALSE;
+		model->private->drag_drop = FALSE;
 
-	gdk_property_change(
-			context->source_window,
-			XDS_ATOM, TEXT_ATOM, 8, GDK_PROP_MODE_REPLACE, ( guchar * ) XDS_FILENAME, strlen( XDS_FILENAME ));
+		nact_clipboard_dnd_clear( model->private->clipboard );
 
-	return( FALSE );
+		gdk_property_change(
+				context->source_window,
+				XDS_ATOM, TEXT_ATOM, 8, GDK_PROP_MODE_REPLACE, ( guchar * ) XDS_FILENAME, strlen( XDS_FILENAME ));
+	}
 }
 
-static void
-on_drag_end( GtkWidget *widget, GdkDragContext *context, BaseWindow *window )
+/*
+ * this function works well, but only called from on_drag_motion handler...
+ */
+/*static gboolean
+is_row_drop_possible( NactTreeModel *model, GtkTreePath *path, GtkTreeViewDropPosition pos )
 {
-	static const gchar *thisfn = "nact_clipboard_on_drag_end";
-	NactTreeModel *model;
+	gboolean ok = FALSE;
+	GtkTreeModel *store;
+	GtkTreeIter iter;
+	NAObject *object;
 
-	g_debug( "%s: widget=%p, context=%p, window=%p",
-			thisfn, ( void * ) widget, ( void * ) context, ( void * ) window );
+	store = gtk_tree_model_filter_get_model( GTK_TREE_MODEL_FILTER( model ));
+	gtk_tree_model_get_iter( store, &iter, path );
+	gtk_tree_model_get( store, &iter, IACTIONS_LIST_NAOBJECT_COLUMN, &object, -1 );
+
+	if( model->private->drag_has_profiles ){
+		if( NA_IS_OBJECT_PROFILE( object )){
+			ok = TRUE;
+		} else if( NA_IS_OBJECT_ACTION( object )){
+			ok = ( pos == GTK_TREE_VIEW_DROP_INTO_OR_BEFORE || pos == GTK_TREE_VIEW_DROP_INTO_OR_AFTER );
+		}
+	} else {
+		if( NA_IS_OBJECT_ITEM( object )){
+			ok = TRUE;
+		}
+	}
+
+	g_object_unref( object );
+	return( ok );
+}*/
+
+/*
+ * called when the user moves into the target widget
+ * returns TRUE if a drop zone
+ */
+#if 0
+static gboolean
+on_drag_motion( GtkWidget *widget, GdkDragContext *context, gint x, gint y, guint time, BaseWindow *window )
+{
+	NactTreeModel *model;
+	gboolean ok = FALSE;
+	GtkTreePath *path;
+	GtkTreeViewDropPosition pos;
 
 	model = NACT_TREE_MODEL( gtk_tree_view_get_model( GTK_TREE_VIEW( widget )));
+	g_return_val_if_fail( NACT_IS_TREE_MODEL( model ), FALSE );
 
-	if( model->private->drag_dest_uri && model->private->drag_items && g_list_length( model->private->drag_items )){
-		nact_clipboard_export_items( model->private->drag_dest_uri, model->private->drag_items );
-	}
+	if( !model->private->dispose_has_run ){
+
+		if( !model->private->drag_highlight ){
+			model->private->drag_highlight = TRUE;
+			gtk_drag_highlight( widget );
+		}
 
-	g_free( model->private->drag_dest_uri );
-	model->private->drag_dest_uri = NULL;
+		/*target = gtk_drag_dest_find_target( widget, context, NULL );
+		if( target == GDK_NONE ){
+			gdk_drag_status( context, 0, time );
+		} else {
+			gtk_drag_get_data( widget, context, target, time );
+		}*/
 
-	g_list_free( model->private->drag_items );
-	model->private->drag_items = NULL;
+		if( gtk_tree_view_get_dest_row_at_pos( GTK_TREE_VIEW( widget ), x, y, &path, &pos )){
+			ok = is_row_drop_possible( model, path, pos );
+			if( ok ){
+				gdk_drag_status( context, 0, time );
+			}
+		}
 
-	gdk_property_delete( context->source_window, XDS_ATOM );
+		gtk_tree_path_free( path );
+		g_debug( "nact_tree_model_on_drag_motion: ok=%s, pos=%d", ok ? "True":"False", pos );
+	}
+
+	return( ok );
 }
+#endif
 
+/*
+ * called when the user drops the data
+ * returns TRUE if a drop zone
+ */
 /*static gboolean
 on_drag_drop( GtkWidget *widget, GdkDragContext *context, gint x, gint y, guint time, BaseWindow *window )
 {
-	static const gchar *thisfn = "nact_clipboard_on_drag_drop";
+	NactTreeModel *model;
 
-	g_debug( "%s: widget=%p, context=%p, x=%d, y=%d, time=%d, window=%p",
-			thisfn, ( void * ) widget, ( void * ) context, x, y, time, ( void * ) window );
-*/
-	/*No!*/
-	/*gtk_drag_get_data( widget, context, NACT_ATOM, time );*/
+	model = NACT_TREE_MODEL( gtk_tree_view_get_model( GTK_TREE_VIEW( widget )));
+	g_return_val_if_fail( NACT_IS_TREE_MODEL( model ), FALSE );
 
-	/* return TRUE is the mouse pointer is on a drop zone, FALSE else */
-	/*return( TRUE );
+	if( !model->private->dispose_has_run ){
+
+		model->private->drag_drop = TRUE;
+	}
+
+	return( TRUE );
 }*/
 
-/*static void
-on_drag_data_received( GtkWidget *widget, GdkDragContext *drag_context, gint x, gint y, GtkSelectionData *data, guint info, guint time, BaseWindow *window )
+static void
+on_drag_end( GtkWidget *widget, GdkDragContext *context, BaseWindow *window )
 {
-	static const gchar *thisfn = "nact_tree_model_on_drag_data_received";
+	static const gchar *thisfn = "nact_tree_model_on_drag_end";
+	NactTreeModel *model;
 
-	g_debug( "%s: widget=%p, drag_context=%p, x=%d, y=%d, selection_data=%p, info=%d, time=%d, window=%p",
-			thisfn, ( void * ) widget, ( void * ) drag_context, x, y, ( void * ) data, info, time, ( void * ) window );
-}*/
+	g_debug( "%s: widget=%p, context=%p, window=%p",
+			thisfn, ( void * ) widget, ( void * ) context, ( void * ) window );
+
+	model = NACT_TREE_MODEL( gtk_tree_view_get_model( GTK_TREE_VIEW( widget )));
+	g_return_if_fail( NACT_IS_TREE_MODEL( model ));
+
+	if( !model->private->dispose_has_run ){
+
+		nact_clipboard_dnd_drag_end( model->private->clipboard );
+		nact_clipboard_dnd_clear( model->private->clipboard );
+		gdk_property_delete( context->source_window, XDS_ATOM );
+	}
+}
+
+/* The following function taken from bugzilla
+ * (http://bugzilla.gnome.org/attachment.cgi?id=49362&action=view)
+ * Author: Christian Neumair
+ * Copyright: 2005 Free Software Foundation, Inc
+ * License: GPL
+ */
+static char *
+get_xds_atom_value( GdkDragContext *context )
+{
+	char *ret;
+
+	g_return_val_if_fail (context != NULL, NULL);
+	g_return_val_if_fail (context->source_window != NULL, NULL);
+
+	gdk_property_get (context->source_window,
+						XDS_ATOM, TEXT_ATOM,
+						0, MAX_XDS_ATOM_VAL_LEN,
+						FALSE, NULL, NULL, NULL,
+						(unsigned char **) &ret);
+
+	return ret;
+}
+
+static guint
+target_atom_to_id( GdkAtom atom )
+{
+	gint i;
+	guint info = 0;
+	gchar *atom_name;
+
+	atom_name = gdk_atom_name( atom );
+	for( i = 0 ; i < G_N_ELEMENTS( dnd_dest_targets ) ; ++i ){
+		if( !g_ascii_strcasecmp( dnd_dest_targets[i].target, atom_name )){
+			info = dnd_dest_targets[i].info;
+			break;
+		}
+	}
+	g_free( atom_name );
+	return( info );
+}
 
 static gint
 sort_actions_list( GtkTreeModel *model, GtkTreeIter *a, GtkTreeIter *b, gpointer user_data )
@@ -1581,26 +1962,3 @@ filter_visible( GtkTreeModel *store, GtkTreeIter *iter, NactTreeModel *model )
 
 	return( FALSE );
 }
-
-/* The following function taken from bugzilla
- * (http://bugzilla.gnome.org/attachment.cgi?id=49362&action=view)
- * Author: Christian Neumair
- * Copyright: 2005 Free Software Foundation, Inc
- * License: GPL
- */
-static char *
-get_xds_atom_value (GdkDragContext *context)
-{
-	char *ret;
-
-	g_return_val_if_fail (context != NULL, NULL);
-	g_return_val_if_fail (context->source_window != NULL, NULL);
-
-	gdk_property_get (context->source_window,
-						XDS_ATOM, TEXT_ATOM,
-						0, MAX_XDS_ATOM_VAL_LEN,
-						FALSE, NULL, NULL, NULL,
-						(unsigned char **) &ret);
-
-	return ret;
-}
diff --git a/src/nact/nact-tree-model.h b/src/nact/nact-tree-model.h
index bf5f4ff..781e918 100644
--- a/src/nact/nact-tree-model.h
+++ b/src/nact/nact-tree-model.h
@@ -97,7 +97,7 @@ void         nact_tree_model_display( NactTreeModel *model, NAObject *object );
 void         nact_tree_model_display_order_change( NactTreeModel *model, gint order_mode );
 void         nact_tree_model_dump( NactTreeModel *model );
 void         nact_tree_model_fill( NactTreeModel *model, GList *items, gboolean only_actions);
-gchar       *nact_tree_model_insert( NactTreeModel *model, const NAObject *object, GtkTreePath *path, NAObject **parent );
+gchar       *nact_tree_model_insert( NactTreeModel *model, const NAObject *object, GtkTreePath *path, NAObject **parent, gboolean inside );
 void         nact_tree_model_iter( NactTreeModel *model, FnIterOnStore fn, gpointer user_data );
 GtkTreePath *nact_tree_model_remove( NactTreeModel *model, NAObject *object );
 
diff --git a/src/nact/nact-xml-reader.c b/src/nact/nact-xml-reader.c
index 939d367..59b171c 100644
--- a/src/nact/nact-xml-reader.c
+++ b/src/nact/nact-xml-reader.c
@@ -317,7 +317,7 @@ nact_xml_reader_import( BaseWindow *window, const gchar *uri, gint import_mode,
 	reader->private->window = window;
 	reader->private->import_mode = import_mode;
 
-	g_return_val_if_fail( BASE_IS_ASSISTANT( window ), NULL );
+	g_return_val_if_fail( BASE_IS_WINDOW( window ), NULL );
 
 	doc = xmlParseFile( uri );
 
diff --git a/src/nact/nautilus-actions-config-tool.ui b/src/nact/nautilus-actions-config-tool.ui
index 29f3107..62c0444 100644
--- a/src/nact/nautilus-actions-config-tool.ui
+++ b/src/nact/nautilus-actions-config-tool.ui
@@ -1799,7 +1799,7 @@ If there is no root submenu, a 'Nautilus Actions' one is created.</property>
                                   <object class="GtkLabel" id="label45">
                                     <property name="visible">True</property>
                                     <property name="xalign">0</property>
-                                    <property name="label" translatable="yes">What to do when pasting, duplicating or importing an action or a menu which already exists in the tree ?</property>
+                                    <property name="label" translatable="yes">What to do when pasting or duplicating an item in the tree ?</property>
                                     <property name="wrap">True</property>
                                   </object>
                                   <packing>
@@ -1941,7 +1941,7 @@ If there is no root submenu, a 'Nautilus Actions' one is created.</property>
                                     <property name="visible">True</property>
                                     <property name="can_focus">True</property>
                                     <property name="receives_default">False</property>
-                                    <property name="tooltip_text" translatable="yes">Imported actions whose UUID already exists will be renumbered. Depending on UI preferences, they may also be relabeled. Existing action will remain unchanged.</property>
+                                    <property name="tooltip_text" translatable="yes">Imported actions whose UUID already exists will be renumbered. A 'renumbered' mention will be added to the label of the item. Existing action will remain unchanged.</property>
                                     <property name="use_underline">True</property>
                                     <property name="draw_indicator">True</property>
                                     <property name="group">PrefsNoImportButton</property>
@@ -2058,16 +2058,16 @@ Be warned: you will not be prompted another time. This mode may be dangerous.	</
   </object>
   <object class="GtkSizeGroup" id="CommandLabelSizeGroup">
     <widgets>
-      <widget name="CommandExamplePreLabel"/>
-      <widget name="CommandParametersLabel"/>
-      <widget name="CommandPathLabel"/>
       <widget name="ProfileLabelLabel"/>
+      <widget name="CommandPathLabel"/>
+      <widget name="CommandParametersLabel"/>
+      <widget name="CommandExamplePreLabel"/>
     </widgets>
   </object>
   <object class="GtkSizeGroup" id="CommandButtonSizeGroup">
     <widgets>
-      <widget name="CommandLegendButton"/>
       <widget name="CommandPathButton"/>
+      <widget name="CommandLegendButton"/>
     </widgets>
   </object>
 </interface>



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