From 1df38871e11625b11d7dbd22fae4b1328946b76a Mon Sep 17 00:00:00 2001 From: Matthias Clasen Date: Thu, 7 Jul 2005 17:11:26 +0000 Subject: [PATCH] Implement Drag-and-Drop to the file list. (#145121, Sven Neumann) 2005-07-07 Matthias Clasen Implement Drag-and-Drop to the file list. (#145121, Sven Neumann) * gtk/gtkfilechooserdefault.c (file_list_drag_data_received_cb) (file_list_drag_drop_cb, file_list_drag_motion_cb): New functions to handle drag-and-drop on the file list. (create_file_list): Set up drag-and-drop handlers on the file list. --- ChangeLog | 9 +++ ChangeLog.pre-2-10 | 9 +++ ChangeLog.pre-2-8 | 9 +++ gtk/gtkfilechooserdefault.c | 145 ++++++++++++++++++++++++++++++++++++ 4 files changed, 172 insertions(+) diff --git a/ChangeLog b/ChangeLog index 42646f5c9d..ea0ef9218e 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,12 @@ +2005-07-07 Matthias Clasen + + Implement Drag-and-Drop to the file list. (#145121, Sven Neumann) + + * gtk/gtkfilechooserdefault.c (file_list_drag_data_received_cb) + (file_list_drag_drop_cb, file_list_drag_motion_cb): New functions + to handle drag-and-drop on the file list. + (create_file_list): Set up drag-and-drop handlers on the file list. + 2005-07-07 Matthias Clasen Fix #157787, reported by Jonathan Blandford: diff --git a/ChangeLog.pre-2-10 b/ChangeLog.pre-2-10 index 42646f5c9d..ea0ef9218e 100644 --- a/ChangeLog.pre-2-10 +++ b/ChangeLog.pre-2-10 @@ -1,3 +1,12 @@ +2005-07-07 Matthias Clasen + + Implement Drag-and-Drop to the file list. (#145121, Sven Neumann) + + * gtk/gtkfilechooserdefault.c (file_list_drag_data_received_cb) + (file_list_drag_drop_cb, file_list_drag_motion_cb): New functions + to handle drag-and-drop on the file list. + (create_file_list): Set up drag-and-drop handlers on the file list. + 2005-07-07 Matthias Clasen Fix #157787, reported by Jonathan Blandford: diff --git a/ChangeLog.pre-2-8 b/ChangeLog.pre-2-8 index 42646f5c9d..ea0ef9218e 100644 --- a/ChangeLog.pre-2-8 +++ b/ChangeLog.pre-2-8 @@ -1,3 +1,12 @@ +2005-07-07 Matthias Clasen + + Implement Drag-and-Drop to the file list. (#145121, Sven Neumann) + + * gtk/gtkfilechooserdefault.c (file_list_drag_data_received_cb) + (file_list_drag_drop_cb, file_list_drag_motion_cb): New functions + to handle drag-and-drop on the file list. + (create_file_list): Set up drag-and-drop handlers on the file list. + 2005-07-07 Matthias Clasen Fix #157787, reported by Jonathan Blandford: diff --git a/gtk/gtkfilechooserdefault.c b/gtk/gtkfilechooserdefault.c index ae0c458356..6dee5b6488 100644 --- a/gtk/gtkfilechooserdefault.c +++ b/gtk/gtkfilechooserdefault.c @@ -264,6 +264,15 @@ static const GtkTargetEntry file_list_source_targets[] = { static const int num_file_list_source_targets = (sizeof (file_list_source_targets) / sizeof (file_list_source_targets[0])); +/* Target types for dropping into the file list */ +static const GtkTargetEntry file_list_dest_targets[] = { + { "text/uri-list", 0, TEXT_URI_LIST } +}; + +static const int num_file_list_dest_targets = (sizeof (file_list_dest_targets) + / sizeof (file_list_dest_targets[0])); + + /* Interesting places in the shortcuts bar */ typedef enum { SHORTCUTS_HOME, @@ -445,6 +454,7 @@ static const GtkFileInfo *get_list_file_info (GtkFileChooserDefault *impl, GtkTreeIter *iter); static void load_remove_timer (GtkFileChooserDefault *impl); +static void browse_files_center_selected_row (GtkFileChooserDefault *impl); static GObjectClass *parent_class; @@ -3292,6 +3302,127 @@ show_hidden_toggled_cb (GtkCheckMenuItem *item, NULL); } +/* Shows an error dialog about not being able to select a dragged file */ +static void +error_selecting_dragged_file_dialog (GtkFileChooserDefault *impl, + const GtkFilePath *path, + GError *error) +{ + error_dialog (impl, + _("Could not select file"), + path, error); +} + +static void +file_list_drag_data_received_cb (GtkWidget *widget, + GdkDragContext *context, + gint x, + gint y, + GtkSelectionData *selection_data, + guint info, + guint time_, + gpointer data) +{ + GtkFileChooserDefault *impl; + GtkFileChooser *chooser; + gchar **uris; + char *uri; + GtkFilePath *path; + GError *error = NULL; + gint i; + + impl = GTK_FILE_CHOOSER_DEFAULT (data); + chooser = GTK_FILE_CHOOSER (data); + + /* Parse the text/uri-list string, navigate to the first one */ + uris = g_uri_list_extract_uris (selection_data->data); + if (uris[0]) + { + uri = uris[0]; + path = gtk_file_system_uri_to_path (impl->file_system, uri); + + if (path) + { + if ((impl->action == GTK_FILE_CHOOSER_ACTION_OPEN || + impl->action == GTK_FILE_CHOOSER_ACTION_SAVE) && + uris[1] == 0 && + check_is_folder (impl->file_system, path, NULL)) + change_folder_and_display_error (impl, path); + else + { + gtk_file_chooser_default_unselect_all (chooser); + gtk_file_chooser_default_select_path (chooser, path, &error); + if (error) + error_selecting_dragged_file_dialog (impl, path, error); + else + browse_files_center_selected_row (impl); + } + + gtk_file_path_free (path); + } + else + { + g_set_error (&error, + GTK_FILE_CHOOSER_ERROR, + GTK_FILE_CHOOSER_ERROR_BAD_FILENAME, + _("Could not select file '%s' " + "because it is an invalid path name."), + uri); + error_selecting_dragged_file_dialog (impl, NULL, error); + } + + + if (impl->select_multiple) + { + for (i = 1; uris[i]; i++) + { + uri = uris[i]; + path = gtk_file_system_uri_to_path (impl->file_system, uri); + + if (path) + { + gtk_file_chooser_default_select_path (chooser, path, &error); + if (error) + error_selecting_dragged_file_dialog (impl, path, error); + + gtk_file_path_free (path); + } + } + } + } + + g_strfreev (uris); + + g_signal_stop_emission_by_name (widget, "drag-data-received"); +} + +/* Don't do anything with the drag_drop signal */ +static gboolean +file_list_drag_drop_cb (GtkWidget *widget, + GdkDragContext *context, + gint x, + gint y, + guint time_, + GtkFileChooserDefault *impl) +{ + g_signal_stop_emission_by_name (widget, "drag-drop"); + return TRUE; +} + +/* Disable the normal tree drag motion handler, it makes it look like you're + dropping the dragged item onto a tree item */ +static gboolean +file_list_drag_motion_cb (GtkWidget *widget, + GdkDragContext *context, + gint x, + gint y, + guint time_, + GtkFileChooserDefault *impl) +{ + g_signal_stop_emission_by_name (widget, "drag-motion"); + return TRUE; +} + /* Constructs the popup menu for the file list if needed */ static void file_list_build_popup_menu (GtkFileChooserDefault *impl) @@ -3456,6 +3587,13 @@ create_file_list (GtkFileChooserDefault *impl) gtk_tree_view_set_rules_hint (GTK_TREE_VIEW (impl->browse_files_tree_view), TRUE); gtk_container_add (GTK_CONTAINER (swin), impl->browse_files_tree_view); + + gtk_drag_dest_set (impl->browse_files_tree_view, + GTK_DEST_DEFAULT_ALL, + file_list_dest_targets, + num_file_list_dest_targets, + GDK_ACTION_COPY | GDK_ACTION_MOVE); + g_signal_connect (impl->browse_files_tree_view, "row-activated", G_CALLBACK (list_row_activated), impl); g_signal_connect (impl->browse_files_tree_view, "key-press-event", @@ -3465,6 +3603,13 @@ create_file_list (GtkFileChooserDefault *impl) g_signal_connect (impl->browse_files_tree_view, "button-press-event", G_CALLBACK (list_button_press_event_cb), impl); + g_signal_connect (impl->browse_files_tree_view, "drag-data-received", + G_CALLBACK (file_list_drag_data_received_cb), impl); + g_signal_connect (impl->browse_files_tree_view, "drag-drop", + G_CALLBACK (file_list_drag_drop_cb), impl); + g_signal_connect (impl->browse_files_tree_view, "drag-motion", + G_CALLBACK (file_list_drag_motion_cb), impl); + selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (impl->browse_files_tree_view)); gtk_tree_selection_set_select_function (selection, list_select_func,