diff options
author | Matthew Barnes <mbarnes@src.gnome.org> | 2009-03-21 03:06:59 +0800 |
---|---|---|
committer | Matthew Barnes <mbarnes@src.gnome.org> | 2009-03-21 03:06:59 +0800 |
commit | 4cec9fc7169dc3b810321555a70cda916720867d (patch) | |
tree | 8fe739ab0d249fb35bedc572bd34b3717512283b /widgets/misc/e-attachment-view.c | |
parent | 7a92d9cc82b7775a0f5cb1fde233119d435a79b6 (diff) | |
download | gsoc2013-evolution-4cec9fc7169dc3b810321555a70cda916720867d.tar gsoc2013-evolution-4cec9fc7169dc3b810321555a70cda916720867d.tar.gz gsoc2013-evolution-4cec9fc7169dc3b810321555a70cda916720867d.tar.bz2 gsoc2013-evolution-4cec9fc7169dc3b810321555a70cda916720867d.tar.lz gsoc2013-evolution-4cec9fc7169dc3b810321555a70cda916720867d.tar.xz gsoc2013-evolution-4cec9fc7169dc3b810321555a70cda916720867d.tar.zst gsoc2013-evolution-4cec9fc7169dc3b810321555a70cda916720867d.zip |
Saving progress on a massive attachment handling rewrite.
svn path=/branches/kill-bonobo/; revision=37465
Diffstat (limited to 'widgets/misc/e-attachment-view.c')
-rw-r--r-- | widgets/misc/e-attachment-view.c | 1041 |
1 files changed, 1041 insertions, 0 deletions
diff --git a/widgets/misc/e-attachment-view.c b/widgets/misc/e-attachment-view.c new file mode 100644 index 0000000000..198ce75d31 --- /dev/null +++ b/widgets/misc/e-attachment-view.c @@ -0,0 +1,1041 @@ +/* + * e-attachment-view.c + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with the program; if not, see <http://www.gnu.org/licenses/> + * + * + * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) + * + */ + +#include "e-attachment-view.h" + +#include <config.h> +#include <glib/gi18n.h> +#include <camel/camel-stream-mem.h> + +#include "e-util/e-plugin-ui.h" +#include "e-util/e-util.h" +#include "e-attachment-dialog.h" + +enum { + DND_TYPE_MESSAGE_RFC822, + DND_TYPE_X_UID_LIST, + DND_TYPE_TEXT_URI_LIST, + DND_TYPE_NETSCAPE_URL, + DND_TYPE_TEXT_VCARD, + DND_TYPE_TEXT_CALENDAR +}; + +static GtkTargetEntry drop_types[] = { + { "message/rfc822", 0, DND_TYPE_MESSAGE_RFC822 }, + { "x-uid-list", 0, DND_TYPE_X_UID_LIST }, + { "text/uri-list", 0, DND_TYPE_TEXT_URI_LIST }, + { "_NETSCAPE_URL", 0, DND_TYPE_NETSCAPE_URL }, + { "text/x-vcard", 0, DND_TYPE_TEXT_VCARD }, + { "text/calendar", 0, DND_TYPE_TEXT_CALENDAR } +}; + +/* The atoms need initialized at runtime. */ +static struct { + const gchar *target; + GdkAtom atom; + GdkDragAction actions; +} drag_info[] = { + { "message/rfc822", NULL, GDK_ACTION_COPY }, + { "x-uid-list", NULL, GDK_ACTION_COPY | + GDK_ACTION_MOVE | + GDK_ACTION_ASK }, + { "text/uri-list", NULL, GDK_ACTION_COPY }, + { "_NETSCAPE_URL", NULL, GDK_ACTION_COPY }, + { "text/x-vcard", NULL, GDK_ACTION_COPY }, + { "text/calendar", NULL, GDK_ACTION_COPY } +}; + +static const gchar *ui = +"<ui>" +" <popup name='context'>" +" <menuitem action='save-as'/>" +" <menuitem action='set-background'/>" +" <menuitem action='remove'/>" +" <menuitem action='properties'/>" +" <placeholder name='custom-actions'/>" +" <separator/>" +" <menuitem action='add'/>" +" <separator/>" +" <placeholder name='open-actions'/>" +" </popup>" +" <popup name='dnd'>" +" <menuitem action='drag-copy'/>" +" <menuitem action='drag-move'/>" +" <separator/>" +" <menuitem action='drag-cancel'/>" +" </popup>" +"</ui>"; + +static void +action_add_cb (GtkAction *action, + EAttachmentView *view) +{ + EAttachmentStore *store; + gpointer parent; + + parent = gtk_widget_get_toplevel (GTK_WIDGET (view)); + parent = GTK_WIDGET_TOPLEVEL (parent) ? parent : NULL; + + store = e_attachment_view_get_store (view); + e_attachment_store_run_load_dialog (store, parent); +} + +static void +action_drag_cancel_cb (GtkAction *action, + EAttachmentView *view) +{ + EAttachmentViewPrivate *priv; + + priv = e_attachment_view_get_private (view); + gtk_drag_finish (priv->drag_context, FALSE, FALSE, priv->time); +} + +static void +action_drag_copy_cb (GtkAction *action, + EAttachmentView *view) +{ + e_attachment_view_drag_action (view, GDK_ACTION_COPY); +} + +static void +action_drag_move_cb (GtkAction *action, + EAttachmentView *view) +{ + e_attachment_view_drag_action (view, GDK_ACTION_MOVE); +} + +static void +action_properties_cb (GtkAction *action, + EAttachmentView *view) +{ + EAttachment *attachment; + GtkWidget *dialog; + GList *selected; + gpointer parent; + + selected = e_attachment_view_get_selected_attachments (view); + g_return_if_fail (g_list_length (selected) == 1); + attachment = selected->data; + + parent = gtk_widget_get_toplevel (GTK_WIDGET (view)); + parent = GTK_WIDGET_TOPLEVEL (parent) ? parent : NULL; + + dialog = e_attachment_dialog_new (parent, attachment); + gtk_dialog_run (GTK_DIALOG (dialog)); + gtk_widget_destroy (dialog); + + g_list_foreach (selected, (GFunc) g_object_unref, NULL); + g_list_free (selected); +} + +static void +action_recent_cb (GtkAction *action, + EAttachmentView *view) +{ + GtkRecentChooser *chooser; + EAttachmentStore *store; + EAttachment *attachment; + gchar *uri; + + chooser = GTK_RECENT_CHOOSER (action); + store = e_attachment_view_get_store (view); + + uri = gtk_recent_chooser_get_current_uri (chooser); + attachment = e_attachment_new_for_uri (uri); + e_attachment_store_add_attachment (store, attachment); + g_free (uri); +} + +static void +action_remove_cb (GtkAction *action, + EAttachmentView *view) +{ + e_attachment_view_remove_selected (view, FALSE); +} + +static void +action_save_as_cb (GtkAction *action, + EAttachmentView *view) +{ +} + +static void +action_set_background_cb (GtkAction *action, + EAttachmentView *view) +{ +} + +static GtkActionEntry standard_entries[] = { + + { "drag-cancel", + NULL, + N_("Cancel _Drag"), + NULL, + NULL, /* XXX Add a tooltip! */ + G_CALLBACK (action_drag_cancel_cb) }, + + { "drag-copy", + NULL, + N_("_Copy"), + NULL, + NULL, /* XXX Add a tooltip! */ + G_CALLBACK (action_drag_copy_cb) }, + + { "drag-move", + NULL, + N_("_Move"), + NULL, + NULL, /* XXX Add a tooltip! */ + G_CALLBACK (action_drag_move_cb) }, + + { "save-as", + GTK_STOCK_SAVE_AS, + NULL, + NULL, + NULL, /* XXX Add a tooltip! */ + G_CALLBACK (action_save_as_cb) }, + + { "set-background", + NULL, + N_("Set as _Background"), + NULL, + NULL, /* XXX Add a tooltip! */ + G_CALLBACK (action_set_background_cb) } +}; + +static GtkActionEntry editable_entries[] = { + + { "add", + GTK_STOCK_ADD, + N_("A_dd Attachment..."), + NULL, + NULL, /* XXX Add a tooltip! */ + G_CALLBACK (action_add_cb) }, + + { "properties", + GTK_STOCK_PROPERTIES, + NULL, + NULL, + NULL, /* XXX Add a tooltip! */ + G_CALLBACK (action_properties_cb) }, + + { "remove", + GTK_STOCK_REMOVE, + NULL, + NULL, + NULL, /* XXX Add a tooltip! */ + G_CALLBACK (action_remove_cb) } +}; + +static void +drop_message_rfc822 (EAttachmentView *view, + GtkSelectionData *selection_data, + EAttachmentStore *store, + GdkDragAction action) +{ + EAttachmentViewPrivate *priv; + EAttachment *attachment; + CamelMimeMessage *message; + CamelDataWrapper *wrapper; + CamelStream *stream; + const gchar *data; + gboolean success = FALSE; + gboolean delete = FALSE; + gint length; + + priv = e_attachment_view_get_private (view); + + data = (const gchar *) gtk_selection_data_get_data (selection_data); + length = gtk_selection_data_get_length (selection_data); + + stream = camel_stream_mem_new (); + camel_stream_write (stream, data, length); + camel_stream_reset (stream); + + message = camel_mime_message_new (); + wrapper = CAMEL_DATA_WRAPPER (message); + + if (camel_data_wrapper_construct_from_stream (wrapper, stream) == -1) + goto exit; + + attachment = e_attachment_new_for_message (message); + e_attachment_store_add_attachment (store, attachment); + g_object_unref (attachment); + + success = TRUE; + delete = (action == GDK_ACTION_MOVE); + +exit: + camel_object_unref (message); + camel_object_unref (stream); + + gtk_drag_finish (priv->drag_context, success, delete, priv->time); +} + +static void +drop_netscape_url (EAttachmentView *view, + GtkSelectionData *selection_data, + EAttachmentStore *store, + GdkDragAction action) +{ + EAttachmentViewPrivate *priv; + EAttachment *attachment; + const gchar *data; + gchar *copied_data; + gchar **strv; + gint length; + + /* _NETSCAPE_URL is represented as "URI\nTITLE" */ + + priv = e_attachment_view_get_private (view); + + data = (const gchar *) gtk_selection_data_get_data (selection_data); + length = gtk_selection_data_get_length (selection_data); + + copied_data = g_strndup (data, length); + strv = g_strsplit (copied_data, "\n", 2); + g_free (copied_data); + + attachment = e_attachment_new_for_uri (strv[0]); + e_attachment_store_add_attachment (store, attachment); + g_object_unref (attachment); + + g_strfreev (strv); + + gtk_drag_finish (priv->drag_context, TRUE, FALSE, priv->time); +} + +static void +drop_text_uri_list (EAttachmentView *view, + GtkSelectionData *selection_data, + EAttachmentStore *store, + GdkDragAction action) +{ + EAttachmentViewPrivate *priv; + gchar **uris; + gint ii; + + priv = e_attachment_view_get_private (view); + + uris = gtk_selection_data_get_uris (selection_data); + + for (ii = 0; uris[ii] != NULL; ii++) { + EAttachment *attachment; + + attachment = e_attachment_new_for_uri (uris[ii]); + e_attachment_store_add_attachment (store, attachment); + g_object_unref (attachment); + } + + g_strfreev (uris); + + gtk_drag_finish (priv->drag_context, TRUE, FALSE, priv->time); +} + +static void +drop_text_generic (EAttachmentView *view, + GtkSelectionData *selection_data, + EAttachmentStore *store, + GdkDragAction action) +{ + EAttachmentViewPrivate *priv; + EAttachment *attachment; + CamelMimePart *mime_part; + GdkAtom atom; + const gchar *data; + gchar *content_type; + gint length; + + priv = e_attachment_view_get_private (view); + + data = (const gchar *) gtk_selection_data_get_data (selection_data); + length = gtk_selection_data_get_length (selection_data); + atom = gtk_selection_data_get_data_type (selection_data); + + mime_part = camel_mime_part_new (); + + content_type = gdk_atom_name (atom); + camel_mime_part_set_content (mime_part, data, length, content_type); + camel_mime_part_set_disposition (mime_part, "inline"); + g_free (content_type); + + attachment = e_attachment_new (); + e_attachment_set_mime_part (attachment, mime_part); + e_attachment_store_add_attachment (store, attachment); + g_object_unref (attachment); + + camel_object_unref (mime_part); + + gtk_drag_finish (priv->drag_context, TRUE, FALSE, priv->time); +} + +static void +drop_x_uid_list (EAttachmentView *view, + GtkSelectionData *selection_data, + EAttachmentStore *store, + GdkDragAction action) +{ + EAttachmentViewPrivate *priv; + + /* FIXME Ugh, this looks painful. Requires mailer stuff. */ + + priv = e_attachment_view_get_private (view); + + gtk_drag_finish (priv->drag_context, FALSE, FALSE, priv->time); +} + +static void +attachment_view_class_init (EAttachmentViewIface *iface) +{ + gint ii; + + for (ii = 0; ii < G_N_ELEMENTS (drag_info); ii++) { + const gchar *target = drag_info[ii].target; + drag_info[ii].atom = gdk_atom_intern (target, FALSE); + } +} + +GType +e_attachment_view_get_type (void) +{ + static GType type = 0; + + if (G_UNLIKELY (type == 0)) { + static const GTypeInfo type_info = { + sizeof (EAttachmentViewIface), + (GBaseInitFunc) NULL, + (GBaseFinalizeFunc) NULL, + (GClassInitFunc) attachment_view_class_init, + (GClassFinalizeFunc) NULL, + NULL, /* class_data */ + 0, /* instance_size */ + 0, /* n_preallocs */ + (GInstanceInitFunc) NULL, + NULL /* value_table */ + }; + + type = g_type_register_static ( + G_TYPE_INTERFACE, "EAttachmentView", &type_info, 0); + + g_type_interface_add_prerequisite (type, GTK_TYPE_WIDGET); + } + + return type; +} + +void +e_attachment_view_init (EAttachmentView *view) +{ + EAttachmentViewPrivate *priv; + GtkUIManager *ui_manager; + GtkActionGroup *action_group; + const gchar *domain = GETTEXT_PACKAGE; + GError *error = NULL; + + priv = e_attachment_view_get_private (view); + + gtk_drag_dest_set ( + GTK_WIDGET (view), GTK_DEST_DEFAULT_ALL, + drop_types, G_N_ELEMENTS (drop_types), + GDK_ACTION_COPY | GDK_ACTION_MOVE | GDK_ACTION_ASK); + + ui_manager = gtk_ui_manager_new (); + priv->merge_id = gtk_ui_manager_new_merge_id (ui_manager); + priv->ui_manager = ui_manager; + + action_group = gtk_action_group_new ("standard"); + gtk_action_group_set_translation_domain (action_group, domain); + gtk_action_group_add_actions ( + action_group, standard_entries, + G_N_ELEMENTS (standard_entries), view); + gtk_ui_manager_insert_action_group (ui_manager, action_group, 0); + priv->standard_actions = action_group; + + action_group = gtk_action_group_new ("editable"); + gtk_action_group_set_translation_domain (action_group, domain); + gtk_action_group_add_actions ( + action_group, editable_entries, + G_N_ELEMENTS (editable_entries), view); + gtk_ui_manager_insert_action_group (ui_manager, action_group, 0); + priv->editable_actions = action_group; + + action_group = gtk_action_group_new ("openwith"); + gtk_action_group_set_translation_domain (action_group, domain); + gtk_ui_manager_insert_action_group (ui_manager, action_group, 0); + priv->openwith_actions = action_group; + + /* Because we are loading from a hard-coded string, there is + * no chance of I/O errors. Failure here implies a malformed + * UI definition. Full stop. */ + gtk_ui_manager_add_ui_from_string (ui_manager, ui, -1, &error); + if (error != NULL) + g_error ("%s", error->message); + + e_plugin_ui_register_manager (ui_manager, "attachment-view", view); +} + +void +e_attachment_view_dispose (EAttachmentView *view) +{ + EAttachmentViewPrivate *priv; + + priv = e_attachment_view_get_private (view); + + if (priv->ui_manager != NULL) { + g_object_unref (priv->ui_manager); + priv->ui_manager = NULL; + } + + if (priv->standard_actions != NULL) { + g_object_unref (priv->standard_actions); + priv->standard_actions = NULL; + } + + if (priv->editable_actions != NULL) { + g_object_unref (priv->editable_actions); + priv->editable_actions = NULL; + } + + if (priv->openwith_actions != NULL) { + g_object_unref (priv->openwith_actions); + priv->openwith_actions = NULL; + } + + if (priv->drag_context != NULL) { + g_object_unref (priv->drag_context); + priv->drag_context = NULL; + } +} + +void +e_attachment_view_finalize (EAttachmentView *view) +{ + EAttachmentViewPrivate *priv; + + priv = e_attachment_view_get_private (view); + + if (priv->selection_data != NULL) + gtk_selection_data_free (priv->selection_data); +} + +EAttachmentViewPrivate * +e_attachment_view_get_private (EAttachmentView *view) +{ + EAttachmentViewIface *iface; + + g_return_val_if_fail (E_IS_ATTACHMENT_VIEW (view), NULL); + + iface = E_ATTACHMENT_VIEW_GET_IFACE (view); + g_return_val_if_fail (iface->get_private != NULL, NULL); + + return iface->get_private (view); +} + +EAttachmentStore * +e_attachment_view_get_store (EAttachmentView *view) +{ + EAttachmentViewIface *iface; + + g_return_val_if_fail (E_IS_ATTACHMENT_VIEW (view), NULL); + + iface = E_ATTACHMENT_VIEW_GET_IFACE (view); + g_return_val_if_fail (iface->get_store != NULL, NULL); + + return iface->get_store (view); +} + +GList * +e_attachment_view_get_selected_attachments (EAttachmentView *view) +{ + EAttachmentStore *store; + GtkTreeModel *model; + GList *selected, *item; + gint column_id; + + column_id = E_ATTACHMENT_STORE_COLUMN_ATTACHMENT; + selected = e_attachment_view_get_selected_paths (view); + store = e_attachment_view_get_store (view); + model = GTK_TREE_MODEL (store); + + /* Convert the GtkTreePaths to EAttachments. */ + for (item = selected; item != NULL; item = item->next) { + EAttachment *attachment; + GtkTreePath *path; + GtkTreeIter iter; + + path = item->data; + + gtk_tree_model_get_iter (model, &iter, path); + gtk_tree_model_get (model, &iter, column_id, &attachment, -1); + gtk_tree_path_free (path); + + item->data = attachment; + } + + return selected; +} +void +e_attachment_view_remove_selected (EAttachmentView *view, + gboolean select_next) +{ + EAttachmentStore *store; + GtkTreeModel *model; + GList *selected, *item; + gint column_id; + + g_return_if_fail (E_IS_ATTACHMENT_VIEW (view)); + + column_id = E_ATTACHMENT_STORE_COLUMN_ATTACHMENT; + selected = e_attachment_view_get_selected_paths (view); + store = e_attachment_view_get_store (view); + model = GTK_TREE_MODEL (store); + + for (item = selected; item != NULL; item = item->next) { + EAttachment *attachment; + GtkTreePath *path = item->data; + GtkTreeIter iter; + + gtk_tree_model_get_iter (model, &iter, path); + gtk_tree_model_get (model, &iter, column_id, &attachment, -1); + e_attachment_store_remove_attachment (store, attachment); + g_object_unref (attachment); + } + + /* If we only removed one attachment, try to select another. */ + if (select_next && g_list_length (selected) == 1) { + GtkTreePath *path = selected->data; + + e_attachment_view_select_path (view, path); + if (!e_attachment_view_path_is_selected (view, path)) + if (gtk_tree_path_prev (path)) + e_attachment_view_select_path (view, path); + } + + g_list_foreach (selected, (GFunc) gtk_tree_path_free, NULL); + g_list_free (selected); +} + +GtkTreePath * +e_attachment_view_get_path_at_pos (EAttachmentView *view, + gint x, + gint y) +{ + EAttachmentViewIface *iface; + + g_return_val_if_fail (E_IS_ATTACHMENT_VIEW (view), NULL); + + iface = E_ATTACHMENT_VIEW_GET_IFACE (view); + g_return_val_if_fail (iface->get_path_at_pos != NULL, NULL); + + return iface->get_path_at_pos (view, x, y); +} + +GList * +e_attachment_view_get_selected_paths (EAttachmentView *view) +{ + EAttachmentViewIface *iface; + + g_return_val_if_fail (E_IS_ATTACHMENT_VIEW (view), NULL); + + iface = E_ATTACHMENT_VIEW_GET_IFACE (view); + g_return_val_if_fail (iface->get_selected_paths != NULL, NULL); + + return iface->get_selected_paths (view); +} + +gboolean +e_attachment_view_path_is_selected (EAttachmentView *view, + GtkTreePath *path) +{ + EAttachmentViewIface *iface; + + g_return_val_if_fail (E_IS_ATTACHMENT_VIEW (view), FALSE); + g_return_val_if_fail (path != NULL, FALSE); + + iface = E_ATTACHMENT_VIEW_GET_IFACE (view); + g_return_val_if_fail (iface->path_is_selected != NULL, FALSE); + + return iface->path_is_selected (view, path); +} + +void +e_attachment_view_select_path (EAttachmentView *view, + GtkTreePath *path) +{ + EAttachmentViewIface *iface; + + g_return_if_fail (E_IS_ATTACHMENT_VIEW (view)); + g_return_if_fail (path != NULL); + + iface = E_ATTACHMENT_VIEW_GET_IFACE (view); + g_return_if_fail (iface->select_path != NULL); + + iface->select_path (view, path); +} + +void +e_attachment_view_unselect_path (EAttachmentView *view, + GtkTreePath *path) +{ + EAttachmentViewIface *iface; + + g_return_if_fail (E_IS_ATTACHMENT_VIEW (view)); + g_return_if_fail (path != NULL); + + iface = E_ATTACHMENT_VIEW_GET_IFACE (view); + g_return_if_fail (iface->unselect_path != NULL); + + iface->unselect_path (view, path); +} + +void +e_attachment_view_select_all (EAttachmentView *view) +{ + EAttachmentViewIface *iface; + + g_return_if_fail (E_IS_ATTACHMENT_VIEW (view)); + + iface = E_ATTACHMENT_VIEW_GET_IFACE (view); + g_return_if_fail (iface->select_all != NULL); + + iface->select_all (view); +} + +void +e_attachment_view_unselect_all (EAttachmentView *view) +{ + EAttachmentViewIface *iface; + + g_return_if_fail (E_IS_ATTACHMENT_VIEW (view)); + + iface = E_ATTACHMENT_VIEW_GET_IFACE (view); + g_return_if_fail (iface->unselect_all != NULL); + + iface->unselect_all (view); +} + +void +e_attachment_view_sync_selection (EAttachmentView *view, + EAttachmentView *target) +{ + GList *selected, *iter; + + g_return_if_fail (E_IS_ATTACHMENT_VIEW (view)); + g_return_if_fail (E_IS_ATTACHMENT_VIEW (target)); + + selected = e_attachment_view_get_selected_paths (view); + e_attachment_view_unselect_all (target); + + for (iter = selected; iter != NULL; iter = iter->next) + e_attachment_view_select_path (target, iter->data); + + g_list_foreach (selected, (GFunc) gtk_tree_path_free, NULL); + g_list_free (selected); +} + +void +e_attachment_view_drag_action (EAttachmentView *view, + GdkDragAction action) +{ + EAttachmentViewPrivate *priv; + GtkSelectionData *selection_data; + EAttachmentStore *store; + GdkAtom atom; + gchar *name; + + g_return_if_fail (E_IS_ATTACHMENT_VIEW (view)); + + priv = e_attachment_view_get_private (view); + + selection_data = priv->selection_data; + store = e_attachment_view_get_store (view); + atom = gtk_selection_data_get_data_type (selection_data); + + switch (priv->info) { + case DND_TYPE_MESSAGE_RFC822: + drop_message_rfc822 ( + view, selection_data, store, action); + return; + + case DND_TYPE_NETSCAPE_URL: + drop_netscape_url ( + view, selection_data, store, action); + return; + + case DND_TYPE_TEXT_URI_LIST: + drop_text_uri_list ( + view, selection_data, store, action); + return; + + case DND_TYPE_TEXT_VCARD: + case DND_TYPE_TEXT_CALENDAR: + drop_text_generic ( + view, selection_data, store, action); + return; + + case DND_TYPE_X_UID_LIST: + drop_x_uid_list ( + view, selection_data, store, action); + return; + + default: + name = gdk_atom_name (atom); + g_warning ("Unknown drag type: %s", name); + g_free (name); + break; + } + + gtk_drag_finish (priv->drag_context, FALSE, FALSE, priv->time); +} + +gboolean +e_attachment_view_drag_motion (EAttachmentView *view, + GdkDragContext *context, + gint x, + gint y, + guint time) +{ + GList *iter; + GdkDragAction actions = 0; + GdkDragAction chosen_action; + + g_return_val_if_fail (E_IS_ATTACHMENT_VIEW (view), FALSE); + + for (iter = context->targets; iter != NULL; iter = iter->next) { + GdkAtom atom = iter->data; + gint ii; + + for (ii = 0; ii < G_N_ELEMENTS (drag_info); ii++) + if (atom == drag_info[ii].atom) + actions |= drag_info[ii].actions; + } + + actions &= context->actions; + chosen_action = context->suggested_action; + + if (chosen_action == GDK_ACTION_ASK) { + GdkDragAction mask; + + mask = GDK_ACTION_COPY | GDK_ACTION_MOVE; + if ((actions & mask) != mask) + chosen_action = GDK_ACTION_COPY; + } + + gdk_drag_status (context, chosen_action, time); + + return (chosen_action != 0); +} + +void +e_attachment_view_drag_data_received (EAttachmentView *view, + GdkDragContext *drag_context, + gint x, + gint y, + GtkSelectionData *selection_data, + guint info, + guint time) +{ + EAttachmentViewPrivate *priv; + GtkUIManager *ui_manager; + GdkDragAction action; + + g_return_if_fail (E_IS_ATTACHMENT_VIEW (view)); + + priv = e_attachment_view_get_private (view); + ui_manager = e_attachment_view_get_ui_manager (view); + + action = drag_context->action; + + if (gtk_selection_data_get_data (selection_data) == NULL) + return; + + if (gtk_selection_data_get_length (selection_data) == -1) + return; + + if (priv->drag_context != NULL) + g_object_unref (priv->drag_context); + + if (priv->selection_data != NULL) + gtk_selection_data_free (priv->selection_data); + + priv->drag_context = g_object_ref (drag_context); + priv->selection_data = gtk_selection_data_copy (selection_data); + priv->info = info; + priv->time = time; + + if (action == GDK_ACTION_ASK) { + GtkWidget *menu; + + menu = gtk_ui_manager_get_widget (ui_manager, "/dnd"); + g_return_if_fail (GTK_IS_MENU (menu)); + + gtk_menu_popup ( + GTK_MENU (menu), NULL, NULL, NULL, NULL, 0, time); + } else + e_attachment_view_drag_action (view, action); +} + +GtkAction * +e_attachment_view_get_action (EAttachmentView *view, + const gchar *action_name) +{ + GtkUIManager *ui_manager; + + g_return_val_if_fail (E_IS_ATTACHMENT_VIEW (view), NULL); + g_return_val_if_fail (action_name != NULL, NULL); + + ui_manager = e_attachment_view_get_ui_manager (view); + + return e_lookup_action (ui_manager, action_name); +} + +GtkActionGroup * +e_attachment_view_get_action_group (EAttachmentView *view, + const gchar *group_name) +{ + GtkUIManager *ui_manager; + + g_return_val_if_fail (E_IS_ATTACHMENT_VIEW (view), NULL); + g_return_val_if_fail (group_name != NULL, NULL); + + ui_manager = e_attachment_view_get_ui_manager (view); + + return e_lookup_action_group (ui_manager, group_name); +} + +GtkUIManager * +e_attachment_view_get_ui_manager (EAttachmentView *view) +{ + EAttachmentViewPrivate *priv; + + g_return_val_if_fail (E_IS_ATTACHMENT_VIEW (view), NULL); + + priv = e_attachment_view_get_private (view); + + return priv->ui_manager; +} + +GtkAction * +e_attachment_view_recent_action_new (EAttachmentView *view, + const gchar *action_name, + const gchar *action_label) +{ + GtkAction *action; + GtkRecentChooser *chooser; + + g_return_val_if_fail (E_IS_ATTACHMENT_VIEW (view), NULL); + g_return_val_if_fail (action_name != NULL, NULL); + + action = gtk_recent_action_new ( + action_name, action_label, NULL, NULL); + gtk_recent_action_set_show_numbers (GTK_RECENT_ACTION (action), TRUE); + + chooser = GTK_RECENT_CHOOSER (action); + gtk_recent_chooser_set_show_icons (chooser, TRUE); + gtk_recent_chooser_set_show_not_found (chooser, FALSE); + gtk_recent_chooser_set_show_private (chooser, FALSE); + gtk_recent_chooser_set_show_tips (chooser, TRUE); + gtk_recent_chooser_set_sort_type (chooser, GTK_RECENT_SORT_MRU); + + g_signal_connect ( + action, "item-activated", + G_CALLBACK (action_recent_cb), view); + + return action; +} + +void +e_attachment_view_show_popup_menu (EAttachmentView *view, + GdkEventButton *event) +{ + GtkUIManager *ui_manager; + GtkWidget *menu; + + g_return_if_fail (E_IS_ATTACHMENT_VIEW (view)); + + if (event != NULL) { + GtkTreePath *path; + + path = e_attachment_view_get_path_at_pos ( + view, event->x, event->y); + if (path != NULL) { + if (!e_attachment_view_path_is_selected (view, path)) { + e_attachment_view_unselect_all (view); + e_attachment_view_select_path (view, path); + } + gtk_tree_path_free (path); + } else + e_attachment_view_unselect_all (view); + } + + e_attachment_view_update_actions (view); + + ui_manager = e_attachment_view_get_ui_manager (view); + menu = gtk_ui_manager_get_widget (ui_manager, "/context"); + g_return_if_fail (GTK_IS_MENU (menu)); + + if (event != NULL) + gtk_menu_popup ( + GTK_MENU (menu), NULL, NULL, NULL, NULL, + event->button, event->time); + else + gtk_menu_popup ( + GTK_MENU (menu), NULL, NULL, NULL, NULL, + 0, gtk_get_current_event_time ()); +} + +void +e_attachment_view_update_actions (EAttachmentView *view) +{ + EAttachmentViewPrivate *priv; + GFileInfo *file_info; + GtkAction *action; + GList *selected; + guint n_selected; + gboolean is_image; + + g_return_if_fail (E_IS_ATTACHMENT_VIEW (view)); + + priv = e_attachment_view_get_private (view); + selected = e_attachment_view_get_selected_attachments (view); + n_selected = g_list_length (selected); + + is_image = FALSE; + file_info = NULL; + + if (n_selected == 1) { + EAttachment *attachment = selected->data; + file_info = e_attachment_get_file_info (attachment); + is_image = e_attachment_is_image (attachment); + } + + action = e_attachment_view_get_action (view, "properties"); + gtk_action_set_visible (action, n_selected == 1); + + action = e_attachment_view_get_action (view, "remove"); + gtk_action_set_visible (action, n_selected > 0); + + action = e_attachment_view_get_action (view, "save-as"); + gtk_action_set_visible (action, n_selected > 0); + + action = e_attachment_view_get_action (view, "set-background"); + gtk_action_set_visible (action, is_image); +} |