From dfbcaea807e940db1f55863d71b8b40775362aa2 Mon Sep 17 00:00:00 2001 From: Benedikt Meurer <benny@xfce.org> Date: Thu, 9 Mar 2006 00:56:06 +0000 Subject: [PATCH] 2006-03-09 Benedikt Meurer <benny@xfce.org> * thunar/thunar-shortcuts-view.c: Add support to drop files to folders listed in the shortcuts pane. Bug #1345. (Old svn revision: 20303) --- ChangeLog | 5 + thunar/thunar-shortcuts-view.c | 552 +++++++++++++++++++++++++-------- 2 files changed, 426 insertions(+), 131 deletions(-) diff --git a/ChangeLog b/ChangeLog index d734fbe0b..d8b6168c6 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2006-03-09 Benedikt Meurer <benny@xfce.org> + + * thunar/thunar-shortcuts-view.c: Add support to drop files to folders + listed in the shortcuts pane. Bug #1345. + 2006-03-08 Benedikt Meurer <benny@xfce.org> * thunar/thunar-view.{c,h}: Add new methods get_visible_range() and diff --git a/thunar/thunar-shortcuts-view.c b/thunar/thunar-shortcuts-view.c index b27c4f267..ad7cdf844 100644 --- a/thunar/thunar-shortcuts-view.c +++ b/thunar/thunar-shortcuts-view.c @@ -26,6 +26,7 @@ #include <thunar/thunar-application.h> #include <thunar/thunar-dialogs.h> +#include <thunar/thunar-dnd.h> #include <thunar/thunar-preferences.h> #include <thunar/thunar-shortcuts-icon-renderer.h> #include <thunar/thunar-shortcuts-model.h> @@ -49,54 +50,64 @@ enum -static void thunar_shortcuts_view_class_init (ThunarShortcutsViewClass *klass); -static void thunar_shortcuts_view_init (ThunarShortcutsView *view); -static void thunar_shortcuts_view_finalize (GObject *object); -static gboolean thunar_shortcuts_view_button_press_event (GtkWidget *widget, - GdkEventButton *event); -static gboolean thunar_shortcuts_view_button_release_event (GtkWidget *widget, - GdkEventButton *event); -static void thunar_shortcuts_view_drag_begin (GtkWidget *widget, - GdkDragContext *context); -static void thunar_shortcuts_view_drag_data_received (GtkWidget *widget, - GdkDragContext *context, - gint x, - gint y, - GtkSelectionData *selection_data, - guint info, - guint time); -static gboolean thunar_shortcuts_view_drag_drop (GtkWidget *widget, - GdkDragContext *context, - gint x, - gint y, - guint time); -static gboolean thunar_shortcuts_view_drag_motion (GtkWidget *widget, - GdkDragContext *context, - gint x, - gint y, - guint time); -static void thunar_shortcuts_view_remove_activated (GtkWidget *item, - ThunarShortcutsView *view); -static void thunar_shortcuts_view_rename_activated (GtkWidget *item, - ThunarShortcutsView *view); -static void thunar_shortcuts_view_renamed (GtkCellRenderer *renderer, - const gchar *path_string, - const gchar *text, - ThunarShortcutsView *view); -static GtkTreePath *thunar_shortcuts_view_compute_drop_position (ThunarShortcutsView *view, - gint x, - gint y); -static void thunar_shortcuts_view_drop_uri_list (ThunarShortcutsView *view, - const gchar *uri_list, - GtkTreePath *dst_path); -static void thunar_shortcuts_view_open (ThunarShortcutsView *view); -static void thunar_shortcuts_view_open_in_new_window (ThunarShortcutsView *view); -static gboolean thunar_shortcuts_view_eject (ThunarShortcutsView *view); -static gboolean thunar_shortcuts_view_mount (ThunarShortcutsView *view); -static gboolean thunar_shortcuts_view_unmount (ThunarShortcutsView *view); -static gboolean thunar_shortcuts_view_separator_func (GtkTreeModel *model, - GtkTreeIter *iter, - gpointer user_data); +static void thunar_shortcuts_view_class_init (ThunarShortcutsViewClass *klass); +static void thunar_shortcuts_view_init (ThunarShortcutsView *view); +static void thunar_shortcuts_view_finalize (GObject *object); +static gboolean thunar_shortcuts_view_button_press_event (GtkWidget *widget, + GdkEventButton *event); +static gboolean thunar_shortcuts_view_button_release_event (GtkWidget *widget, + GdkEventButton *event); +static void thunar_shortcuts_view_drag_begin (GtkWidget *widget, + GdkDragContext *context); +static void thunar_shortcuts_view_drag_data_received (GtkWidget *widget, + GdkDragContext *context, + gint x, + gint y, + GtkSelectionData *selection_data, + guint info, + guint time); +static gboolean thunar_shortcuts_view_drag_drop (GtkWidget *widget, + GdkDragContext *context, + gint x, + gint y, + guint time); +static gboolean thunar_shortcuts_view_drag_motion (GtkWidget *widget, + GdkDragContext *context, + gint x, + gint y, + guint time); +static void thunar_shortcuts_view_drag_leave (GtkWidget *widget, + GdkDragContext *context, + guint time); +static void thunar_shortcuts_view_remove_activated (GtkWidget *item, + ThunarShortcutsView *view); +static void thunar_shortcuts_view_rename_activated (GtkWidget *item, + ThunarShortcutsView *view); +static void thunar_shortcuts_view_renamed (GtkCellRenderer *renderer, + const gchar *path_string, + const gchar *text, + ThunarShortcutsView *view); +static GdkDragAction thunar_shortcuts_view_compute_drop_actions (ThunarShortcutsView *view, + GdkDragContext *context, + gint x, + gint y, + GtkTreePath **path_return, + GdkDragAction *action_return, + GtkTreeViewDropPosition *position_return); +static GtkTreePath *thunar_shortcuts_view_compute_drop_position (ThunarShortcutsView *view, + gint x, + gint y); +static void thunar_shortcuts_view_drop_uri_list (ThunarShortcutsView *view, + GList *path_list, + GtkTreePath *dst_path); +static void thunar_shortcuts_view_open (ThunarShortcutsView *view); +static void thunar_shortcuts_view_open_in_new_window (ThunarShortcutsView *view); +static gboolean thunar_shortcuts_view_eject (ThunarShortcutsView *view); +static gboolean thunar_shortcuts_view_mount (ThunarShortcutsView *view); +static gboolean thunar_shortcuts_view_unmount (ThunarShortcutsView *view); +static gboolean thunar_shortcuts_view_separator_func (GtkTreeModel *model, + GtkTreeIter *iter, + gpointer user_data); @@ -109,6 +120,7 @@ struct _ThunarShortcutsView { GtkTreeView __parent__; ThunarPreferences *preferences; + GtkCellRenderer *icon_renderer; /* the currently pressed mouse button, set in the * button-press-event handler if the associated @@ -116,6 +128,11 @@ struct _ThunarShortcutsView */ gint pressed_button; + /* drop site support */ + guint drop_data_ready : 1; /* whether the drop data was received already */ + guint drop_occurred : 1; + GList *drop_path_list; /* the list of URIs that are contained in the drop data */ + #if GTK_CHECK_VERSION(2,8,0) /* id of the signal used to queue a resize on the * column whenever the shortcuts icon size is changed. @@ -192,6 +209,7 @@ thunar_shortcuts_view_class_init (ThunarShortcutsViewClass *klass) gtkwidget_class->drag_data_received = thunar_shortcuts_view_drag_data_received; gtkwidget_class->drag_drop = thunar_shortcuts_view_drag_drop; gtkwidget_class->drag_motion = thunar_shortcuts_view_drag_motion; + gtkwidget_class->drag_leave = thunar_shortcuts_view_drag_leave; /** * ThunarShortcutsView:shortcut-activated: @@ -241,9 +259,9 @@ thunar_shortcuts_view_init (ThunarShortcutsView *view) #endif /* allocate the special icon renderer */ - renderer = thunar_shortcuts_icon_renderer_new (); - gtk_tree_view_column_pack_start (column, renderer, FALSE); - gtk_tree_view_column_set_attributes (column, renderer, + view->icon_renderer = thunar_shortcuts_icon_renderer_new (); + gtk_tree_view_column_pack_start (column, view->icon_renderer, FALSE); + gtk_tree_view_column_set_attributes (column, view->icon_renderer, "file", THUNAR_SHORTCUTS_MODEL_COLUMN_FILE, "volume", THUNAR_SHORTCUTS_MODEL_COLUMN_VOLUME, NULL); @@ -251,8 +269,8 @@ thunar_shortcuts_view_init (ThunarShortcutsView *view) /* sync the "emblems" property of the icon renderer with the "shortcuts-icon-emblems" preference * and the "size" property of the renderer with the "shortcuts-icon-size" preference. */ - exo_binding_new (G_OBJECT (view->preferences), "shortcuts-icon-size", G_OBJECT (renderer), "size"); - exo_binding_new (G_OBJECT (view->preferences), "shortcuts-icon-emblems", G_OBJECT (renderer), "emblems"); + exo_binding_new (G_OBJECT (view->preferences), "shortcuts-icon-size", G_OBJECT (view->icon_renderer), "size"); + exo_binding_new (G_OBJECT (view->preferences), "shortcuts-icon-emblems", G_OBJECT (view->icon_renderer), "emblems"); /* allocate the text renderer */ renderer = gtk_cell_renderer_text_new (); @@ -269,8 +287,7 @@ thunar_shortcuts_view_init (ThunarShortcutsView *view) /* enable drop support for the shortcuts view (both internal reordering * and adding new shortcuts from other widgets) */ - gtk_drag_dest_set (GTK_WIDGET (view), GTK_DEST_DEFAULT_ALL, - drop_targets, G_N_ELEMENTS (drop_targets), + gtk_drag_dest_set (GTK_WIDGET (view), 0, drop_targets, G_N_ELEMENTS (drop_targets), GDK_ACTION_COPY | GDK_ACTION_LINK | GDK_ACTION_MOVE); /* setup a row separator function to tell GtkTreeView about the separator */ @@ -284,6 +301,9 @@ thunar_shortcuts_view_finalize (GObject *object) { ThunarShortcutsView *view = THUNAR_SHORTCUTS_VIEW (object); + /* release drop path list (if drag_leave wasn't called) */ + thunar_vfs_path_list_free (view->drop_path_list); + /* disconnect the queue resize signal handler */ #if GTK_CHECK_VERSION(2,8,0) g_signal_handler_disconnect (G_OBJECT (view->preferences), view->queue_resize_signal_id); @@ -567,24 +587,137 @@ thunar_shortcuts_view_drag_data_received (GtkWidget *widget, guint info, guint time) { - ThunarShortcutsView *view = THUNAR_SHORTCUTS_VIEW (widget); - GtkTreeSelection *selection; - GtkTreeModel *model; - GtkTreePath *dst_path; - GtkTreePath *src_path; - GtkTreeIter iter; + GtkTreeViewDropPosition position = GTK_TREE_VIEW_DROP_BEFORE; + ThunarShortcutsView *view = THUNAR_SHORTCUTS_VIEW (widget); + GdkDragAction actions; + GdkDragAction action; + GtkTreeModel *model; + GtkTreePath *path; + GtkTreeIter iter; + ThunarFile *file; + gboolean succeed = FALSE; g_return_if_fail (THUNAR_IS_SHORTCUTS_VIEW (view)); - /* compute the drop position */ - dst_path = thunar_shortcuts_view_compute_drop_position (view, x, y); + /* check if we don't already know the drop data */ + if (G_LIKELY (!view->drop_data_ready)) + { + /* extract the URI list from the selection data (if valid) */ + if (info == TEXT_URI_LIST && selection_data->format == 8 && selection_data->length > 0) + view->drop_path_list = thunar_vfs_path_list_from_string ((const gchar *) selection_data->data, NULL); + + /* reset the state */ + view->drop_data_ready = TRUE; + } + + /* check if the data was droppped */ + if (G_UNLIKELY (view->drop_occurred)) + { + /* reset the state */ + view->drop_occurred = FALSE; + + /* verify that we only handle text/uri-list here */ + if (G_LIKELY (info == TEXT_URI_LIST)) + { + /* determine the drop actions */ + actions = thunar_shortcuts_view_compute_drop_actions (view, context, x, y, &path, &action, &position); + if (G_LIKELY (actions != 0)) + { + /* check if we should add a shortcut */ + if (position == GTK_TREE_VIEW_DROP_BEFORE || position == GTK_TREE_VIEW_DROP_AFTER) + { + /* if position is "after", we need to advance the path, + * as the drop_uri_list() will insert "at" the path. + */ + if (position == GTK_TREE_VIEW_DROP_AFTER) + gtk_tree_path_next (path); + + /* just add the required shortcuts then */ + thunar_shortcuts_view_drop_uri_list (view, view->drop_path_list, path); + } + else if (G_LIKELY ((actions & (GDK_ACTION_COPY | GDK_ACTION_MOVE | GDK_ACTION_LINK)) != 0)) + { + /* ask the user what to do with the drop data */ + if (G_UNLIKELY (action == GDK_ACTION_ASK)) + action = thunar_dnd_ask (widget, time, actions); + + /* perform the requested action */ + if (G_LIKELY (action != 0)) + { + /* get the shortcuts model */ + model = gtk_tree_view_get_model (GTK_TREE_VIEW (view)); + + /* determine the iterator for the path */ + if (gtk_tree_model_get_iter (model, &iter, path)) + { + /* determine the file for the iter */ + gtk_tree_model_get (model, &iter, THUNAR_SHORTCUTS_MODEL_COLUMN_FILE, &file, -1); + if (G_LIKELY (file != NULL)) + { + /* really perform the drop :-) */ + succeed = thunar_dnd_perform (widget, file, view->drop_path_list, action, NULL); + + /* release the file */ + g_object_unref (G_OBJECT (file)); + } + } + } + } + + /* release the tree path */ + gtk_tree_path_free (path); + } + } + + /* disable the drop highlighting */ + thunar_shortcuts_view_drag_leave (widget, context, time); + + /* tell the peer that we handled the drop */ + gtk_drag_finish (context, succeed, FALSE, time); + } + else + { + gdk_drag_status (context, 0, time); + } +} + + + +static gboolean +thunar_shortcuts_view_drag_drop (GtkWidget *widget, + GdkDragContext *context, + gint x, + gint y, + guint time) +{ + ThunarShortcutsView *view = THUNAR_SHORTCUTS_VIEW (widget); + GtkTreeSelection *selection; + GtkTreeModel *model; + GtkTreePath *dst_path; + GtkTreePath *src_path; + GtkTreeIter iter; + GdkAtom target; + + g_return_val_if_fail (THUNAR_IS_SHORTCUTS_VIEW (view), FALSE); - if (selection_data->target == gdk_atom_intern ("text/uri-list", FALSE)) + /* determine the drop target */ + target = gtk_drag_dest_find_target (widget, context, NULL); + if (G_LIKELY (target == gdk_atom_intern ("text/uri-list", FALSE))) { - thunar_shortcuts_view_drop_uri_list (view, (gchar *) selection_data->data, dst_path); + /* set state so the drag-data-received handler + * knows that this is really a drop this time. + */ + view->drop_occurred = TRUE; + + /* request the drag data from the source. */ + gtk_drag_get_data (widget, context, target, time); } - else if (selection_data->target == gdk_atom_intern ("GTK_TREE_MODEL_ROW", FALSE)) + else if (target == gdk_atom_intern ("GTK_TREE_MODEL_ROW", FALSE)) { + /* compute the drop position */ + dst_path = thunar_shortcuts_view_compute_drop_position (view, x, y); + + /* determine the source path */ selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (view)); if (gtk_tree_selection_get_selected (selection, &model, &iter)) { @@ -601,21 +734,19 @@ thunar_shortcuts_view_drag_data_received (GtkWidget *widget, thunar_shortcuts_model_move (THUNAR_SHORTCUTS_MODEL (model), src_path, dst_path); gtk_tree_path_free (src_path); } - } - - gtk_tree_path_free (dst_path); -} + /* release the dst path */ + gtk_tree_path_free (dst_path); + /* finish the dnd operation */ + gtk_drag_finish (context, TRUE, FALSE, time); + } + else + { + /* we cannot handle the drop */ + return FALSE; + } -static gboolean -thunar_shortcuts_view_drag_drop (GtkWidget *widget, - GdkDragContext *context, - gint x, - gint y, - guint time) -{ - g_return_val_if_fail (THUNAR_IS_SHORTCUTS_VIEW (widget), FALSE); return TRUE; } @@ -630,45 +761,106 @@ thunar_shortcuts_view_drag_motion (GtkWidget *widget, { GtkTreeViewDropPosition position = GTK_TREE_VIEW_DROP_BEFORE; ThunarShortcutsView *view = THUNAR_SHORTCUTS_VIEW (widget); - GdkDragAction action; + GdkDragAction action = 0; GtkTreeModel *model; - GtkTreePath *path; + GtkTreePath *path = NULL; + GdkAtom target; - /* check the action that should be performed */ - if (context->suggested_action == GDK_ACTION_LINK || (context->actions & GDK_ACTION_LINK) != 0) - action = GDK_ACTION_LINK; - else if (context->suggested_action == GDK_ACTION_COPY || (context->actions & GDK_ACTION_COPY) != 0) - action = GDK_ACTION_COPY; - else if (context->suggested_action == GDK_ACTION_MOVE || (context->actions & GDK_ACTION_MOVE) != 0) - action = GDK_ACTION_MOVE; - else - return FALSE; + /* reset the "drop-file" of the icon renderer */ + g_object_set (G_OBJECT (view->icon_renderer), "drop-file", NULL, NULL); - /* compute the drop position for the coordinates */ - path = thunar_shortcuts_view_compute_drop_position (view, x, y); + /* determine the drag target */ + target = gtk_drag_dest_find_target (widget, context, NULL); + if (target == gdk_atom_intern ("text/uri-list", FALSE)) + { + /* request the drop data on-demand (if we don't have it already) */ + if (G_UNLIKELY (!view->drop_data_ready)) + { + /* request the drag data from the source */ + gtk_drag_get_data (widget, context, target, time); - /* check if path is about to append to the model */ - model = gtk_tree_view_get_model (GTK_TREE_VIEW (view)); - if (gtk_tree_path_get_indices (path)[0] >= gtk_tree_model_iter_n_children (model, NULL)) + /* gdk_drag_status() will be called by drag_data_received */ + return TRUE; + } + else + { + /* compute the drop position */ + thunar_shortcuts_view_compute_drop_actions (view, context, x, y, &path, &action, &position); + } + } + else if (target == gdk_atom_intern ("GTK_TREE_MODEL_ROW", FALSE)) { - /* set the position to "after" and move the path to - * point to the previous row instead; required to - * get the highlighting in GtkTreeView correct. - */ - position = GTK_TREE_VIEW_DROP_AFTER; - gtk_tree_path_prev (path); + /* check the action that should be performed */ + if (context->suggested_action == GDK_ACTION_LINK || (context->actions & GDK_ACTION_LINK) != 0) + action = GDK_ACTION_LINK; + else if (context->suggested_action == GDK_ACTION_COPY || (context->actions & GDK_ACTION_COPY) != 0) + action = GDK_ACTION_COPY; + else if (context->suggested_action == GDK_ACTION_MOVE || (context->actions & GDK_ACTION_MOVE) != 0) + action = GDK_ACTION_MOVE; + else + return FALSE; + + /* compute the drop position for the coordinates */ + path = thunar_shortcuts_view_compute_drop_position (view, x, y); + + /* check if path is about to append to the model */ + model = gtk_tree_view_get_model (GTK_TREE_VIEW (view)); + if (gtk_tree_path_get_indices (path)[0] >= gtk_tree_model_iter_n_children (model, NULL)) + { + /* set the position to "after" and move the path to + * point to the previous row instead; required to + * get the highlighting in GtkTreeView correct. + */ + position = GTK_TREE_VIEW_DROP_AFTER; + gtk_tree_path_prev (path); + } + } + else + { + /* we cannot handle the drop */ + return FALSE; } - /* highlight the appropriate row */ - gtk_tree_view_set_drag_dest_row (GTK_TREE_VIEW (view), path, position); - gtk_tree_path_free (path); + /* check if we have a drop path */ + if (G_LIKELY (path != NULL)) + { + /* highlight the appropriate row */ + gtk_tree_view_set_drag_dest_row (GTK_TREE_VIEW (view), path, position); + gtk_tree_path_free (path); + } + /* tell Gdk whether we can drop here */ gdk_drag_status (context, action, time); + return TRUE; } +static void +thunar_shortcuts_view_drag_leave (GtkWidget *widget, + GdkDragContext *context, + guint time) +{ + ThunarShortcutsView *view = THUNAR_SHORTCUTS_VIEW (widget); + + /* reset the "drop-file" of the icon renderer */ + g_object_set (G_OBJECT (view->icon_renderer), "drop-file", NULL, NULL); + + /* reset the "drop data ready" status and free the URI list */ + if (G_LIKELY (view->drop_data_ready)) + { + thunar_vfs_path_list_free (view->drop_path_list); + view->drop_data_ready = FALSE; + view->drop_path_list = NULL; + } + + /* call the parent's handler */ + return (*GTK_WIDGET_CLASS (thunar_shortcuts_view_parent_class)->drag_leave) (widget, context, time); +} + + + static void thunar_shortcuts_view_remove_activated (GtkWidget *item, ThunarShortcutsView *view) @@ -742,6 +934,104 @@ thunar_shortcuts_view_renamed (GtkCellRenderer *renderer, +static GdkDragAction +thunar_shortcuts_view_compute_drop_actions (ThunarShortcutsView *view, + GdkDragContext *context, + gint x, + gint y, + GtkTreePath **path_return, + GdkDragAction *action_return, + GtkTreeViewDropPosition *position_return) +{ + GtkTreeViewColumn *column; + GdkDragAction actions = 0; + GdkRectangle cell_area; + GtkTreeModel *model; + GtkTreePath *path; + GtkTreeIter iter; + ThunarFile *file; + gint cell_y; + + /* determine the shortcuts model */ + model = gtk_tree_view_get_model (GTK_TREE_VIEW (view)); + + /* determine the path for x/y */ + if (gtk_tree_view_get_path_at_pos (GTK_TREE_VIEW (view), x, y, &path, &column, NULL, &cell_y)) + { + /* determine the background area of the column */ + gtk_tree_view_get_background_area (GTK_TREE_VIEW (view), path, column, &cell_area); + + /* check if 1/6th inside the cell and the path is within the model */ + if ((cell_y > (cell_area.height / 6) && cell_y < (cell_area.height - cell_area.height / 6)) + && gtk_tree_model_get_iter (model, &iter, path)) + { + /* determine the file for the iterator */ + gtk_tree_model_get (model, &iter, THUNAR_SHORTCUTS_MODEL_COLUMN_FILE, &file, -1); + if (G_LIKELY (file != NULL)) + { + /* check if the file accepts the drop */ + actions = thunar_file_accepts_drop (file, view->drop_path_list, context, action_return); + if (G_LIKELY (actions != 0)) + { + /* we can drop into this location */ + *position_return = GTK_TREE_VIEW_DROP_INTO_OR_AFTER; + *path_return = gtk_tree_path_copy (path); + + /* display a drop icon for the file */ + g_object_set (G_OBJECT (view->icon_renderer), "drop-file", file, NULL); + } + + /* release the file */ + g_object_unref (G_OBJECT (file)); + } + } + + /* release the path */ + gtk_tree_path_free (path); + } + + /* check if we cannot drop into the shortcut */ + if (G_UNLIKELY (actions == 0)) + { + /* check the action that should be performed */ + if (context->suggested_action == GDK_ACTION_LINK || (context->actions & GDK_ACTION_LINK) != 0) + actions = GDK_ACTION_LINK; + else if (context->suggested_action == GDK_ACTION_COPY || (context->actions & GDK_ACTION_COPY) != 0) + actions = GDK_ACTION_COPY; + else if (context->suggested_action == GDK_ACTION_MOVE || (context->actions & GDK_ACTION_MOVE) != 0) + actions = GDK_ACTION_MOVE; + else + return 0; + + /* but maybe we can add as shortcut */ + path = thunar_shortcuts_view_compute_drop_position (view, x, y); + + /* check if path is about to append to the model */ + if (gtk_tree_path_get_indices (path)[0] >= gtk_tree_model_iter_n_children (model, NULL)) + { + /* set the position to "after" and move the path to + * point to the previous row instead; required to + * get the highlighting in GtkTreeView correct. + */ + *position_return = GTK_TREE_VIEW_DROP_AFTER; + gtk_tree_path_prev (path); + } + else + { + /* drop before the path */ + *position_return = GTK_TREE_VIEW_DROP_BEFORE; + } + + /* got it */ + *action_return = actions; + *path_return = path; + } + + return actions; +} + + + static GtkTreePath* thunar_shortcuts_view_compute_drop_position (ThunarShortcutsView *view, gint x, @@ -788,50 +1078,50 @@ thunar_shortcuts_view_compute_drop_position (ThunarShortcutsView *view, static void thunar_shortcuts_view_drop_uri_list (ThunarShortcutsView *view, - const gchar *uri_list, + GList *path_list, GtkTreePath *dst_path) { GtkTreeModel *model; + GtkTreePath *path; ThunarFile *file; GError *error = NULL; gchar *display_string; gchar *uri_string; - GList *path_list; GList *lp; - path_list = thunar_vfs_path_list_from_string (uri_list, &error); - if (G_LIKELY (error == NULL)) - { - /* process the URIs one-by-one and stop on error */ - model = gtk_tree_view_get_model (GTK_TREE_VIEW (view)); - for (lp = path_list; lp != NULL; lp = lp->next) - { - file = thunar_file_get_for_path (lp->data, &error); - if (G_UNLIKELY (file == NULL)) - break; + /* take a copy of the destination path */ + path = gtk_tree_path_copy (dst_path); - /* make sure, that only directories gets added to the shortcuts list */ - if (G_UNLIKELY (!thunar_file_is_directory (file))) - { - uri_string = thunar_vfs_path_dup_string (lp->data); - display_string = g_filename_display_name (uri_string); - g_set_error (&error, G_FILE_ERROR, G_FILE_ERROR_NOTDIR, - _("The path \"%s\" does not refer to a directory"), - display_string); - g_object_unref (G_OBJECT (file)); - g_free (display_string); - g_free (uri_string); - break; - } + /* process the URIs one-by-one and stop on error */ + model = gtk_tree_view_get_model (GTK_TREE_VIEW (view)); + for (lp = path_list; lp != NULL; lp = lp->next) + { + file = thunar_file_get_for_path (lp->data, &error); + if (G_UNLIKELY (file == NULL)) + break; - thunar_shortcuts_model_add (THUNAR_SHORTCUTS_MODEL (model), dst_path, file); + /* make sure, that only directories gets added to the shortcuts list */ + if (G_UNLIKELY (!thunar_file_is_directory (file))) + { + uri_string = thunar_vfs_path_dup_string (lp->data); + display_string = g_filename_display_name (uri_string); + g_set_error (&error, G_FILE_ERROR, G_FILE_ERROR_NOTDIR, + _("The path \"%s\" does not refer to a directory"), + display_string); g_object_unref (G_OBJECT (file)); - gtk_tree_path_next (dst_path); + g_free (display_string); + g_free (uri_string); + break; } - thunar_vfs_path_list_free (path_list); + thunar_shortcuts_model_add (THUNAR_SHORTCUTS_MODEL (model), path, file); + g_object_unref (G_OBJECT (file)); + gtk_tree_path_next (path); } + /* release the tree path copy */ + gtk_tree_path_free (path); + if (G_UNLIKELY (error != NULL)) { /* display an error message to the user */ -- GitLab