From c6505454dca4a33a1bceaf96484b9ed8c03e560a Mon Sep 17 00:00:00 2001 From: Benedikt Meurer <benny@xfce.org> Date: Wed, 13 Sep 2006 23:36:10 +0000 Subject: [PATCH] 2006-09-14 Benedikt Meurer <benny@xfce.org> * thunarx/thunarx-menu-provider.{c,h}, thunarx/thunarx.symbols: Add a new method get_dnd_actions() to the ThunarxMenuProvider, which allows menu providers to install additional actions into the Drag'n'Drop menu of the file manager. * docs/reference/thunarx/: Update the thunarx reference manual. * thunar/thunar-dnd.{c,h}, thunar/thunar-location-button.c, thunar/thunar-shortcuts-view.c, thunar/thunar-standard-view.c, thunar/thunar-tree-view.c: Insert the additional actions supplied by the installed menu providers into the Drag'n'Drop menu. (Old svn revision: 23151) --- ChangeLog | 12 ++ docs/reference/thunarx/thunarx-sections.txt | 1 + .../thunarx/tmpl/thunarx-menu-provider.sgml | 13 ++ .../thunarx/tmpl/thunarx-renamer.sgml | 10 +- thunar/thunar-dnd.c | 138 +++++++++++++----- thunar/thunar-dnd.h | 4 +- thunar/thunar-location-button.c | 4 +- thunar/thunar-shortcuts-view.c | 32 ++-- thunar/thunar-standard-view.c | 4 +- thunar/thunar-tree-view.c | 4 +- thunarx/thunarx-menu-provider.c | 67 ++++++++- thunarx/thunarx-menu-provider.h | 17 ++- thunarx/thunarx.symbols | 5 +- 13 files changed, 240 insertions(+), 71 deletions(-) diff --git a/ChangeLog b/ChangeLog index aa591c386..3bee53476 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,15 @@ +2006-09-14 Benedikt Meurer <benny@xfce.org> + + * thunarx/thunarx-menu-provider.{c,h}, thunarx/thunarx.symbols: Add a + new method get_dnd_actions() to the ThunarxMenuProvider, which allows + menu providers to install additional actions into the Drag'n'Drop + menu of the file manager. + * docs/reference/thunarx/: Update the thunarx reference manual. + * thunar/thunar-dnd.{c,h}, thunar/thunar-location-button.c, + thunar/thunar-shortcuts-view.c, thunar/thunar-standard-view.c, + thunar/thunar-tree-view.c: Insert the additional actions supplied + by the installed menu providers into the Drag'n'Drop menu. + 2006-09-13 Benedikt Meurer <benny@xfce.org> * thunar-vfs/thunar-vfs-monitor.c, thunar/thunar-standard-view.c: diff --git a/docs/reference/thunarx/thunarx-sections.txt b/docs/reference/thunarx/thunarx-sections.txt index 066342202..d03dc9054 100644 --- a/docs/reference/thunarx/thunarx-sections.txt +++ b/docs/reference/thunarx/thunarx-sections.txt @@ -35,6 +35,7 @@ ThunarxMenuProviderIface ThunarxMenuProvider thunarx_menu_provider_get_file_actions thunarx_menu_provider_get_folder_actions +thunarx_menu_provider_get_dnd_actions <SUBSECTION Standard> THUNARX_TYPE_MENU_PROVIDER THUNARX_MENU_PROVIDER diff --git a/docs/reference/thunarx/tmpl/thunarx-menu-provider.sgml b/docs/reference/thunarx/tmpl/thunarx-menu-provider.sgml index 1ee6e3c22..bc71743e7 100644 --- a/docs/reference/thunarx/tmpl/thunarx-menu-provider.sgml +++ b/docs/reference/thunarx/tmpl/thunarx-menu-provider.sgml @@ -112,6 +112,7 @@ Stable @get_file_actions: See thunarx_menu_provider_get_file_actions(). @get_folder_actions: See thunarx_menu_provider_get_folder_actions(). +@get_dnd_actions: See thunarx_menu_provider_get_dnd_actions(). <!-- ##### STRUCT ThunarxMenuProvider ##### --> <para> @@ -141,3 +142,15 @@ Stable @Returns: +<!-- ##### FUNCTION thunarx_menu_provider_get_dnd_actions ##### --> +<para> + +</para> + +@provider: +@window: +@folder: +@files: +@Returns: + + diff --git a/docs/reference/thunarx/tmpl/thunarx-renamer.sgml b/docs/reference/thunarx/tmpl/thunarx-renamer.sgml index 09f379acc..05ff01464 100644 --- a/docs/reference/thunarx/tmpl/thunarx-renamer.sgml +++ b/docs/reference/thunarx/tmpl/thunarx-renamer.sgml @@ -73,11 +73,11 @@ The abstract base class for bulk renamers rename module in Thunar. </para> -@process: see thunarx_renamer_process(). -@load: see thunarx_renamer_load(). -@save: see thunarx_renamer_save(). -@get_actions: -@changed: see thunarx_renamer_changed(). +@process: see thunarx_renamer_process(). +@load: see thunarx_renamer_load(). +@save: see thunarx_renamer_save(). +@get_actions: see thunarx_renamer_get_actions(). +@changed: see thunarx_renamer_changed(). <!-- ##### FUNCTION thunarx_renamer_get_help_url ##### --> <para> diff --git a/thunar/thunar-dnd.c b/thunar/thunar-dnd.c index cfef78898..4fb278c62 100644 --- a/thunar/thunar-dnd.c +++ b/thunar/thunar-dnd.c @@ -21,27 +21,32 @@ #include <config.h> #endif +#include <thunarx/thunarx.h> + #include <thunar/thunar-application.h> #include <thunar/thunar-dialogs.h> #include <thunar/thunar-dnd.h> +#include <thunar/thunar-gtk-extensions.h> #include <thunar/thunar-private.h> static void -action_selected (GtkWidget *item, - GdkDragAction *action) +dnd_action_selected (GtkWidget *item, + GdkDragAction *dnd_action_return) { - *action = GPOINTER_TO_UINT (g_object_get_data (G_OBJECT (item), I_("action"))); + *dnd_action_return = GPOINTER_TO_UINT (g_object_get_data (G_OBJECT (item), "dnd-action")); } /** * thunar_dnd_ask: - * @widget : the widget on which the drop was performed. - * @time : the time of the drop event. - * @actions : the list of actions supported for the drop. + * @widget : the widget on which the drop was performed. + * @folder : the #ThunarFile to which the @path_list is being dropped. + * @path_list : the #ThunarVfsPath<!---->s 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 @@ -56,45 +61,51 @@ action_selected (GtkWidget *item, **/ GdkDragAction thunar_dnd_ask (GtkWidget *widget, + ThunarFile *folder, + GList *path_list, guint time, - GdkDragAction actions) + GdkDragAction dnd_actions) { - static const GdkDragAction action_items[] = { GDK_ACTION_COPY, GDK_ACTION_MOVE, GDK_ACTION_LINK }; - static const gchar *action_names[] = { N_ ("_Copy here"), N_ ("_Move here"), N_ ("_Link here") }; - static const gchar *action_icons[] = { "stock_folder-copy", "stock_folder-move", NULL }; - - GdkDragAction action = 0; - GtkWidget *image; - GtkWidget *menu; - GtkWidget *item; - GMainLoop *loop; - guint n; - + 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); - /* prepare the internal loop */ - loop = g_main_loop_new (NULL, FALSE); + /* connect to the provider factory */ + factory = thunarx_provider_factory_get_default (); /* prepare the popup menu */ menu = gtk_menu_new (); - gtk_menu_set_screen (GTK_MENU (menu), gtk_widget_get_screen (widget)); - g_signal_connect_swapped (G_OBJECT (menu), "deactivate", G_CALLBACK (g_main_loop_quit), loop); - exo_gtk_object_ref_sink (GTK_OBJECT (menu)); /* append the various items */ - for (n = 0; n < G_N_ELEMENTS (action_items); ++n) - if (G_LIKELY ((actions & action_items[n]) != 0)) + 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 (_(action_names[n])); - g_object_set_data (G_OBJECT (item), I_("action"), GUINT_TO_POINTER (action_items[n])); - g_signal_connect (G_OBJECT (item), "activate", G_CALLBACK (action_selected), &action); + 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 (action_icons[n] != NULL)) + if (G_LIKELY (dnd_action_icons[n] != NULL)) { - image = gtk_image_new_from_icon_name (action_icons[n], GTK_ICON_SIZE_MENU); + 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); } @@ -105,22 +116,71 @@ thunar_dnd_ask (GtkWidget *widget, gtk_menu_shell_append (GTK_MENU_SHELL (menu), item); gtk_widget_show (item); + /* determine the toplevel window the widget belongs to */ + window = gtk_widget_get_toplevel (widget); + if (G_LIKELY (window != NULL && GTK_WIDGET_TOPLEVEL (window))) + { + /* check if we can resolve all paths */ + for (lp = path_list; lp != NULL; lp = lp->next) + { + /* try to resolve this path */ + file = thunar_file_cache_lookup (lp->data); + if (G_LIKELY (file != NULL)) + file_list = g_list_prepend (file_list, file); + else + break; + } + + /* check if we resolved all paths (and have atleast one file) */ + if (G_LIKELY (file_list != NULL && lp == NULL)) + { + /* load the menu providers from the provider factory */ + providers = thunarx_provider_factory_list_providers (factory, THUNARX_TYPE_MENU_PROVIDER); + + /* load the dnd actions offered by the menu providers */ + for (lp = providers; lp != NULL; lp = lp->next) + { + /* merge the actions from this provider */ + actions = g_list_concat (actions, thunarx_menu_provider_get_dnd_actions (lp->data, window, THUNARX_FILE_INFO (folder), file_list)); + g_object_unref (G_OBJECT (lp->data)); + } + g_list_free (providers); + + /* check if we have atleast one action */ + if (G_UNLIKELY (actions != NULL)) + { + /* add menu items for all actions */ + for (lp = actions; lp != NULL; lp = lp->next) + { + /* add a menu item for the action */ + item = gtk_action_create_menu_item (lp->data); + gtk_menu_shell_append (GTK_MENU_SHELL (menu), item); + g_object_unref (G_OBJECT (lp->data)); + gtk_widget_show (item); + } + g_list_free (actions); + + /* append another 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 internal loop */ - gtk_grab_add (menu); - gtk_menu_popup (GTK_MENU (menu), NULL, NULL, NULL, NULL, 3, time); - g_main_loop_run (loop); - gtk_grab_remove (menu); + /* 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); - /* clean up */ - g_object_unref (G_OBJECT (menu)); - g_main_loop_unref (loop); + /* cleanup */ + g_object_unref (G_OBJECT (factory)); + g_list_free (file_list); - return action; + return dnd_action; } diff --git a/thunar/thunar-dnd.h b/thunar/thunar-dnd.h index 7163d11fe..f1e83555a 100644 --- a/thunar/thunar-dnd.h +++ b/thunar/thunar-dnd.h @@ -1,6 +1,6 @@ /* $Id$ */ /*- - * Copyright (c) 2005 Benedikt Meurer <benny@xfce.org> + * Copyright (c) 2005-2006 Benedikt Meurer <benny@xfce.org> * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the Free @@ -25,6 +25,8 @@ G_BEGIN_DECLS; GdkDragAction thunar_dnd_ask (GtkWidget *widget, + ThunarFile *folder, + GList *path_list, guint time, GdkDragAction actions); diff --git a/thunar/thunar-location-button.c b/thunar/thunar-location-button.c index ad5d65324..2c3d6257a 100644 --- a/thunar/thunar-location-button.c +++ b/thunar/thunar-location-button.c @@ -703,7 +703,9 @@ thunar_location_button_drag_data_received (GtkWidget *button, if (G_LIKELY ((actions & (GDK_ACTION_COPY | GDK_ACTION_MOVE | GDK_ACTION_LINK)) != 0)) { /* as the user what to do with the drop data */ - action = (context->action == GDK_ACTION_ASK) ? thunar_dnd_ask (button, time, actions) : context->action; + action = (context->action == GDK_ACTION_ASK) + ? thunar_dnd_ask (button, location_button->file, location_button->drop_path_list, time, actions) + : context->action; /* perform the requested action */ if (G_LIKELY (action != 0)) diff --git a/thunar/thunar-shortcuts-view.c b/thunar/thunar-shortcuts-view.c index ce3b998c1..5c88b9771 100644 --- a/thunar/thunar-shortcuts-view.c +++ b/thunar/thunar-shortcuts-view.c @@ -487,29 +487,29 @@ thunar_shortcuts_view_drag_data_received (GtkWidget *widget, } 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); + /* get the shortcuts model */ + model = gtk_tree_view_get_model (GTK_TREE_VIEW (view)); - /* perform the requested action */ - if (G_LIKELY (action != 0)) + /* determine the iterator for the path */ + if (gtk_tree_model_get_iter (model, &iter, path)) { - /* 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)) { - /* determine the file for the iter */ - gtk_tree_model_get (model, &iter, THUNAR_SHORTCUTS_MODEL_COLUMN_FILE, &file, -1); - if (G_LIKELY (file != NULL)) + /* ask the user what to do with the drop data */ + if (G_UNLIKELY (action == GDK_ACTION_ASK)) + action = thunar_dnd_ask (widget, file, view->drop_path_list, time, actions); + + /* perform the requested action */ + if (G_LIKELY (action != 0)) { /* 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 file */ + g_object_unref (G_OBJECT (file)); } } } diff --git a/thunar/thunar-standard-view.c b/thunar/thunar-standard-view.c index 8aab7c2f8..89e55c7f1 100644 --- a/thunar/thunar-standard-view.c +++ b/thunar/thunar-standard-view.c @@ -2770,7 +2770,9 @@ thunar_standard_view_drag_data_received (GtkWidget *view, if (G_LIKELY ((actions & (GDK_ACTION_COPY | GDK_ACTION_MOVE | GDK_ACTION_LINK)) != 0)) { /* ask the user what to do with the drop data */ - action = (context->action == GDK_ACTION_ASK) ? thunar_dnd_ask (GTK_WIDGET (standard_view), time, actions) : context->action; + action = (context->action == GDK_ACTION_ASK) + ? thunar_dnd_ask (GTK_WIDGET (standard_view), file, standard_view->priv->drop_path_list, time, actions) + : context->action; /* perform the requested action */ if (G_LIKELY (action != 0)) diff --git a/thunar/thunar-tree-view.c b/thunar/thunar-tree-view.c index d71105850..189f8fbda 100644 --- a/thunar/thunar-tree-view.c +++ b/thunar/thunar-tree-view.c @@ -734,7 +734,9 @@ thunar_tree_view_drag_data_received (GtkWidget *widget, if (G_LIKELY ((actions & (GDK_ACTION_COPY | GDK_ACTION_MOVE | GDK_ACTION_LINK)) != 0)) { /* ask the user what to do with the drop data */ - action = (context->action == GDK_ACTION_ASK) ? thunar_dnd_ask (GTK_WIDGET (view), time, actions) : context->action; + action = (context->action == GDK_ACTION_ASK) + ? thunar_dnd_ask (GTK_WIDGET (view), file, view->drop_path_list, time, actions) + : context->action; /* perform the requested action */ if (G_LIKELY (action != 0)) diff --git a/thunarx/thunarx-menu-provider.c b/thunarx/thunarx-menu-provider.c index 7c6f5f113..5bb5be29b 100644 --- a/thunarx/thunarx-menu-provider.c +++ b/thunarx/thunarx-menu-provider.c @@ -1,6 +1,6 @@ /* $Id$ */ /*- - * Copyright (c) 2005 Benedikt Meurer <benny@xfce.org> + * Copyright (c) 2005-2006 Benedikt Meurer <benny@xfce.org> * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public @@ -172,5 +172,70 @@ thunarx_menu_provider_get_folder_actions (ThunarxMenuProvider *provider, +/** + * thunarx_menu_provider_get_dnd_actions: + * @provider : a #ThunarxMenuProvider. + * @window : the #GtkWindow within which the actions will be used. + * @folder : the folder into which the @files are being dropped + * @files : the list of #ThunarxFileInfo<!---->s for the files that are + * being dropped to @folder in @window. + * + * Returns the list of #GtkAction<!---->s that @provider has to offer for + * dropping the @files into the @folder. For example, the thunar-archive-plugin + * provides <guilabel>Extract Here</guilabel> actions when dropping archive + * files into a folder that is writable by the user. + * + * As a special note, this method automatically takes a reference on the + * @provider for every #GtkAction object returned from the real implementation + * of this method in @provider. This is to make sure that the extension stays + * in memory for atleast the time that the actions are used. If the extension + * wants to stay in memory for a longer time, it'll need to take care of this + * itself (e.g. by taking an additional reference on the @provider itself, + * that's released at a later time). + * + * The caller is responsible to free the returned list of actions using + * something like this when no longer needed: + * <informalexample><programlisting> + * g_list_foreach (list, (GFunc) g_object_unref, NULL); + * g_list_free (list); + * </programlisting></informalexample> + * + * Return value: the list of #GtkAction<!---->s that @provider has to offer + * for dropping @files to @folder. + * + * Since: 0.4.1 + **/ +GList* +thunarx_menu_provider_get_dnd_actions (ThunarxMenuProvider *provider, + GtkWidget *window, + ThunarxFileInfo *folder, + GList *files) +{ + GList *actions; + + g_return_val_if_fail (THUNARX_IS_MENU_PROVIDER (provider), NULL); + g_return_val_if_fail (GTK_IS_WINDOW (window), NULL); + g_return_val_if_fail (THUNARX_IS_FILE_INFO (folder), NULL); + g_return_val_if_fail (thunarx_file_info_is_directory (folder), NULL); + g_return_val_if_fail (files != NULL, NULL); + + if (THUNARX_MENU_PROVIDER_GET_IFACE (provider)->get_dnd_actions != NULL) + { + /* query the actions from the implementation */ + actions = (*THUNARX_MENU_PROVIDER_GET_IFACE (provider)->get_dnd_actions) (provider, window, folder, files); + + /* take a reference on the provider for each action */ + thunarx_object_list_take_reference (actions, provider); + } + else + { + actions = NULL; + } + + return actions; +} + + + #define __THUNARX_MENU_PROVIDER_C__ #include <thunarx/thunarx-aliasdef.c> diff --git a/thunarx/thunarx-menu-provider.h b/thunarx/thunarx-menu-provider.h index d6efdd98f..018babc2b 100644 --- a/thunarx/thunarx-menu-provider.h +++ b/thunarx/thunarx-menu-provider.h @@ -1,6 +1,6 @@ /* $Id$ */ /*- - * Copyright (c) 2005 Benedikt Meurer <benny@xfce.org> + * Copyright (c) 2005-2006 Benedikt Meurer <benny@xfce.org> * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public @@ -53,22 +53,31 @@ struct _ThunarxMenuProviderIface GtkWidget *window, ThunarxFileInfo *folder); + GList *(*get_dnd_actions) (ThunarxMenuProvider *provider, + GtkWidget *window, + ThunarxFileInfo *folder, + GList *files); + /*< private >*/ void (*reserved1) (void); void (*reserved2) (void); void (*reserved3) (void); - void (*reserved4) (void); }; GType thunarx_menu_provider_get_type (void) G_GNUC_CONST; GList *thunarx_menu_provider_get_file_actions (ThunarxMenuProvider *provider, GtkWidget *window, - GList *files); + GList *files) G_GNUC_MALLOC G_GNUC_WARN_UNUSED_RESULT; GList *thunarx_menu_provider_get_folder_actions (ThunarxMenuProvider *provider, GtkWidget *window, - ThunarxFileInfo *folder); + ThunarxFileInfo *folder) G_GNUC_MALLOC G_GNUC_WARN_UNUSED_RESULT; + +GList *thunarx_menu_provider_get_dnd_actions (ThunarxMenuProvider *provider, + GtkWidget *window, + ThunarxFileInfo *folder, + GList *files) G_GNUC_MALLOC G_GNUC_WARN_UNUSED_RESULT; G_END_DECLS; diff --git a/thunarx/thunarx.symbols b/thunarx/thunarx.symbols index 849cdb9c5..ebb82cee5 100644 --- a/thunarx/thunarx.symbols +++ b/thunarx/thunarx.symbols @@ -68,8 +68,9 @@ thunarx_file_info_list_free #if IN_HEADER(__THUNARX_MENU_PROVIDER_H__) #if IN_SOURCE(__THUNARX_MENU_PROVIDER_C__) thunarx_menu_provider_get_type G_GNUC_CONST -thunarx_menu_provider_get_file_actions -thunarx_menu_provider_get_folder_actions +thunarx_menu_provider_get_file_actions G_GNUC_MALLOC G_GNUC_WARN_UNUSED_RESULT +thunarx_menu_provider_get_folder_actions G_GNUC_MALLOC G_GNUC_WARN_UNUSED_RESULT +thunarx_menu_provider_get_dnd_actions G_GNUC_MALLOC G_GNUC_WARN_UNUSED_RESULT #endif #endif -- GitLab