[nautilus-actions] Fix drag and drop when reordering items



commit 17d8e749e63f94939f7e11adfd4f0d5bba31e2c5
Author: Pierre Wieser <pwieser trychlos org>
Date:   Sun Oct 11 21:20:14 2009 +0200

    Fix drag and drop when reordering items

 ChangeLog                     |   15 ++
 src/nact/nact-iactions-list.c |   11 ++
 src/nact/nact-main-menubar.c  |   29 +++-
 src/nact/nact-main-window.c   |   20 ++-
 src/nact/nact-main-window.h   |    1 +
 src/nact/nact-tree-model.c    |  372 ++++++++++++++++++++++++++++-------------
 6 files changed, 328 insertions(+), 120 deletions(-)
---
diff --git a/ChangeLog b/ChangeLog
index 72154bb..f0f1ab9 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,18 @@
+2009-10-11 Pierre Wieser <pwieser trychlos org>
+
+	* src/nact/nact-iactions-list.c (do_insert_into_first):
+	Recursively insert subitems.
+
+	* src/nact/nact-main-menubar.c (on_level_zero_order_changed):
+	Connect to new signal to enable save action.
+
+	* src/nact/nact-main-window.c:
+	* src/nact/nact-main-window.h:
+	Define new signal "main-window-level-zero-order-changed".
+
+	* src/nact/nact-tree-model.c (idrag_dest_drag_data_received):
+	Fix drag and drop when reordering items.
+
 2009-10-09 Pierre Wieser <pwieser trychlos org>
 
 	* src/nact/nact-iactions-list.c (do_insert_into_first):
diff --git a/src/nact/nact-iactions-list.c b/src/nact/nact-iactions-list.c
index 125948d..bf3e28c 100644
--- a/src/nact/nact-iactions-list.c
+++ b/src/nact/nact-iactions-list.c
@@ -1232,6 +1232,7 @@ do_insert_into_first( GtkTreeView *treeview, GtkTreeModel *model, GList *items,
 	NAObject *parent;
 	gchar *insert_path_str;
 	GtkTreePath *inserted_path;
+	GList *subitems;
 
 	insert_path_str = gtk_tree_path_to_string( insert_path );
 	g_debug( "%s: treeview=%p, model=%p, items=%p (count=%d), insert_path=%p (%s), new_path=%p",
@@ -1247,6 +1248,15 @@ do_insert_into_first( GtkTreeView *treeview, GtkTreeModel *model, GList *items,
 
 	inserted_path = nact_tree_model_insert_into( NACT_TREE_MODEL( model ), NA_OBJECT( last->data ), insert_path, &parent );
 	gtk_tree_view_expand_to_path( treeview, inserted_path );
+
+	/* recursively insert subitems
+	 */
+	if( NA_IS_OBJECT_ITEM( last->data ) && na_object_get_items_count( last->data )){
+
+		subitems = na_object_get_items_list( last->data );
+		do_insert_into_first( treeview, model, subitems, inserted_path, NULL );
+	}
+
 	do_insert_items( treeview, model, copy, inserted_path, NULL );
 
 	if( new_path ){
@@ -1984,6 +1994,7 @@ select_row_at_path( NactIActionsList *instance, GtkTreeView *treeview, GtkTreeMo
 
 	if( path ){
 		g_debug( "nact_iactions_list_select_row_at_path: path=%s", gtk_tree_path_to_string( path ));
+		gtk_tree_view_expand_to_path( treeview, path );
 
 		if( gtk_tree_model_get_iter( model, &iter, path )){
 			gtk_tree_view_set_cursor( treeview, path, NULL, FALSE );
diff --git a/src/nact/nact-main-menubar.c b/src/nact/nact-main-menubar.c
index b195941..87f6328 100644
--- a/src/nact/nact-main-menubar.c
+++ b/src/nact/nact-main-menubar.c
@@ -84,6 +84,7 @@ typedef struct {
 	gboolean is_modified;
 	gboolean have_exportables;
 	gboolean treeview_has_focus;
+	gboolean level_zero_order_changed;
 }
 	MenubarIndicatorsStruct;
 
@@ -93,6 +94,7 @@ static void     on_iactions_list_count_updated( NactMainWindow *window, gint men
 static void     on_iactions_list_selection_changed( NactMainWindow *window, GList *selected );
 static void     on_iactions_list_focus_in( NactMainWindow *window, gpointer user_data );
 static void     on_iactions_list_focus_out( NactMainWindow *window, gpointer user_data );
+static void     on_level_zero_order_changed( NactMainWindow *window, gpointer user_data );
 static void     on_update_sensitivities( NactMainWindow *window, gpointer user_data );
 
 static void     on_new_menu_activated( GtkAction *action, NactMainWindow *window );
@@ -352,6 +354,12 @@ nact_main_menubar_runtime_init( NactMainWindow *window )
 			MAIN_WINDOW_SIGNAL_UPDATE_ACTION_SENSITIVITIES,
 			G_CALLBACK( on_update_sensitivities ));
 
+	base_window_signal_connect(
+			BASE_WINDOW( window ),
+			G_OBJECT( window ),
+			MAIN_WINDOW_SIGNAL_LEVEL_ZERO_ORDER_CHANGED,
+			G_CALLBACK( on_level_zero_order_changed ));
+
 	mis = g_new0( MenubarIndicatorsStruct, 1 );
 	g_object_set_data( G_OBJECT( window ), MENUBAR_PROP_INDICATORS, mis );
 }
@@ -446,6 +454,19 @@ on_iactions_list_focus_out( NactMainWindow *window, gpointer user_data )
 }
 
 static void
+on_level_zero_order_changed( NactMainWindow *window, gpointer user_data )
+{
+	MenubarIndicatorsStruct *mis;
+
+	g_debug( "nact_main_menubar_on_level_zero_order_changed" );
+	g_return_if_fail( NACT_IS_MAIN_WINDOW( window ));
+
+	mis = ( MenubarIndicatorsStruct * ) g_object_get_data( G_OBJECT( window ), MENUBAR_PROP_INDICATORS );
+	mis->level_zero_order_changed = TRUE;
+	g_signal_emit_by_name( window, MAIN_WINDOW_SIGNAL_UPDATE_ACTION_SENSITIVITIES, NULL );
+}
+
+static void
 on_update_sensitivities( NactMainWindow *window, gpointer user_data )
 {
 	static const gchar *thisfn = "nact_main_menubar_on_update_sensitivities";
@@ -529,7 +550,7 @@ on_update_sensitivities( NactMainWindow *window, gpointer user_data )
 	/* new profile enabled if selection is relative to only one action */
 	enable_item( window, "NewProfileItem", item != NULL && !NA_IS_OBJECT_MENU( item ));
 	/* save enabled if at least one item has been modified */
-	enable_item( window, "SaveItem", has_modified );
+	enable_item( window, "SaveItem", has_modified || mis->level_zero_order_changed );
 	/* quit always enabled */
 
 	/* edit menu (cf. above) */
@@ -624,6 +645,7 @@ on_save_activated( GtkAction *gtk_action, NactMainWindow *window )
 	GList *items;
 	NactApplication *application;
 	NAPivot *pivot;
+	MenubarIndicatorsStruct *mis;
 
 	g_debug( "%s: gtk_action=%p, window=%p", thisfn, ( void * ) gtk_action, ( void * ) window );
 	g_return_if_fail( GTK_IS_ACTION( gtk_action ));
@@ -644,6 +666,11 @@ on_save_activated( GtkAction *gtk_action, NactMainWindow *window )
 	save_items( window, pivot, items );
 	g_list_free( items );
 
+	/* reset level zero indicator
+	 */
+	mis = ( MenubarIndicatorsStruct * ) g_object_get_data( G_OBJECT( window ), MENUBAR_PROP_INDICATORS );
+	mis->level_zero_order_changed = FALSE;
+
 	/* required as selection has not changed
 	 */
 	g_signal_emit_by_name( window, MAIN_WINDOW_SIGNAL_UPDATE_ACTION_SENSITIVITIES, NULL );
diff --git a/src/nact/nact-main-window.c b/src/nact/nact-main-window.c
index 17bd3ff..ad759b8 100644
--- a/src/nact/nact-main-window.c
+++ b/src/nact/nact-main-window.c
@@ -110,6 +110,7 @@ enum {
 	SELECTION_CHANGED,
 	ITEM_UPDATED,
 	UPDATE_SENSITIVITIES,
+	ORDER_CHANGED,
 	LAST_SIGNAL
 };
 
@@ -360,6 +361,24 @@ class_init( NactMainWindowClass *klass )
 			G_TYPE_NONE,
 			1,
 			G_TYPE_POINTER );
+
+	/**
+	 * main-window-level-zero-order-changed:
+	 *
+	 * This signal is emitted each time a user interaction may led the
+	 * action sensitivities to be updated.
+	 */
+	st_signals[ ORDER_CHANGED ] = g_signal_new(
+			MAIN_WINDOW_SIGNAL_LEVEL_ZERO_ORDER_CHANGED,
+			G_TYPE_OBJECT,
+			G_SIGNAL_RUN_LAST,
+			0,					/* no default handler */
+			NULL,
+			NULL,
+			g_cclosure_marshal_VOID__POINTER,
+			G_TYPE_NONE,
+			1,
+			G_TYPE_POINTER );
 }
 
 static void
@@ -788,7 +807,6 @@ nact_main_window_remove_deleted( NactMainWindow *window )
 			actually_delete_item( window, item, pivot );
 		}
 
-		g_debug( "nact_main_window_remove_deleted: before free deleted" );
 		na_object_free_items_list( window->private->deleted );
 		window->private->deleted = NULL;
 	}
diff --git a/src/nact/nact-main-window.h b/src/nact/nact-main-window.h
index 6e8a6c2..b24b996 100644
--- a/src/nact/nact-main-window.h
+++ b/src/nact/nact-main-window.h
@@ -70,6 +70,7 @@ typedef struct {
 	NactMainWindowClass;
 
 #define MAIN_WINDOW_SIGNAL_UPDATE_ACTION_SENSITIVITIES	"main-window-update-sensitivities"
+#define MAIN_WINDOW_SIGNAL_LEVEL_ZERO_ORDER_CHANGED		"main-window-level-zero-order-changed"
 
 GType           nact_main_window_get_type( void );
 
diff --git a/src/nact/nact-tree-model.c b/src/nact/nact-tree-model.c
index 62921da..13a055c 100644
--- a/src/nact/nact-tree-model.c
+++ b/src/nact/nact-tree-model.c
@@ -189,6 +189,9 @@ static GtkTargetList *imulti_drag_source_get_target_list( EggTreeMultiDragSource
 static GdkDragAction  imulti_drag_source_get_drag_actions( EggTreeMultiDragSource *drag_source );
 
 static gboolean       idrag_dest_drag_data_received( GtkTreeDragDest *drag_dest, GtkTreePath *dest, GtkSelectionData  *selection_data );
+static gboolean       inside_drag_and_drop( NactTreeModel *model, GtkTreePath *dest, GtkSelectionData  *selection_data );
+static GtkTreePath   *is_drop_possible( NactTreeModel *model, GtkTreePath *dest, NAObjectAction **parent );
+static gboolean       drop_uri_list( NactTreeModel *model, GtkTreePath *dest, GtkSelectionData  *selection_data );
 static gboolean       idrag_dest_row_drop_possible( GtkTreeDragDest *drag_dest, GtkTreePath *dest_path, GtkSelectionData *selection_data );
 
 static void           on_drag_begin( GtkWidget *widget, GdkDragContext *context, BaseWindow *window );
@@ -810,12 +813,8 @@ nact_tree_model_insert( NactTreeModel *model, const NAObject *object, GtkTreePat
 				GTK_TREE_STORE( store ), &iter,
 				has_parent ? &parent_iter : NULL,
 				has_sibling ? &sibling_iter : NULL );
-		g_debug( "un" );
-		g_debug( "%s: iter_is_valid=%s", thisfn, gtk_tree_store_iter_is_valid( GTK_TREE_STORE( store ), &iter ) ? "True":"False" );
 		gtk_tree_store_set( GTK_TREE_STORE( store ), &iter, IACTIONS_LIST_NAOBJECT_COLUMN, object, -1 );
-		g_debug( "deux" );
 		display_item( GTK_TREE_STORE( store ), model->private->treeview, &iter, object );
-		g_debug( "trois" );
 	}
 }
 
@@ -877,6 +876,8 @@ remove_if_exists( NactTreeModel *model, GtkTreeModel *store, const NAObject *obj
 
 	if( NA_IS_OBJECT_ITEM( object )){
 		if( search_for_object_id( model, store, object, &iter )){
+			g_debug( "nact_tree_model_remove_if_exists: removing %s %p",
+					G_OBJECT_TYPE_NAME( object ), ( void * ) object );
 			gtk_tree_store_remove( GTK_TREE_STORE( store ), &iter );
 		}
 	}
@@ -1082,8 +1083,8 @@ iter_on_store_item( NactTreeModel *model, GtkTreeModel *store, GtkTreeIter *iter
 	 * unchanged in dump_store
 	 */
 	g_object_unref( object );
-	g_debug( "nact_tree_model_iter_on_store_item: object=%p (%s, ref_count=%d)",
-			( void * ) object, G_OBJECT_TYPE_NAME( object ), G_OBJECT( object )->ref_count );
+	/*g_debug( "nact_tree_model_iter_on_store_item: object=%p (%s, ref_count=%d)",
+			( void * ) object, G_OBJECT_TYPE_NAME( object ), G_OBJECT( object )->ref_count );*/
 
 	path = gtk_tree_model_get_path( store, iter );
 
@@ -1392,24 +1393,9 @@ idrag_dest_drag_data_received( GtkTreeDragDest *drag_dest, GtkTreePath *dest, Gt
 {
 	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 );
@@ -1431,14 +1417,58 @@ idrag_dest_drag_data_received( GtkTreeDragDest *drag_dest, GtkTreePath *dest, Gt
 	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 );
 
+	switch( info ){
+		case NACT_XCHANGE_FORMAT_NACT:
+			result = inside_drag_and_drop( NACT_TREE_MODEL( drag_dest ), dest, selection_data );
+			break;
+
+		/* drop some actions from outside
+		 * most probably from the file manager as a list of uris
+		 */
+		case NACT_XCHANGE_FORMAT_URI_LIST:
+			result = drop_uri_list( NACT_TREE_MODEL( drag_dest ), dest, selection_data );
+			break;
+
+		default:
+			break;
+	}
+
+	return( result );
+}
+
+/*
+ * called when a drop occurs in the treeview for a move/copy inside of
+ * the tree
+ *
+ * Returns: %TRUE if the specified rows were successfully inserted at
+ * the given dest, %FALSE else.
+ */
+static gboolean
+inside_drag_and_drop( NactTreeModel *model, GtkTreePath *dest, GtkSelectionData  *selection_data )
+{
+	static const gchar *thisfn = "nact_tree_model_inside_drag_and_drop";
+	gboolean drop_done;
+	NactApplication *application;
+	NAPivot *pivot;
+	NactMainWindow *main_window;
+	NAObjectAction *parent;
+	gboolean copy_data;
+	GList *rows;
+	GtkTreePath *new_dest;
+	GtkTreePath *path;
+	NAObject *current;
+	NAObject *inserted;
+	GList *object_list, *it;
+	GtkTreeIter iter;
+
+	application = NACT_APPLICATION( base_window_get_application( model->private->window ));
+	pivot = nact_application_get_pivot( application );
+	main_window = NACT_MAIN_WINDOW( base_application_get_main_window( BASE_APPLICATION( application )));
+
 	/*
 	 * NACT format (may embed profiles, or not)
 	 * 	with profiles: only valid dest is inside an action
@@ -1446,121 +1476,227 @@ idrag_dest_drag_data_received( GtkTreeDragDest *drag_dest, GtkTreePath *dest, Gt
 	 * 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_ACTION( na_object_get_parent( current ));
+	drop_done = FALSE;
+	parent = NULL;
+	new_dest = is_drop_possible( model, dest, &parent );
+
+	if( new_dest ){
+		rows = nact_clipboard_dnd_get_data( model->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( model ), &iter, path )){
+					gtk_tree_model_get( GTK_TREE_MODEL( model ), &iter, IACTIONS_LIST_NAOBJECT_COLUMN, &current, -1 );
+					g_object_unref( current );
+					if( copy_data ){
+						inserted = na_object_duplicate( current );
+						na_object_set_origin( inserted, NULL );
+						na_object_prepare_for_paste( inserted, pivot, TRUE, parent );
+					} else {
+						inserted = na_object_ref( current );
+					}
+					object_list = g_list_prepend( object_list, inserted );
+				}
+				gtk_tree_path_free( path );
+			}
 		}
-		g_object_unref( current );
+		object_list = g_list_reverse( object_list );
+
+		if( !copy_data ){
+			nact_iactions_list_delete( NACT_IACTIONS_LIST( main_window ), object_list );
+		}
+
+		nact_iactions_list_insert_at_path( NACT_IACTIONS_LIST( main_window ), object_list, dest );
+
+		if( !copy_data ){
+			g_signal_emit_by_name( main_window, MAIN_WINDOW_SIGNAL_LEVEL_ZERO_ORDER_CHANGED, NULL );
+		}
+
+		g_list_foreach( object_list, ( GFunc ) na_object_object_unref, NULL );
+		g_list_free( object_list );
+		g_list_foreach( rows, ( GFunc ) gtk_tree_row_reference_free, NULL );
+		g_list_free( rows );
+		gtk_tree_path_free( new_dest );
+
+		drop_done = TRUE;
 	}
 
-	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 ){
-								na_object_prepare_for_paste( current, pivot, TRUE, 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 );
+	return( drop_done );
+}
 
-				if( !copy_data ){
-					nact_iactions_list_delete( NACT_IACTIONS_LIST( main_window ), object_list );
-				}
+/*
+ * is a drop possible at given dest ?
+ * may slightly adjust the dest to drop profile inside an action
+ */
+static GtkTreePath *
+is_drop_possible( NactTreeModel *model, GtkTreePath *dest, NAObjectAction **parent )
+{
+	static const gchar *thisfn = "nact_tree_model_is_drop_possible";
+	static const gchar *refuse_profile = N_( "Unable to drop a profile here" );
+	static const gchar *refuse_action_menu = N_( "Unable to drop an action or a menu here" );
+	GtkTreePath *new_dest;
+	gboolean drop_ok;
+	NactApplication *application;
+	NAPivot *pivot;
+	NactMainWindow *main_window;
+	GtkTreeIter iter;
+	NAObject *current;
+	GtkTreePath *path;
 
-				g_list_free( object_list );
-				g_list_foreach( rows, ( GFunc ) gtk_tree_row_reference_free, NULL );
-				g_list_free( rows );
-				result = TRUE;
-			}
-			break;
+	application = NACT_APPLICATION( base_window_get_application( model->private->window ));
+	pivot = nact_application_get_pivot( application );
+	main_window = NACT_MAIN_WINDOW( base_application_get_main_window( BASE_APPLICATION( application )));
 
-		/* 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 ){
+	new_dest = gtk_tree_path_copy( dest );
+	drop_ok = FALSE;
+
+	/* if we can have an iter on given dest, then the dest already exists
+	 * so dropped items should be of the same type that already existing
+	 */
+	if( gtk_tree_model_get_iter( GTK_TREE_MODEL( model ), &iter, new_dest )){
+		gtk_tree_model_get( GTK_TREE_MODEL( model ), &iter, IACTIONS_LIST_NAOBJECT_COLUMN, &current, -1 );
+		g_object_unref( current );
+		g_debug( "%s: current object at dest is %s", thisfn, G_OBJECT_TYPE_NAME( current ));
 
+		if( model->private->drag_has_profiles ){
+			if( NA_IS_OBJECT_PROFILE( current )){
+				drop_ok = TRUE;
+				*parent = NA_OBJECT_ACTION( na_object_get_parent( current ));
+			} else {
 				nact_main_statusbar_display_with_timeout(
-						main_window,
-						TREE_MODEL_STATUSBAR_CONTEXT,
-						_( "Unable to drop an action inside of another one" ));
+						main_window, TREE_MODEL_STATUSBAR_CONTEXT, refuse_profile );
+			}
 
+		} else {
+			if( NA_IS_OBJECT_ITEM( current )){
+				drop_ok = TRUE;
 			} 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 ){
+				nact_main_statusbar_display_with_timeout(
+						main_window, TREE_MODEL_STATUSBAR_CONTEXT, refuse_action_menu );
+			}
+		}
 
-					action = nact_xml_reader_import(
-							NACT_TREE_MODEL( drag_dest )->private->window,
-							( const gchar * ) is->data,
-							import_mode,
-							&msg );
+	/* inserting at the end of the list
+	 */
+	} else if( gtk_tree_path_get_depth( dest ) == 1 ){
+		if( model->private->drag_has_profiles ){
+			nact_main_statusbar_display_with_timeout(
+						main_window, TREE_MODEL_STATUSBAR_CONTEXT, refuse_profile );
+		} else {
+			drop_ok = TRUE;
+		}
 
-					if( msg ){
-						nact_main_statusbar_display_with_timeout(
-								main_window,
-								TREE_MODEL_STATUSBAR_CONTEXT,
-								msg->data );
-						na_utils_free_string_list( msg );
+	/* we cannot have an iter on the dest: this means that we try to
+	 * insert items into the dest : check what is the parent
+	 */
+	} else {
+		path = gtk_tree_path_copy( dest );
+		if( gtk_tree_path_up( path )){
+			if( gtk_tree_model_get_iter( GTK_TREE_MODEL( model ), &iter, path )){
+				gtk_tree_model_get( GTK_TREE_MODEL( model ), &iter, IACTIONS_LIST_NAOBJECT_COLUMN, &current, -1 );
+				g_object_unref( current );
+				g_debug( "%s: current object at parent dest is %s", thisfn, G_OBJECT_TYPE_NAME( current ));
+
+				if( model->private->drag_has_profiles ){
+					if( NA_IS_OBJECT_ACTION( current )){
+						drop_ok = TRUE;
+						*parent = NA_OBJECT_ACTION( current );
+
+					} else if( NA_IS_OBJECT_PROFILE( current )){
+						gtk_tree_path_free( new_dest );
+						new_dest = gtk_tree_path_copy( path );
+						drop_ok = TRUE;
+						*parent = NA_OBJECT_ACTION( na_object_get_parent( current ));
 
 					} else {
-						g_return_val_if_fail( NA_IS_OBJECT_ACTION( action ), FALSE );
-						object_list = g_list_prepend( NULL, action );
-						na_object_dump( action );
-						nact_iactions_list_insert_at_path( NACT_IACTIONS_LIST( main_window ), object_list, dest );
-						g_list_free( object_list );
+						nact_main_statusbar_display_with_timeout(
+								main_window, TREE_MODEL_STATUSBAR_CONTEXT, refuse_profile );
 					}
 
-					if( action ){
-						g_return_val_if_fail( NA_IS_OBJECT_ACTION( action ), FALSE );
-						na_object_unref( action );
+				} else {
+					if( NA_IS_OBJECT_MENU( current )){
+						drop_ok = TRUE;
+					} else {
+						nact_main_statusbar_display_with_timeout(
+								main_window, TREE_MODEL_STATUSBAR_CONTEXT, refuse_action_menu );
 					}
 				}
-				nact_tree_model_dump( NACT_TREE_MODEL( drag_dest ));
-				na_utils_free_string_list( uri_list );
-				result = TRUE;
 			}
-			break;
+		}
+		gtk_tree_path_free( path );
+	}
 
-		default:
-			break;
+	if( !drop_ok ){
+		gtk_tree_path_free( new_dest );
+		new_dest = NULL;
 	}
 
-	return( result );
+	return( new_dest );
+}
+
+/*
+ * called when a drop from the outside occurs in the treeview
+ *
+ * Returns: %TRUE if the specified rows were successfully inserted at
+ * the given dest, %FALSE else.
+ */
+static gboolean
+drop_uri_list( NactTreeModel *model, GtkTreePath *dest, GtkSelectionData  *selection_data )
+{
+	/*static const gchar *thisfn = "nact_tree_model_drop_from_outside";*/
+	gboolean drop_done = FALSE;
+	GSList *uri_list, *is, *msg;
+	NactApplication *application;
+	NAPivot *pivot;
+	gint import_mode;
+	NAObjectAction *action;
+	NactMainWindow *main_window;
+	GList *object_list;
+
+	application = NACT_APPLICATION( base_window_get_application( model->private->window ));
+	pivot = nact_application_get_pivot( application );
+	main_window = NACT_MAIN_WINDOW( base_application_get_main_window( BASE_APPLICATION( application )));
+
+	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(
+				model->private->window,
+				( const gchar * ) is->data,
+				import_mode,
+				&msg );
+
+		if( msg ){
+			main_window = NACT_MAIN_WINDOW( base_application_get_main_window( BASE_APPLICATION( application )));
+			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 );
+			na_object_dump( action );
+			nact_iactions_list_insert_at_path( NACT_IACTIONS_LIST( main_window ), object_list, dest );
+			g_list_free( object_list );
+			drop_done = TRUE;
+		}
+
+		if( action ){
+			g_return_val_if_fail( NA_IS_OBJECT_ACTION( action ), FALSE );
+			na_object_unref( action );
+		}
+	}
+
+	nact_tree_model_dump( model );
+	na_utils_free_string_list( uri_list );
+
+	return( drop_done );
 }
 
 /*



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