diff -rupN thunar-svn29263.orig/ChangeLog thunar-svn29263/ChangeLog --- thunar-svn29263.orig/ChangeLog 2009-01-16 16:09:39.000000000 +0100 +++ thunar-svn29263/ChangeLog 2009-01-16 16:09:41.000000000 +0100 @@ -1,3 +1,17 @@ +2009-01-16 Helmut Duregger + + * thunar/thunar-dnd.{h,c}: Add new function thunar_dnd_new_menu_head() + that prepares a menu with Drag'n'Drop options and can be reused + for consistent order of menu items. Replace part of menu creation + in thunar_dnd_ask() with that new function. Add new + function thunar_dnd_ask_netscape_url() that also uses the above + new function and let the user choose whether to link to or copy the + content at a _NETSCAPE_URL. + * thunar/thunar-standard-view.c: Add call to thunar_dnd_ask_netscape_url() + for _NETSCAPE_URL to provide a menu to the user, then either link + with existing exo functionality or copy/download the file at the URL + with a call to wget. + 2009-01-14 Jannis Pohlmann * configure.in.in: Add the 'svn' version tag again. diff -rupN thunar-svn29263.orig/thunar/thunar-dnd.c thunar-svn29263/thunar/thunar-dnd.c --- thunar-svn29263.orig/thunar/thunar-dnd.c 2009-01-16 16:09:34.000000000 +0100 +++ thunar-svn29263/thunar/thunar-dnd.c 2009-01-16 13:01:22.000000000 +0100 @@ -41,6 +41,55 @@ dnd_action_selected (GtkWidget *item /** + * thunar_dnd_new_menu_head: + * @dnd_actions : the actions to be added to the menu + * @dnd_action : the location of the buffer that will store the selected action + * + * Creates a menu for the actions specified in @dnd_actions. This can be any + * combination of GDK_ACTION_COPY, GDK_ACTION_MOVE and GDK_ACTION_LINK. + * When the user selects an action the result will be stored at @dnd_action. + * + * Return value: the created #GtkWidget menu. + **/ +GtkWidget* +thunar_dnd_new_menu_head (GdkDragAction dnd_actions, GdkDragAction *dnd_action) +{ + static const GdkDragAction dnd_action_items[] = { GDK_ACTION_COPY, GDK_ACTION_MOVE, GDK_ACTION_LINK }; + static const gchar *dnd_action_names[] = { N_ ("_Copy here"), N_ ("_Move here"), N_ ("_Link here") }; + static const gchar *dnd_action_icons[] = { "stock_folder-copy", "stock_folder-move", NULL }; + + GtkWidget *menu; + GtkWidget *item; + GtkWidget *image; + guint n; + + menu = gtk_menu_new (); + + /* append the various items */ + for (n = 0; n < G_N_ELEMENTS (dnd_action_items); ++n) + if (G_LIKELY ((dnd_actions & dnd_action_items[n]) != 0)) + { + item = gtk_image_menu_item_new_with_mnemonic (_(dnd_action_names[n])); + g_object_set_data (G_OBJECT (item), I_("dnd-action"), GUINT_TO_POINTER (dnd_action_items[n])); + g_signal_connect (G_OBJECT (item), "activate", G_CALLBACK (dnd_action_selected), dnd_action); + gtk_menu_shell_append (GTK_MENU_SHELL (menu), item); + gtk_widget_show (item); + + /* add image to the menu item */ + if (G_LIKELY (dnd_action_icons[n] != NULL)) + { + image = gtk_image_new_from_icon_name (dnd_action_icons[n], GTK_ICON_SIZE_MENU); + gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (item), image); + gtk_widget_show (image); + } + } + + return menu; +} + + + +/** * thunar_dnd_ask: * @widget : the widget on which the drop was performed. * @folder : the #ThunarFile to which the @path_list is being dropped. @@ -66,22 +115,16 @@ thunar_dnd_ask (GtkWidget *widget, guint time, GdkDragAction dnd_actions) { - static const GdkDragAction dnd_action_items[] = { GDK_ACTION_COPY, GDK_ACTION_MOVE, GDK_ACTION_LINK }; - static const gchar *dnd_action_names[] = { N_ ("_Copy here"), N_ ("_Move here"), N_ ("_Link here") }; - static const gchar *dnd_action_icons[] = { "stock_folder-copy", "stock_folder-move", NULL }; - ThunarxProviderFactory *factory; GdkDragAction dnd_action = 0; ThunarFile *file; GtkWidget *window; - GtkWidget *image; GtkWidget *menu; GtkWidget *item; GList *file_list = NULL; GList *providers = NULL; GList *actions = NULL; GList *lp; - guint n; _thunar_return_val_if_fail (thunar_file_is_directory (folder), 0); _thunar_return_val_if_fail (GTK_IS_WIDGET (widget), 0); @@ -89,27 +132,8 @@ thunar_dnd_ask (GtkWidget *widget, /* connect to the provider factory */ factory = thunarx_provider_factory_get_default (); - /* prepare the popup menu */ - menu = gtk_menu_new (); - - /* append the various items */ - for (n = 0; n < G_N_ELEMENTS (dnd_action_items); ++n) - if (G_LIKELY ((dnd_actions & dnd_action_items[n]) != 0)) - { - item = gtk_image_menu_item_new_with_mnemonic (_(dnd_action_names[n])); - g_object_set_data (G_OBJECT (item), I_("dnd-action"), GUINT_TO_POINTER (dnd_action_items[n])); - g_signal_connect (G_OBJECT (item), "activate", G_CALLBACK (dnd_action_selected), &dnd_action); - gtk_menu_shell_append (GTK_MENU_SHELL (menu), item); - gtk_widget_show (item); - - /* add image to the menu item */ - if (G_LIKELY (dnd_action_icons[n] != NULL)) - { - image = gtk_image_new_from_icon_name (dnd_action_icons[n], GTK_ICON_SIZE_MENU); - gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (item), image); - gtk_widget_show (image); - } - } + /* prepare the popup menu head */ + menu = thunar_dnd_new_menu_head (dnd_actions, &dnd_action); /* append the separator */ item = gtk_separator_menu_item_new (); @@ -186,6 +210,57 @@ thunar_dnd_ask (GtkWidget *widget, /** + * thunar_dnd_ask_netscape_url: + * @widget : the widget on which the drop was performed. + * @folder : the #ThunarFile to which the @path_list is being dropped. + * @path_list : the #ThunarVfsPaths of the files being dropped to @file. + * @time : the time of the drop event. + * @actions : the list of actions supported for the drop. + * + * Pops up a menu that asks the user to choose one of the + * @actions or to cancel the drop. If the user chooses a + * valid #GdkDragAction from @actions, then this action is + * returned. Else if the user cancels the drop, 0 will be + * returned. + * + * This method can be used to implement a response to the + * #GDK_ACTION_ASK action on drops. + * + * Return value: the selected #GdkDragAction or 0 to cancel. + **/ +GdkDragAction +thunar_dnd_ask_netscape_url (GtkWidget *widget, + guint time, + GdkDragAction dnd_actions) +{ + GdkDragAction dnd_action = 0; + GtkWidget *menu; + GtkWidget *item; + + _thunar_return_val_if_fail (GTK_IS_WIDGET (widget), 0); + + /* prepare the popup menu head */ + menu = thunar_dnd_new_menu_head (dnd_actions, &dnd_action); + + /* append the separator */ + item = gtk_separator_menu_item_new (); + gtk_menu_shell_append (GTK_MENU_SHELL (menu), item); + gtk_widget_show (item); + + /* append the cancel item */ + item = gtk_image_menu_item_new_from_stock (GTK_STOCK_CANCEL, NULL); + gtk_menu_shell_append (GTK_MENU_SHELL (menu), item); + gtk_widget_show (item); + + /* run the menu on the widget's screen (takes over the floating reference of menu) */ + thunar_gtk_menu_run (GTK_MENU (menu), widget, NULL, NULL, 3, time); + + return dnd_action; +} + + + +/** * thunar_dnd_perform: * @widget : the #GtkWidget on which the drop was done. * @file : the #ThunarFile on which the @path_list was dropped. diff -rupN thunar-svn29263.orig/thunar/thunar-dnd.h thunar-svn29263/thunar/thunar-dnd.h --- thunar-svn29263.orig/thunar/thunar-dnd.h 2009-01-16 16:09:34.000000000 +0100 +++ thunar-svn29263/thunar/thunar-dnd.h 2009-01-16 13:09:31.000000000 +0100 @@ -24,17 +24,21 @@ G_BEGIN_DECLS; -GdkDragAction thunar_dnd_ask (GtkWidget *widget, - ThunarFile *folder, - GList *path_list, - guint time, - GdkDragAction actions); - -gboolean thunar_dnd_perform (GtkWidget *widget, - ThunarFile *file, - GList *uri_list, - GdkDragAction action, - GClosure *new_files_closure); +GdkDragAction thunar_dnd_ask (GtkWidget *widget, + ThunarFile *folder, + GList *path_list, + guint time, + GdkDragAction actions); + +GdkDragAction thunar_dnd_ask_netscape_url (GtkWidget *widget, + guint time, + GdkDragAction dnd_actions); + +gboolean thunar_dnd_perform (GtkWidget *widget, + ThunarFile *file, + GList *uri_list, + GdkDragAction action, + GClosure *new_files_closure); G_END_DECLS; diff -rupN thunar-svn29263.orig/thunar/thunar-standard-view.c thunar-svn29263/thunar/thunar-standard-view.c --- thunar-svn29263.orig/thunar/thunar-standard-view.c 2009-01-16 16:09:34.000000000 +0100 +++ thunar-svn29263/thunar/thunar-standard-view.c 2009-01-16 15:24:16.000000000 +0100 @@ -2688,49 +2688,93 @@ thunar_standard_view_drag_data_received file = thunar_standard_view_get_drop_file (standard_view, x, y, NULL); if (G_LIKELY (file != NULL)) { - /* determine the absolute path to the target directory */ - working_directory = thunar_vfs_path_dup_string (thunar_file_get_path (file)); - - /* prepare the basic part of the command */ - argv[n++] = "exo-desktop-item-edit"; - argv[n++] = "--type=Link"; - argv[n++] = "--url"; - argv[n++] = bits[0]; - argv[n++] = "--name"; - argv[n++] = bits[1]; - - /* determine the toplevel window */ - toplevel = gtk_widget_get_toplevel (view); - if (toplevel != NULL && GTK_WIDGET_TOPLEVEL (toplevel)) + actions = GDK_ACTION_COPY | GDK_ACTION_LINK; + + /* ask the user what to do with the drop data */ + action = thunar_dnd_ask_netscape_url (GTK_WIDGET (standard_view), time, actions); + + /* perform the requested action */ + if (G_LIKELY (action != 0)) { + /* determine the absolute path to the target directory */ + working_directory = thunar_vfs_path_dup_string (thunar_file_get_path (file)); + + if (G_LIKELY (action == GDK_ACTION_LINK)) + { + + /* prepare the basic part of the command */ + argv[n++] = "exo-desktop-item-edit"; + argv[n++] = "--type=Link"; + argv[n++] = "--url"; + argv[n++] = bits[0]; + argv[n++] = "--name"; + argv[n++] = bits[1]; + + /* determine the toplevel window */ + toplevel = gtk_widget_get_toplevel (view); + if (toplevel != NULL && GTK_WIDGET_TOPLEVEL (toplevel)) + { #if defined(GDK_WINDOWING_X11) - /* on X11, we can supply the parent window id here */ - argv[n++] = "--xid"; - argv[n++] = g_newa (gchar, 32); - g_snprintf (argv[n - 1], 32, "%ld", (glong) GDK_WINDOW_XID (toplevel->window)); + /* on X11, we can supply the parent window id here */ + argv[n++] = "--xid"; + argv[n++] = g_newa (gchar, 32); + g_snprintf (argv[n - 1], 32, "%ld", (glong) GDK_WINDOW_XID (toplevel->window)); #endif - } + } - /* terminate the parameter list */ - argv[n++] = "--create-new"; - argv[n++] = working_directory; - argv[n++] = NULL; - - /* try to run exo-desktop-item-edit */ - succeed = gdk_spawn_on_screen (gtk_widget_get_screen (view), working_directory, argv, NULL, - G_SPAWN_DO_NOT_REAP_CHILD | G_SPAWN_SEARCH_PATH, - NULL, NULL, &pid, &error); - if (G_UNLIKELY (!succeed)) - { - /* display an error dialog to the user */ - thunar_dialogs_show_error (standard_view, error, _("Failed to create a link for the URL \"%s\""), bits[0]); - g_free (working_directory); - g_error_free (error); - } - else - { - /* reload the directory when the command terminates */ - g_child_watch_add_full (G_PRIORITY_LOW, pid, tsv_reload_directory, working_directory, g_free); + /* terminate the parameter list */ + argv[n++] = "--create-new"; + argv[n++] = working_directory; + argv[n++] = NULL; + + /* try to run exo-desktop-item-edit */ + succeed = gdk_spawn_on_screen (gtk_widget_get_screen (view), working_directory, argv, NULL, + G_SPAWN_DO_NOT_REAP_CHILD | G_SPAWN_SEARCH_PATH, + NULL, NULL, &pid, &error); + if (G_UNLIKELY (!succeed)) + { + /* display an error dialog to the user */ + thunar_dialogs_show_error (standard_view, error, _("Failed to create a link for the URL \"%s\""), bits[0]); + g_free (working_directory); + g_error_free (error); + } + else + { + /* reload the directory when the command terminates */ + g_child_watch_add_full (G_PRIORITY_LOW, pid, tsv_reload_directory, working_directory, g_free); + } + } + else if (G_UNLIKELY (action == GDK_ACTION_COPY)) + { + /* prepare the basic part of the command */ + argv[n++] = "wget"; + argv[n++] = "--tries=20"; + argv[n++] = "--quiet"; + argv[n++] = "--timeout=30"; + argv[n++] = "--no-glob"; + argv[n++] = bits[0]; + + /* terminate the parameter list */ + argv[n++] = NULL; + + /* try to run wget */ + succeed = gdk_spawn_on_screen (gtk_widget_get_screen (view), working_directory, argv, NULL, + G_SPAWN_DO_NOT_REAP_CHILD | G_SPAWN_SEARCH_PATH, + NULL, NULL, &pid, &error); + if (G_UNLIKELY (!succeed)) + { + /* display an error dialog to the user */ + thunar_dialogs_show_error (standard_view, error, _("Failed to download the file at the URL \"%s\""), bits[0]); + g_free (working_directory); + g_error_free (error); + } + else + { + /* reload the directory when the command terminates */ + g_child_watch_add_full (G_PRIORITY_LOW, pid, tsv_reload_directory, working_directory, g_free); + } + } + } /* cleanup */