[gthumb] added ability to drag files with the middle mouse button to allow the user to choose the action to p



commit 661aae066d620ded9c6eed97f3594d8d0f49d024
Author: Paolo Bacchilega <paobac src gnome org>
Date:   Sun Jan 23 11:13:11 2011 +0100

    added ability to drag files with the middle mouse button to allow the user to choose the action to perform
    
    [new feature]

 extensions/file_manager/callbacks.c |   18 ++++-
 gthumb/gth-browser.c                |   11 ++-
 gthumb/gth-file-list.c              |    4 +-
 gthumb/gth-icon-view.c              |   20 ++++++-
 gthumb/gtk-utils.c                  |  116 +++++++++++++++++++++++++++++++++++
 gthumb/gtk-utils.h                  |    4 +
 6 files changed, 162 insertions(+), 11 deletions(-)
---
diff --git a/extensions/file_manager/callbacks.c b/extensions/file_manager/callbacks.c
index 23322ac..14bbb0a 100644
--- a/extensions/file_manager/callbacks.c
+++ b/extensions/file_manager/callbacks.c
@@ -272,20 +272,28 @@ gth_file_list_drag_data_received (GtkWidget        *file_view,
 	g_signal_stop_emission_by_name (file_view, "drag-data-received");
 
 	/*
-	if ((gdk_drag_context_get_action (context) == GDK_ACTION_COPY)
-	    || (gdk_drag_context_get_action (context) == GDK_ACTION_MOVE))
+	if ((gdk_drag_context_get_suggested_action (context) == GDK_ACTION_COPY)
+	    || (gdk_drag_context_get_suggested_action (context) == GDK_ACTION_MOVE))
 	{
 		success = TRUE;
 	}
 	*/
 
-	if ((context->action == GDK_ACTION_COPY)
-	    || (context->action == GDK_ACTION_MOVE))
+	if ((context->suggested_action == GDK_ACTION_COPY)
+	    || (context->suggested_action == GDK_ACTION_MOVE)
+	    || (context->suggested_action == GDK_ACTION_ASK))
 	{
 		success = TRUE;
 	}
 
+	if (context->suggested_action == GDK_ACTION_ASK) {
+		context->action = _gtk_menu_ask_drag_drop_action (file_view, context->actions, time);
+		success = context->action != 0;
+	}
+
 	gtk_drag_finish (context, success, FALSE, time);
+	if (! success)
+		return;
 
 	uris = gtk_selection_data_get_uris (selection_data);
 	selected_files = _g_file_list_new_from_uriv (uris);
@@ -449,6 +457,8 @@ gth_file_list_drag_motion (GtkWidget      *file_view,
 			data->scroll_event = 0;
 		}
 	}
+	else if (context->suggested_action == GDK_ACTION_ASK)
+		gdk_drag_status (context, GDK_ACTION_ASK, time);
 	else
 		gdk_drag_status (context, GDK_ACTION_COPY, time);
 
diff --git a/gthumb/gth-browser.c b/gthumb/gth-browser.c
index 1765e92..3478434 100644
--- a/gthumb/gth-browser.c
+++ b/gthumb/gth-browser.c
@@ -2512,10 +2512,10 @@ folder_tree_drag_data_received (GtkWidget        *tree_view,
 		success = FALSE;
 	}
 
-	gtk_drag_finish (context, success, FALSE, time);
-
-	if (! success)
+	if (! success) {
+		gtk_drag_finish (context, FALSE, FALSE, time);
 		return;
+	}
 
 	destination = gth_folder_tree_get_file (GTH_FOLDER_TREE (browser->priv->folder_tree), path);
 	uris = gtk_selection_data_get_uris (selection_data);
@@ -2523,6 +2523,8 @@ folder_tree_drag_data_received (GtkWidget        *tree_view,
 	if (file_list != NULL)
 		gth_hook_invoke ("gth-browser-folder-tree-drag-data-received", browser, destination, file_list, suggested_action);
 
+	gtk_drag_finish (context, TRUE, FALSE, time);
+
 	_g_object_list_unref (file_list);
 	g_strfreev (uris);
 	_g_object_unref (destination);
@@ -2550,7 +2552,8 @@ folder_tree_drag_data_get_cb (GtkWidget        *widget,
 	if (file_source == NULL)
 		return;
 
-	drag_context->suggested_action = gth_file_source_can_cut (file_source, file_data->file) ? GDK_ACTION_MOVE : GDK_ACTION_COPY;
+	if (drag_context->actions && GDK_ACTION_MOVE)
+		drag_context->suggested_action = gth_file_source_can_cut (file_source, file_data->file) ? GDK_ACTION_MOVE : GDK_ACTION_COPY;
 
 	uris = g_new (char *, 2);
 	uris[0] = g_file_get_uri (file_data->file);
diff --git a/gthumb/gth-file-list.c b/gthumb/gth-file-list.c
index 815f20b..d7daa45 100644
--- a/gthumb/gth-file-list.c
+++ b/gthumb/gth-file-list.c
@@ -666,10 +666,10 @@ gth_file_list_construct (GthFileList     *file_list,
 		gtk_target_list_add_text_targets (target_list, 0);
 		targets = gtk_target_table_new_from_list (target_list, &n_targets);
 		gth_file_view_enable_drag_source (GTH_FILE_VIEW (file_list->priv->view),
-						  GDK_BUTTON1_MASK,
+						  GDK_BUTTON1_MASK | GDK_BUTTON2_MASK,
 						  targets,
 						  n_targets,
-						  GDK_ACTION_MOVE | GDK_ACTION_COPY);
+						  GDK_ACTION_COPY | GDK_ACTION_MOVE | GDK_ACTION_ASK);
 
 		gtk_target_list_unref (target_list);
 		gtk_target_table_free (targets, n_targets);
diff --git a/gthumb/gth-icon-view.c b/gthumb/gth-icon-view.c
index 00559ec..cd570d3 100644
--- a/gthumb/gth-icon-view.c
+++ b/gthumb/gth-icon-view.c
@@ -44,6 +44,7 @@ struct _GthIconViewPrivate {
 	GdkDragAction    drag_actions;
 
 	gboolean         dragging : 1;        /* Whether the user is dragging items. */
+	int              drag_button;
 	gboolean         drag_started : 1;    /* Whether the drag has started. */
 	int              drag_start_x;        /* The position where the drag started. */
 	int              drag_start_y;
@@ -556,6 +557,20 @@ icon_view_button_press_event_cb (GtkWidget      *widget,
 		return TRUE;
 	}
 
+	if ((event->button == 2) && (event->type == GDK_BUTTON_PRESS)) {
+		/* This can be the start of a dragging action. */
+
+		if (! (event->state & GDK_CONTROL_MASK)
+		    && ! (event->state & GDK_SHIFT_MASK)
+		    && icon_view->priv->drag_source_enabled)
+		{
+			icon_view->priv->dragging = TRUE;
+			icon_view->priv->drag_button = 2;
+			icon_view->priv->drag_start_x = event->x;
+			icon_view->priv->drag_start_y = event->y;
+		}
+	}
+
 	if ((event->button == 1) && (event->type == GDK_BUTTON_PRESS)) {
 		GtkTreePath *path;
 		int          pos;
@@ -576,6 +591,7 @@ icon_view_button_press_event_cb (GtkWidget      *widget,
 		    && icon_view->priv->drag_source_enabled)
 		{
 			icon_view->priv->dragging = TRUE;
+			icon_view->priv->drag_button = 1;
 			icon_view->priv->drag_start_x = event->x;
 			icon_view->priv->drag_start_y = event->y;
 		}
@@ -686,8 +702,10 @@ icon_view_motion_notify_event_cb (GtkWidget      *widget,
 			context = gtk_drag_begin (widget,
 						  icon_view->priv->drag_target_list,
 						  icon_view->priv->drag_actions,
-						  1,
+						  icon_view->priv->drag_button,
 						  (GdkEvent *) event);
+			if (icon_view->priv->drag_button == 2)
+				context->suggested_action = GDK_ACTION_ASK;
 
 			dnd_icon = gtk_icon_view_create_drag_icon (GTK_ICON_VIEW (icon_view), path);
 			gdk_drawable_get_size (dnd_icon, &width, &height);
diff --git a/gthumb/gtk-utils.c b/gthumb/gtk-utils.c
index 82d4f55..337d711 100644
--- a/gthumb/gtk-utils.c
+++ b/gthumb/gtk-utils.c
@@ -1124,3 +1124,119 @@ _gtk_info_bar_clear_action_area (GtkInfoBar *info_bar)
 {
 	_gtk_container_remove_children (GTK_CONTAINER (gtk_info_bar_get_action_area (info_bar)), NULL, NULL);
 }
+
+
+/* -- _gtk_menu_ask_drag_drop_action -- */
+
+
+typedef struct {
+	GMainLoop     *loop;
+	GdkDragAction  action;
+} DropActionData;
+
+
+static void
+ask_drag_drop_action_menu_deactivate_cb (GtkMenuShell *menushell,
+					 gpointer      user_data)
+{
+	DropActionData *drop_data = user_data;
+
+	if (g_main_loop_is_running (drop_data->loop))
+		g_main_loop_quit (drop_data->loop);
+}
+
+
+static void
+ask_drag_drop_action_item_activate_cb (GtkMenuItem *menuitem,
+                		       gpointer     user_data)
+{
+	DropActionData *drop_data = user_data;
+
+	drop_data->action = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (menuitem), "drop-action"));
+	if (g_main_loop_is_running (drop_data->loop))
+		g_main_loop_quit (drop_data->loop);
+}
+
+
+static void
+_gtk_menu_ask_drag_drop_action_append_item (GtkWidget      *menu,
+					    const char     *label,
+					    GdkDragAction   actions,
+					    GdkDragAction   action,
+					    DropActionData *drop_data)
+{
+	GtkWidget *item;
+
+	item = gtk_menu_item_new_with_mnemonic (label);
+	g_object_set_data (G_OBJECT (item), "drop-action", GINT_TO_POINTER (action));
+	gtk_widget_set_sensitive (item, ((actions & action) != 0));
+	gtk_widget_show (item);
+	gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
+
+	g_signal_connect (item,
+			  "activate",
+			  G_CALLBACK (ask_drag_drop_action_item_activate_cb),
+			  drop_data);
+}
+
+
+GdkDragAction
+_gtk_menu_ask_drag_drop_action (GtkWidget     *widget,
+				GdkDragAction  actions,
+				guint32        activate_time)
+{
+	DropActionData  drop_data;
+	GtkWidget      *menu;
+	GtkWidget      *item;
+
+	drop_data.action = 0;
+	drop_data.loop = g_main_loop_new (NULL, FALSE);
+
+	menu = gtk_menu_new ();
+	gtk_menu_set_screen (GTK_MENU (menu), gtk_widget_get_screen (widget));
+
+	_gtk_menu_ask_drag_drop_action_append_item (menu,
+						    _("_Copy Here"),
+						    actions,
+						    GDK_ACTION_COPY,
+						    &drop_data);
+	_gtk_menu_ask_drag_drop_action_append_item (menu,
+						    _("_Move Here"),
+						    actions,
+						    GDK_ACTION_MOVE,
+						    &drop_data);
+	_gtk_menu_ask_drag_drop_action_append_item (menu,
+						    _("_Link Here"),
+						    actions,
+						    GDK_ACTION_LINK,
+						    &drop_data);
+
+	item = gtk_separator_menu_item_new ();
+	gtk_widget_show (item);
+	gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
+
+	item = gtk_menu_item_new_with_label (_("Cancel"));
+	gtk_widget_show (item);
+	gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
+
+	g_signal_connect (menu,
+        		  "deactivate",
+                          G_CALLBACK (ask_drag_drop_action_menu_deactivate_cb),
+                          &drop_data);
+
+	gtk_menu_popup (GTK_MENU (menu),
+			NULL,
+			NULL,
+			NULL,
+			NULL,
+			0,
+			activate_time);
+	gtk_grab_add (menu);
+	g_main_loop_run (drop_data.loop);
+
+	gtk_grab_remove (menu);
+	gtk_widget_destroy (menu);
+	g_main_loop_unref (drop_data.loop);
+
+	return drop_data.action;
+}
diff --git a/gthumb/gtk-utils.h b/gthumb/gtk-utils.h
index 988f283..c01c8a7 100644
--- a/gthumb/gtk-utils.h
+++ b/gthumb/gtk-utils.h
@@ -125,6 +125,10 @@ void        _gtk_window_resize_to_fit_screen_height
 					    int               default_width);
 void        _gtk_info_bar_clear_action_area (GtkInfoBar      *info_bar);
 
+GdkDragAction _gtk_menu_ask_drag_drop_action (GtkWidget     *widget,
+					      GdkDragAction  actions,
+					      guint32        activate_time);
+
 G_END_DECLS
 
 #endif



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