[gthumb: 5/9] added drag&drop support to the folder tree



commit e485f71b82859a6ea8d63eb6b5d9a510aeb34838
Author: Paolo Bacchilega <paobac src gnome org>
Date:   Sun Apr 25 21:03:00 2010 +0200

    added drag&drop support to the folder tree
    
    [bug #593431]

 extensions/file_manager/callbacks.c |   45 +++++++++++++++
 extensions/file_manager/callbacks.h |   31 ++++++-----
 extensions/file_manager/main.c      |    1 +
 gthumb/gth-browser.c                |  107 +++++++++++++++++++++++++++++++++++
 gthumb/gth-file-list.c              |    6 +-
 gthumb/gth-folder-tree.c            |   28 +++++++++
 gthumb/gth-folder-tree.h            |    2 +
 gthumb/gth-hook.c                   |   31 ++++++++++-
 gthumb/gth-main-default-hooks.c     |   11 ++++
 9 files changed, 244 insertions(+), 18 deletions(-)
---
diff --git a/extensions/file_manager/callbacks.c b/extensions/file_manager/callbacks.c
index 51ce37d..a895f5d 100644
--- a/extensions/file_manager/callbacks.c
+++ b/extensions/file_manager/callbacks.c
@@ -673,6 +673,51 @@ fm__gth_browser_folder_tree_popup_before_cb (GthBrowser    *browser,
 }
 
 
+void
+fm__gth_browser_folder_tree_drag_data_received_cb (GthBrowser    *browser,
+						   GthFileData   *destination,
+						   GList         *file_list,
+						   GdkDragAction  action)
+{
+	GthFileSource *file_source;
+	GthTask       *task;
+
+	file_source = gth_main_get_file_source (destination->file);
+	if (file_source == NULL)
+		return;
+
+	if ((action == GDK_ACTION_MOVE) && ! gth_file_source_can_cut (file_source)) {
+		GtkWidget *dialog;
+		int        response;
+
+		dialog = _gtk_message_dialog_new (GTK_WINDOW (browser),
+						  GTK_DIALOG_MODAL,
+						  GTK_STOCK_DIALOG_QUESTION,
+						  _("Could not move the files"),
+						  _("Files cannot be moved to the current location, as alternative you can choose to copy them."),
+						  GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
+						  GTK_STOCK_COPY, GTK_RESPONSE_OK,
+						  NULL);
+		response = gtk_dialog_run (GTK_DIALOG (dialog));
+		gtk_widget_destroy (dialog);
+
+		if (response == GTK_RESPONSE_CANCEL)
+			return;
+
+		action = GDK_ACTION_COPY;
+	}
+
+	task = gth_copy_task_new (file_source,
+				  destination,
+				  (action == GDK_ACTION_MOVE),
+				  file_list);
+	gth_browser_exec_task (browser, task, FALSE);
+
+	g_object_unref (task);
+	g_object_unref (file_source);
+}
+
+
 static void
 clipboard_targets_received_cb (GtkClipboard *clipboard,
 			       GdkAtom      *atoms,
diff --git a/extensions/file_manager/callbacks.h b/extensions/file_manager/callbacks.h
index d891600..fbe71f0 100644
--- a/extensions/file_manager/callbacks.h
+++ b/extensions/file_manager/callbacks.h
@@ -25,19 +25,22 @@
 
 #include <gthumb.h>
 
-void      fm__gth_browser_construct_cb                (GthBrowser    *browser);
-void      fm__gth_browser_update_sensitivity_cb       (GthBrowser    *browser);
-void      fm__gth_browser_set_current_page_cb         (GthBrowser    *browser);
-void      fm__gth_browser_load_location_after_cb      (GthBrowser    *browser,
-						       GFile         *location,
-						       GError        *error);
-void      fm__gth_browser_folder_tree_popup_before_cb (GthBrowser    *browser,
-						       GthFileSource *file_source,
-						       GFile         *folder);
-void      fm__gth_browser_selection_changed_cb        (GthBrowser    *browser);
-void      fm__gth_browser_realize_cb                  (GthBrowser    *browser);
-void      fm__gth_browser_unrealize_cb                (GthBrowser    *browser);
-gpointer  fm__gth_browser_file_list_key_press_cb      (GthBrowser    *browser,
-						       GdkEventKey   *event);
+void      fm__gth_browser_construct_cb                      (GthBrowser    *browser);
+void      fm__gth_browser_update_sensitivity_cb             (GthBrowser    *browser);
+void      fm__gth_browser_set_current_page_cb               (GthBrowser    *browser);
+void      fm__gth_browser_load_location_after_cb            (GthBrowser    *browser,
+						             GFile         *location,
+						             GError        *error);
+void      fm__gth_browser_folder_tree_popup_before_cb       (GthBrowser    *browser,
+							     GthFileSource *file_source,
+							     GFile         *folder);
+void      fm__gth_browser_folder_tree_drag_data_received_cb (GthBrowser    *browser,
+							     GList         *file_list,
+							     GdkDragAction  action);
+void      fm__gth_browser_selection_changed_cb              (GthBrowser    *browser);
+void      fm__gth_browser_realize_cb                        (GthBrowser    *browser);
+void      fm__gth_browser_unrealize_cb                      (GthBrowser    *browser);
+gpointer  fm__gth_browser_file_list_key_press_cb            (GthBrowser    *browser,
+						             GdkEventKey   *event);
 
 #endif /* CALLBACKS_H */
diff --git a/extensions/file_manager/main.c b/extensions/file_manager/main.c
index a2a6d2d..0f78a5d 100644
--- a/extensions/file_manager/main.c
+++ b/extensions/file_manager/main.c
@@ -34,6 +34,7 @@ gthumb_extension_activate (void)
 	gth_hook_add_callback ("gth-browser-load-location-after", 10, G_CALLBACK (fm__gth_browser_load_location_after_cb), NULL);
 	gth_hook_add_callback ("gth-browser-set-current-page", 10, G_CALLBACK (fm__gth_browser_set_current_page_cb), NULL);
 	gth_hook_add_callback ("gth-browser-folder-tree-popup-before", 10, G_CALLBACK (fm__gth_browser_folder_tree_popup_before_cb), NULL);
+	gth_hook_add_callback ("gth-browser-folder-tree-drag-data-received", 10, G_CALLBACK (fm__gth_browser_folder_tree_drag_data_received_cb), NULL);
 	gth_hook_add_callback ("gth-browser-update-sensitivity", 10, G_CALLBACK (fm__gth_browser_update_sensitivity_cb), NULL);
 	gth_hook_add_callback ("gth-browser-realize", 10, G_CALLBACK (fm__gth_browser_realize_cb), NULL);
 	gth_hook_add_callback ("gth-browser-unrealize", 10, G_CALLBACK (fm__gth_browser_unrealize_cb), NULL);
diff --git a/gthumb/gth-browser.c b/gthumb/gth-browser.c
index 5d675b7..5cb0a2c 100644
--- a/gthumb/gth-browser.c
+++ b/gthumb/gth-browser.c
@@ -2270,6 +2270,80 @@ connect_proxy_cb (GtkUIManager *manager,
 
 
 static void
+folder_tree_drag_data_received (GtkWidget        *tree_view,
+				GdkDragContext   *context,
+				int               x,
+				int               y,
+				GtkSelectionData *selection_data,
+				guint             info,
+				guint             time,
+				gpointer          user_data)
+{
+	GthBrowser   *browser = user_data;
+	gboolean      success = FALSE;
+	GtkTreePath  *path;
+	GthFileData  *destination;
+	char        **uris;
+	GList        *file_list;
+
+	if ((context->suggested_action == GDK_ACTION_COPY)
+	    || (context->suggested_action == GDK_ACTION_MOVE))
+	{
+		success = TRUE;
+	}
+
+	if (! gtk_tree_view_get_dest_row_at_pos (GTK_TREE_VIEW (browser->priv->folder_tree),
+						 x, y,
+						 &path,
+						 NULL))
+	{
+		success = FALSE;
+	}
+
+	gtk_drag_finish (context, success, FALSE, time);
+
+	if (! success)
+		return;
+
+	destination = gth_folder_tree_get_file (GTH_FOLDER_TREE (browser->priv->folder_tree), path);
+	uris = gtk_selection_data_get_uris (selection_data);
+	file_list = _g_file_list_new_from_uriv (uris);
+	if (file_list != NULL)
+		gth_hook_invoke ("gth-browser-folder-tree-drag-data-received", browser, destination, file_list, context->suggested_action);
+
+	_g_object_list_unref (file_list);
+	g_strfreev (uris);
+	g_object_unref (destination);
+}
+
+
+static void
+folder_tree_drag_data_get_cb (GtkWidget        *widget,
+			      GdkDragContext   *drag_context,
+			      GtkSelectionData *data,
+			      guint             info,
+			      guint             time,
+			      gpointer          user_data)
+{
+	GthBrowser   *browser = user_data;
+	GthFileData  *file_data;
+	char        **uris;
+
+	file_data = gth_folder_tree_get_selected (GTH_FOLDER_TREE (browser->priv->folder_tree));
+	if (file_data == NULL)
+		return;
+
+	uris = g_new (char *, 2);
+	uris[0] = g_file_get_uri (file_data->file);
+	uris[1] = NULL;
+	gtk_selection_data_set_uris (data, uris);
+
+	g_strfreev (uris);
+	g_object_unref (file_data);
+}
+
+
+static void
 folder_tree_open_cb (GthFolderTree *folder_tree,
 		     GFile         *file,
 		     GthBrowser    *browser)
@@ -3637,6 +3711,39 @@ _gth_browser_construct (GthBrowser *browser)
 	gtk_container_add (GTK_CONTAINER (scrolled_window), browser->priv->folder_tree);
 	gtk_box_pack_start (GTK_BOX (vbox), scrolled_window, TRUE, TRUE, 0);
 
+	{
+		GtkTargetList  *target_list;
+		GtkTargetEntry *targets;
+		int             n_targets;
+
+		target_list = gtk_target_list_new (NULL, 0);
+		gtk_target_list_add_uri_targets (target_list, 0);
+		gtk_target_list_add_text_targets (target_list, 0);
+		targets = gtk_target_table_new_from_list (target_list, &n_targets);
+
+		gtk_tree_view_enable_model_drag_dest (GTK_TREE_VIEW (browser->priv->folder_tree),
+						      targets,
+						      n_targets,
+						      GDK_ACTION_MOVE | GDK_ACTION_COPY);
+		gtk_tree_view_enable_model_drag_source (GTK_TREE_VIEW (browser->priv->folder_tree),
+							GDK_BUTTON1_MASK,
+							targets,
+							n_targets,
+							GDK_ACTION_MOVE | GDK_ACTION_COPY);
+
+		g_signal_connect (browser->priv->folder_tree,
+	                          "drag-data-received",
+	                          G_CALLBACK (folder_tree_drag_data_received),
+	                          browser);
+		g_signal_connect (browser->priv->folder_tree,
+				  "drag-data-get",
+				  G_CALLBACK (folder_tree_drag_data_get_cb),
+				  browser);
+
+		gtk_target_list_unref (target_list);
+		gtk_target_table_free (targets, n_targets);
+	}
+
 	g_signal_connect (browser->priv->folder_tree,
 			  "open",
 			  G_CALLBACK (folder_tree_open_cb),
diff --git a/gthumb/gth-file-list.c b/gthumb/gth-file-list.c
index 420f0a7..e828e62 100644
--- a/gthumb/gth-file-list.c
+++ b/gthumb/gth-file-list.c
@@ -581,9 +581,9 @@ gth_file_list_construct (GthFileList     *file_list,
 		gth_file_selection_set_selection_mode (GTH_FILE_SELECTION (file_list->priv->view), GTK_SELECTION_MULTIPLE);
 
 	if (enable_drag_drop) {
-		GtkTargetList   *target_list;
-		GtkTargetEntry  *targets;
-		int              n_targets;
+		GtkTargetList  *target_list;
+		GtkTargetEntry *targets;
+		int             n_targets;
 
 		target_list = gtk_target_list_new (NULL, 0);
 		gtk_target_list_add_uri_targets (target_list, 0);
diff --git a/gthumb/gth-folder-tree.c b/gthumb/gth-folder-tree.c
index 637ffe5..3135af4 100644
--- a/gthumb/gth-folder-tree.c
+++ b/gthumb/gth-folder-tree.c
@@ -1400,6 +1400,34 @@ gth_folder_tree_expand_row (GthFolderTree *folder_tree,
 }
 
 
+GthFileData *
+gth_folder_tree_get_file (GthFolderTree *folder_tree,
+			  GtkTreePath   *path)
+{
+	GtkTreeModel *tree_model;
+	GtkTreeIter   iter;
+	EntryType     entry_type;
+	GthFileData  *file_data;
+
+	tree_model = GTK_TREE_MODEL (folder_tree->priv->tree_store);
+	if (! gtk_tree_model_get_iter (tree_model, &iter, path))
+			return NULL;
+
+	file_data = NULL;
+	gtk_tree_model_get (tree_model,
+			    &iter,
+			    COLUMN_TYPE, &entry_type,
+			    COLUMN_FILE_DATA, &file_data,
+			    -1);
+	if (entry_type != ENTRY_TYPE_FILE) {
+		_g_object_unref (file_data);
+		file_data = NULL;
+	}
+
+	return file_data;
+}
+
+
 void
 gth_folder_tree_select_path (GthFolderTree *folder_tree,
 			     GtkTreePath   *path)
diff --git a/gthumb/gth-folder-tree.h b/gthumb/gth-folder-tree.h
index 346dc05..6263725 100644
--- a/gthumb/gth-folder-tree.h
+++ b/gthumb/gth-folder-tree.h
@@ -101,6 +101,8 @@ void          gth_folder_tree_expand_row       (GthFolderTree   *folder_tree,
 void          gth_folder_tree_select_path      (GthFolderTree   *folder_tree,
 						GtkTreePath     *path);
 GFile *       gth_folder_tree_get_root         (GthFolderTree   *folder_tree);
+GthFileData * gth_folder_tree_get_file         (GthFolderTree   *folder_tree,
+						GtkTreePath     *path);
 GthFileData * gth_folder_tree_get_selected     (GthFolderTree   *folder_tree);
 GthFileData * gth_folder_tree_get_selected_or_parent
 					       (GthFolderTree   *folder_tree);
diff --git a/gthumb/gth-hook.c b/gthumb/gth-hook.c
index afd2f54..dd859f2 100644
--- a/gthumb/gth-hook.c
+++ b/gthumb/gth-hook.c
@@ -85,7 +85,7 @@ gth_hook_register (const char *name,
 	GthHook *hook;
 
 	g_return_if_fail (name != NULL);
-	g_return_if_fail ((n_args >= 0) || (n_args <= 3));
+	g_return_if_fail ((n_args >= 0) || (n_args <= 4));
 
 	if (g_hash_table_lookup (hooks, name) != NULL) {
 		g_warning ("hook '%s' already registered", name);
@@ -168,6 +168,7 @@ typedef void (*GthMarshaller0Args) (gpointer);
 typedef void (*GthMarshaller1Arg)  (gpointer, gpointer);
 typedef void (*GthMarshaller2Args) (gpointer, gpointer, gpointer);
 typedef void (*GthMarshaller3Args) (gpointer, gpointer, gpointer, gpointer);
+typedef void (*GthMarshaller4Args) (gpointer, gpointer, gpointer, gpointer, gpointer);
 
 
 static void
@@ -208,6 +209,16 @@ invoke_marshaller_3 (GHook    *hook,
 }
 
 
+static void
+invoke_marshaller_4 (GHook    *hook,
+                     gpointer  data)
+{
+	gpointer *marshal_data = data;
+
+	((GthMarshaller4Args) hook->func) (marshal_data[0], marshal_data[1], marshal_data[2], marshal_data[3], hook->data);
+}
+
+
 void
 gth_hook_invoke (const char *name,
 		 gpointer    first_data,
@@ -243,6 +254,9 @@ gth_hook_invoke (const char *name,
 	case 3:
 		invoke_marshaller = invoke_marshaller_3;
 		break;
+	case 4:
+		invoke_marshaller = invoke_marshaller_4;
+		break;
 	default:
 		invoke_marshaller = NULL;
 		break;
@@ -259,6 +273,7 @@ typedef void * (*GthMarshaller0ArgsGet) (gpointer);
 typedef void * (*GthMarshaller1ArgGet)  (gpointer, gpointer);
 typedef void * (*GthMarshaller2ArgsGet) (gpointer, gpointer, gpointer);
 typedef void * (*GthMarshaller3ArgsGet) (gpointer, gpointer, gpointer, gpointer);
+typedef void * (*GthMarshaller4ArgsGet) (gpointer, gpointer, gpointer, gpointer, gpointer);
 
 
 static void
@@ -305,6 +320,17 @@ invoke_marshaller_3_get (GHook    *hook,
 }
 
 
+static void
+invoke_marshaller_4_get (GHook    *hook,
+                         gpointer  data)
+{
+	gpointer *marshal_data = data;
+
+	if (marshal_data[4] == NULL)
+		marshal_data[4] = ((GthMarshaller4ArgsGet) hook->func) (marshal_data[0], marshal_data[1], marshal_data[2], marshal_data[3], hook->data);
+}
+
+
 void *
 gth_hook_invoke_get (const char *name,
 		     gpointer    first_data,
@@ -340,6 +366,9 @@ gth_hook_invoke_get (const char *name,
 	case 3:
 		invoke_marshaller = invoke_marshaller_3_get;
 		break;
+	case 4:
+		invoke_marshaller = invoke_marshaller_4_get;
+		break;
 	default:
 		invoke_marshaller = NULL;
 		break;
diff --git a/gthumb/gth-main-default-hooks.c b/gthumb/gth-main-default-hooks.c
index 2456236..9905703 100644
--- a/gthumb/gth-main-default-hooks.c
+++ b/gthumb/gth-main-default-hooks.c
@@ -140,6 +140,17 @@ gth_main_register_default_hooks (void)
 	gth_hook_register ("gth-browser-folder-tree-popup-before", 3);
 
 	/**
+	 * Called after a drag-data-received event on the folder tree
+	 *
+	 * @browser (GthBrowser *): the relative window.
+	 * @destination (GthFileData *): the drop destination.
+	 * @file_list (GList *): the GFile list of the dropped files
+	 * @action (GdkDragAction): the drag action
+	 * pressed in an empty area.
+	 **/
+	gth_hook_register ("gth-browser-folder-tree-drag-data-received", 4);
+
+	/**
 	 * Called to view file
 	 *
 	 * @browser (GthBrowser*): the relative window.



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