From 985ea02bdba960ab49e4992cd86d2827548c41cf Mon Sep 17 00:00:00 2001 From: Not Zed Date: Fri, 1 Oct 2004 03:45:33 +0000 Subject: enable ask drop action and hook onto drag motion. (drag_motion): 2004-10-01 Not Zed * e-msg-composer.c (create_composer): enable ask drop action and hook onto drag motion. (drag_motion): implement. (drop_action): do the work here now. (drag_data_received): popup a menu if the action is ask. (drop_popup_copy, drop_popup_move, drop_popup_cancel): (drop_popup_free): Popup callbacks. svn path=/trunk/; revision=27441 --- composer/ChangeLog | 10 +++ composer/e-msg-composer.c | 169 +++++++++++++++++++++++++++++++++++++++++++--- 2 files changed, 169 insertions(+), 10 deletions(-) diff --git a/composer/ChangeLog b/composer/ChangeLog index 0815dbe397..a6649e0df6 100644 --- a/composer/ChangeLog +++ b/composer/ChangeLog @@ -1,3 +1,13 @@ +2004-10-01 Not Zed + + * e-msg-composer.c (create_composer): enable ask drop action and + hook onto drag motion. + (drag_motion): implement. + (drop_action): do the work here now. + (drag_data_received): popup a menu if the action is ask. + (drop_popup_copy, drop_popup_move, drop_popup_cancel): + (drop_popup_free): Popup callbacks. + 2004-09-30 Kjartan Maraas * e-msg-composer.c: (autosave_manager_start), diff --git a/composer/e-msg-composer.c b/composer/e-msg-composer.c index 67b3ea8f1c..e80b222f3b 100644 --- a/composer/e-msg-composer.c +++ b/composer/e-msg-composer.c @@ -117,6 +117,7 @@ #include "mail/mail-ops.h" #include "mail/mail-mt.h" #include "mail/mail-session.h" +#include "mail/em-popup.h" #include "e-msg-composer.h" #include "e-msg-composer-attachment-bar.h" @@ -161,6 +162,19 @@ static GtkTargetEntry drop_types[] = { #define num_drop_types (sizeof (drop_types) / sizeof (drop_types[0])) +static struct { + char *target; + GdkAtom atom; + guint32 actions; +} drag_info[] = { + { "message/rfc822", 0, GDK_ACTION_COPY }, + { "x-uid-list", 0, GDK_ACTION_ASK|GDK_ACTION_MOVE|GDK_ACTION_COPY }, + { "text/uri-list", 0, GDK_ACTION_COPY }, + { "_NETSCAPE_URL", 0, GDK_ACTION_COPY }, + { "text/x-vcard", 0, GDK_ACTION_COPY }, + { "text/calendar", 0, GDK_ACTION_COPY }, +}; + static const char *emc_draft_format_names[] = { "pgp-sign", "pgp-encrypt", "smime-sign", "smime-encrypt" }; @@ -2645,10 +2659,24 @@ attach_message(EMsgComposer *composer, CamelMimeMessage *msg) camel_object_unref(mime_part); } +struct _drop_data { + EMsgComposer *composer; + + GdkDragContext *context; + /* Only selection->data and selection->length are valid */ + GtkSelectionData *selection; + + guint32 action; + guint info; + guint time; + + unsigned int move:1; + unsigned int moved:1; + unsigned int aborted:1; +}; + static void -drag_data_received (EMsgComposer *composer, GdkDragContext *context, - int x, int y, GtkSelectionData *selection, - guint info, guint time) +drop_action(EMsgComposer *composer, GdkDragContext *context, guint32 action, GtkSelectionData *selection, guint info, guint time) { char *tmp, *str, **urls; CamelMimePart *mime_part; @@ -2656,8 +2684,8 @@ drag_data_received (EMsgComposer *composer, GdkDragContext *context, CamelURL *url; CamelMimeMessage *msg; char *content_type; - int i; - + int i, success=FALSE, delete=FALSE; + switch (info) { case DND_TYPE_MESSAGE_RFC822: d(printf ("dropping a message/rfc822\n")); @@ -2667,8 +2695,11 @@ drag_data_received (EMsgComposer *composer, GdkDragContext *context, camel_stream_reset (stream); msg = camel_mime_message_new (); - if (camel_data_wrapper_construct_from_stream((CamelDataWrapper *)msg, stream) != -1) + if (camel_data_wrapper_construct_from_stream((CamelDataWrapper *)msg, stream) != -1) { attach_message(composer, msg); + success = TRUE; + delete = action == GDK_ACTION_MOVE; + } camel_object_unref(msg); camel_object_unref(stream); @@ -2707,6 +2738,7 @@ drag_data_received (EMsgComposer *composer, GdkDragContext *context, } g_free (urls); + success = TRUE; break; case DND_TYPE_TEXT_VCARD: case DND_TYPE_TEXT_CALENDAR: @@ -2724,6 +2756,7 @@ drag_data_received (EMsgComposer *composer, GdkDragContext *context, camel_object_unref (mime_part); g_free (content_type); + success = TRUE; break; case DND_TYPE_X_UID_LIST: { GPtrArray *uids; @@ -2788,6 +2821,8 @@ drag_data_received (EMsgComposer *composer, GdkDragContext *context, camel_object_unref(mime_part); camel_object_unref(mp); } + success = TRUE; + delete = action == GDK_ACTION_MOVE; fail: if (camel_exception_is_set(&ex)) { char *name; @@ -2813,6 +2848,117 @@ drag_data_received (EMsgComposer *composer, GdkDragContext *context, d(printf ("dropping an unknown\n")); break; } + + printf("Drag finished, success %d delete %d\n", success, delete); + + gtk_drag_finish(context, success, delete, time); +} + +static void +drop_popup_copy(EPopup *ep, EPopupItem *item, void *data) +{ + struct _drop_data *m = data; + drop_action(m->composer, m->context, GDK_ACTION_COPY, m->selection, m->info, m->time); +} + +static void +drop_popup_move(EPopup *ep, EPopupItem *item, void *data) +{ + struct _drop_data *m = data; + drop_action(m->composer, m->context, GDK_ACTION_MOVE, m->selection, m->info, m->time); +} + +static void +drop_popup_cancel(EPopup *ep, EPopupItem *item, void *data) +{ + struct _drop_data *m = data; + gtk_drag_finish(m->context, FALSE, FALSE, m->time); +} + +static EPopupItem drop_popup_menu[] = { + { E_POPUP_ITEM, "00.emc.02", N_("_Copy"), drop_popup_copy, NULL, "stock_mail-copy", 0 }, + { E_POPUP_ITEM, "00.emc.03", N_("_Move"), drop_popup_move, NULL, "stock_mail-move", 0 }, + { E_POPUP_BAR, "10.emc" }, + { E_POPUP_ITEM, "99.emc.00", N_("Cancel _Drag"), drop_popup_cancel, NULL, NULL, 0 }, +}; + +static void +drop_popup_free(EPopup *ep, GSList *items, void *data) +{ + struct _drop_data *m = data; + + g_slist_free(items); + + g_object_unref(m->context); + g_object_unref(m->composer); + g_free(m->selection->data); + g_free(m->selection); + g_free(m); +} + +static void +drag_data_received (EMsgComposer *composer, GdkDragContext *context, + int x, int y, GtkSelectionData *selection, + guint info, guint time) +{ + if (selection->data == NULL || selection->length == -1) + return; + + if (context->action == GDK_ACTION_ASK) { + EMPopup *emp; + GSList *menus = NULL; + GtkMenu *menu; + int i; + struct _drop_data *m; + + m = g_malloc0(sizeof(*m)); + m->context = context; + g_object_ref(context); + m->composer = composer; + g_object_ref(composer); + m->action = context->action; + m->info = info; + m->time = time; + m->selection = g_malloc0(sizeof(*m->selection)); + m->selection->data = g_malloc(selection->length); + memcpy(m->selection->data, selection->data, selection->length); + m->selection->length = selection->length; + + emp = em_popup_new("com.ximian.mail.composer.popup.drop"); + for (i=0;iaction, selection, info, time); + } +} + +static gboolean +drag_motion(GObject *o, GdkDragContext *context, gint x, gint y, guint time, EMsgComposer *composer) +{ + GList *targets; + GdkDragAction action, actions = 0; + + for (targets = context->targets; targets; targets = targets->next) { + int i; + + for (i=0;idata == (void *)drag_info[i].atom) + actions |= drag_info[i].actions; + } + + actions &= context->actions; + action = context->suggested_action; + /* we default to copy */ + if (action == GDK_ACTION_ASK && (actions & (GDK_ACTION_MOVE|GDK_ACTION_COPY)) != (GDK_ACTION_MOVE|GDK_ACTION_COPY)) + action = GDK_ACTION_COPY; + + gdk_drag_status(context, action, time); + + return action != 0; } static void @@ -2821,6 +2967,10 @@ class_init (EMsgComposerClass *klass) GtkObjectClass *object_class; GtkWidgetClass *widget_class; GObjectClass *gobject_class; + int i; + + for (i=0;i