enable ask drop action and hook onto drag motion. (drag_motion):

2004-10-01  Not Zed  <NotZed@Ximian.com>

        * 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
This commit is contained in:
Not Zed
2004-10-01 03:45:33 +00:00
committed by Michael Zucci
parent 0086ffe2da
commit 985ea02bdb
2 changed files with 169 additions and 10 deletions
+10
View File
@@ -1,3 +1,13 @@
2004-10-01 Not Zed <NotZed@Ximian.com>
* 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 <kmaraas@gnome.org>
* e-msg-composer.c: (autosave_manager_start),
+159 -10
View File
@@ -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;i<sizeof(drop_popup_menu)/sizeof(drop_popup_menu[0]);i++)
menus = g_slist_append(menus, &drop_popup_menu[i]);
e_popup_add_items((EPopup *)emp, menus, drop_popup_free, m);
menu = e_popup_create_menu_once((EPopup *)emp, NULL, 0, 0);
gtk_menu_popup(menu, NULL, NULL, NULL, NULL, 0, time);
} else {
drop_action(composer, context, context->action, 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;i<sizeof(drag_info)/sizeof(drag_info[0]);i++)
if (targets->data == (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<sizeof(drag_info)/sizeof(drag_info[0]);i++)
drag_info[i].atom = gdk_atom_intern(drag_info[i].target, FALSE);
gobject_class = G_OBJECT_CLASS(klass);
object_class = GTK_OBJECT_CLASS (klass);
@@ -3178,10 +3328,9 @@ create_composer (int visible_mask)
}
/* DND support */
gtk_drag_dest_set (GTK_WIDGET (composer), GTK_DEST_DEFAULT_ALL,
drop_types, num_drop_types, GDK_ACTION_COPY);
g_signal_connect (composer, "drag_data_received",
G_CALLBACK (drag_data_received), NULL);
gtk_drag_dest_set (GTK_WIDGET (composer), GTK_DEST_DEFAULT_ALL, drop_types, num_drop_types, GDK_ACTION_COPY|GDK_ACTION_ASK|GDK_ACTION_MOVE);
g_signal_connect(composer, "drag_data_received", G_CALLBACK (drag_data_received), NULL);
g_signal_connect(composer, "drag-motion", G_CALLBACK(drag_motion), composer);
e_msg_composer_load_config (composer, visible_mask);
setup_ui (composer);