aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMatthew Barnes <mbarnes@redhat.com>2010-08-13 20:09:37 +0800
committerMatthew Barnes <mbarnes@redhat.com>2010-08-13 20:09:37 +0800
commit4032075425d7251642e3f81b9c4732e9a2a23e85 (patch)
treec22289096822a953f7a25892500f512b247c7639
parent6caf022926a6dc7ae0a84e514510def0de87109a (diff)
downloadgsoc2013-evolution-4032075425d7251642e3f81b9c4732e9a2a23e85.tar
gsoc2013-evolution-4032075425d7251642e3f81b9c4732e9a2a23e85.tar.gz
gsoc2013-evolution-4032075425d7251642e3f81b9c4732e9a2a23e85.tar.bz2
gsoc2013-evolution-4032075425d7251642e3f81b9c4732e9a2a23e85.tar.lz
gsoc2013-evolution-4032075425d7251642e3f81b9c4732e9a2a23e85.tar.xz
gsoc2013-evolution-4032075425d7251642e3f81b9c4732e9a2a23e85.tar.zst
gsoc2013-evolution-4032075425d7251642e3f81b9c4732e9a2a23e85.zip
Bug 624913 - Disallow drag-and-drop within the same attachment bar
Adds a boolean "dragging" property to the EAttachmentView interface, which becomes TRUE when the user start a drag from the attachment view. e_attachment_view_drag_motion() and e_attachment_view_drag_drop() both return FALSE when this property is set. Also, do not register the entire EMsgComposer window as a drag destination. Just intercept drag signals from the GtkHTML widget. Requires gtkhtml commit 344eb5e to fully work correctly.
-rw-r--r--composer/e-msg-composer.c126
-rw-r--r--mail/e-mail-attachment-bar.c25
-rw-r--r--widgets/misc/e-attachment-icon-view.c16
-rw-r--r--widgets/misc/e-attachment-paned.c24
-rw-r--r--widgets/misc/e-attachment-tree-view.c16
-rw-r--r--widgets/misc/e-attachment-view.c55
-rw-r--r--widgets/misc/e-attachment-view.h4
7 files changed, 178 insertions, 88 deletions
diff --git a/composer/e-msg-composer.c b/composer/e-msg-composer.c
index 11c20e2adc..e56bab9362 100644
--- a/composer/e-msg-composer.c
+++ b/composer/e-msg-composer.c
@@ -113,14 +113,6 @@ static void handle_multipart_signed (EMsgComposer *composer,
CamelMultipart *multipart,
gint depth);
-static void msg_composer_drag_data_received (GtkWidget *widget,
- GdkDragContext *context,
- gint x,
- gint y,
- GtkSelectionData *selection,
- guint info,
- guint time);
-
/**
* emcu_part_to_html:
* @part:
@@ -1663,17 +1655,49 @@ msg_composer_realize_gtkhtml_cb (GtkWidget *widget,
gtk_target_table_free (targets, n_targets);
}
-struct _drop_data {
- EMsgComposer *composer;
+static gboolean
+msg_composer_drag_motion_cb (GtkWidget *widget,
+ GdkDragContext *context,
+ gint x,
+ gint y,
+ guint time,
+ EMsgComposer *composer)
+{
+ EAttachmentView *view;
- GdkDragContext *context;
- /* Only selection->data and selection->length are valid */
- GtkSelectionData *selection;
+ view = e_msg_composer_get_attachment_view (composer);
- guint32 action;
- guint info;
- guint time;
-};
+ /* Stop the signal from propagating to GtkHtml. */
+ g_signal_stop_emission_by_name (widget, "drag-motion");
+
+ return e_attachment_view_drag_motion (view, context, x, y, time);
+}
+
+static void
+msg_composer_drag_data_received_cb (GtkWidget *widget,
+ GdkDragContext *context,
+ gint x,
+ gint y,
+ GtkSelectionData *selection,
+ guint info,
+ guint time,
+ EMsgComposer *composer)
+{
+ EAttachmentView *view;
+
+ view = e_msg_composer_get_attachment_view (composer);
+
+ /* Forward the data to the attachment view. Note that calling
+ * e_attachment_view_drag_data_received() will not work because
+ * that function only handles the case where all the other drag
+ * handlers have failed. */
+ e_attachment_paned_drag_data_received (
+ E_ATTACHMENT_PANED (view),
+ context, x, y, selection, info, time);
+
+ /* Stop the signal from propagating to GtkHtml. */
+ g_signal_stop_emission_by_name (widget, "drag-data-received");
+}
static void
msg_composer_notify_header_cb (EMsgComposer *composer)
@@ -1792,9 +1816,6 @@ msg_composer_constructed (GObject *object)
EAttachmentView *view;
EAttachmentStore *store;
EComposerHeaderTable *table;
- GdkDragAction drag_actions;
- GtkTargetList *target_list;
- GtkTargetEntry *targets;
GtkUIManager *ui_manager;
GtkToggleAction *action;
GtkHTML *html;
@@ -1802,7 +1823,6 @@ msg_composer_constructed (GObject *object)
const gchar *id;
gboolean active;
guint binding_id;
- gint n_targets;
editor = GTKHTML_EDITOR (object);
composer = E_MSG_COMPOSER (object);
@@ -1863,24 +1883,17 @@ msg_composer_constructed (GObject *object)
/* Drag-and-Drop Support */
- target_list = e_attachment_view_get_target_list (view);
- drag_actions = e_attachment_view_get_drag_actions (view);
-
- targets = gtk_target_table_new_from_list (target_list, &n_targets);
-
- gtk_drag_dest_set (
- GTK_WIDGET (composer), GTK_DEST_DEFAULT_ALL,
- targets, n_targets, drag_actions);
-
g_signal_connect (
html, "realize",
G_CALLBACK (msg_composer_realize_gtkhtml_cb), composer);
g_signal_connect (
- html, "drag-data-received",
- G_CALLBACK (msg_composer_drag_data_received), NULL);
+ html, "drag-motion",
+ G_CALLBACK (msg_composer_drag_motion_cb), composer);
- gtk_target_table_free (targets, n_targets);
+ g_signal_connect (
+ html, "drag-data-received",
+ G_CALLBACK (msg_composer_drag_data_received_cb), composer);
/* Configure Headers */
@@ -2040,51 +2053,6 @@ msg_composer_key_press_event (GtkWidget *widget,
return GTK_WIDGET_CLASS (parent_class)->key_press_event (widget, event);
}
-static gboolean
-msg_composer_drag_motion (GtkWidget *widget,
- GdkDragContext *context,
- gint x,
- gint y,
- guint time)
-{
- EMsgComposer *composer;
- EAttachmentView *view;
-
- /* Widget may be EMsgComposer or GtkHTML. */
- composer = E_MSG_COMPOSER (gtk_widget_get_toplevel (widget));
- view = e_msg_composer_get_attachment_view (composer);
-
- return e_attachment_view_drag_motion (view, context, x, y, time);
-}
-
-static void
-msg_composer_drag_data_received (GtkWidget *widget,
- GdkDragContext *context,
- gint x,
- gint y,
- GtkSelectionData *selection,
- guint info,
- guint time)
-{
- EMsgComposer *composer;
- EAttachmentView *view;
-
- /* Widget may be EMsgComposer or GtkHTML. */
- composer = E_MSG_COMPOSER (gtk_widget_get_toplevel (widget));
- view = e_msg_composer_get_attachment_view (composer);
-
- /* Forward the data to the attachment view. Note that calling
- * e_attachment_view_drag_data_received() will not work because
- * that function only handles the case where all the other drag
- * handlers have failed. */
- e_attachment_paned_drag_data_received (
- E_ATTACHMENT_PANED (view),
- context, x, y, selection, info, time);
-
- /* Stop the signal from propagating to GtkHtml. */
- g_signal_stop_emission_by_name (widget, "drag-data-received");
-}
-
static void
msg_composer_cut_clipboard (GtkhtmlEditor *editor)
{
@@ -2281,8 +2249,6 @@ msg_composer_class_init (EMsgComposerClass *class)
widget_class = GTK_WIDGET_CLASS (class);
widget_class->map = msg_composer_map;
widget_class->key_press_event = msg_composer_key_press_event;
- widget_class->drag_motion = msg_composer_drag_motion;
- widget_class->drag_data_received = msg_composer_drag_data_received;
editor_class = GTKHTML_EDITOR_CLASS (class);
editor_class->cut_clipboard = msg_composer_cut_clipboard;
diff --git a/mail/e-mail-attachment-bar.c b/mail/e-mail-attachment-bar.c
index c791b5fba3..b5a82dbcc1 100644
--- a/mail/e-mail-attachment-bar.c
+++ b/mail/e-mail-attachment-bar.c
@@ -57,6 +57,7 @@ struct _EMailAttachmentBarPrivate {
enum {
PROP_0,
PROP_ACTIVE_VIEW,
+ PROP_DRAGGING,
PROP_EDITABLE,
PROP_EXPANDED
};
@@ -120,6 +121,12 @@ mail_attachment_bar_set_property (GObject *object,
g_value_get_int (value));
return;
+ case PROP_DRAGGING:
+ e_attachment_view_set_dragging (
+ E_ATTACHMENT_VIEW (object),
+ g_value_get_boolean (value));
+ return;
+
case PROP_EDITABLE:
e_attachment_view_set_editable (
E_ATTACHMENT_VIEW (object),
@@ -150,6 +157,13 @@ mail_attachment_bar_get_property (GObject *object,
E_MAIL_ATTACHMENT_BAR (object)));
return;
+ case PROP_DRAGGING:
+ g_value_set_boolean (
+ value,
+ e_attachment_view_get_dragging (
+ E_ATTACHMENT_VIEW (object)));
+ return;
+
case PROP_EDITABLE:
g_value_set_boolean (
value,
@@ -257,6 +271,14 @@ mail_attachment_bar_constructed (GObject *object)
priv->combo_box, "active");
e_mutual_binding_new (
+ object, "dragging",
+ priv->icon_view, "dragging");
+
+ e_mutual_binding_new (
+ object, "dragging",
+ priv->tree_view, "dragging");
+
+ e_mutual_binding_new (
object, "editable",
priv->icon_view, "editable");
@@ -460,6 +482,9 @@ mail_attachment_bar_class_init (EMailAttachmentBarClass *class)
G_PARAM_CONSTRUCT));
g_object_class_override_property (
+ object_class, PROP_DRAGGING, "dragging");
+
+ g_object_class_override_property (
object_class, PROP_EDITABLE, "editable");
}
diff --git a/widgets/misc/e-attachment-icon-view.c b/widgets/misc/e-attachment-icon-view.c
index 57301213dd..35b5d1ed18 100644
--- a/widgets/misc/e-attachment-icon-view.c
+++ b/widgets/misc/e-attachment-icon-view.c
@@ -37,6 +37,7 @@ struct _EAttachmentIconViewPrivate {
enum {
PROP_0,
+ PROP_DRAGGING,
PROP_EDITABLE
};
@@ -56,6 +57,12 @@ attachment_icon_view_set_property (GObject *object,
GParamSpec *pspec)
{
switch (property_id) {
+ case PROP_DRAGGING:
+ e_attachment_view_set_dragging (
+ E_ATTACHMENT_VIEW (object),
+ g_value_get_boolean (value));
+ return;
+
case PROP_EDITABLE:
e_attachment_view_set_editable (
E_ATTACHMENT_VIEW (object),
@@ -73,6 +80,12 @@ attachment_icon_view_get_property (GObject *object,
GParamSpec *pspec)
{
switch (property_id) {
+ case PROP_DRAGGING:
+ g_value_set_boolean (
+ value, e_attachment_view_get_dragging (
+ E_ATTACHMENT_VIEW (object)));
+ return;
+
case PROP_EDITABLE:
g_value_set_boolean (
value, e_attachment_view_get_editable (
@@ -436,6 +449,9 @@ attachment_icon_view_class_init (EAttachmentIconViewClass *class)
icon_view_class->item_activated = attachment_icon_view_item_activated;
g_object_class_override_property (
+ object_class, PROP_DRAGGING, "dragging");
+
+ g_object_class_override_property (
object_class, PROP_EDITABLE, "editable");
}
diff --git a/widgets/misc/e-attachment-paned.c b/widgets/misc/e-attachment-paned.c
index 83a00692d8..64d97ab81f 100644
--- a/widgets/misc/e-attachment-paned.c
+++ b/widgets/misc/e-attachment-paned.c
@@ -60,6 +60,7 @@ struct _EAttachmentPanedPrivate {
enum {
PROP_0,
PROP_ACTIVE_VIEW,
+ PROP_DRAGGING,
PROP_EDITABLE,
PROP_EXPANDED
};
@@ -150,6 +151,12 @@ attachment_paned_set_property (GObject *object,
g_value_get_int (value));
return;
+ case PROP_DRAGGING:
+ e_attachment_view_set_dragging (
+ E_ATTACHMENT_VIEW (object),
+ g_value_get_boolean (value));
+ return;
+
case PROP_EDITABLE:
e_attachment_view_set_editable (
E_ATTACHMENT_VIEW (object),
@@ -179,6 +186,12 @@ attachment_paned_get_property (GObject *object,
E_ATTACHMENT_PANED (object)));
return;
+ case PROP_DRAGGING:
+ g_value_set_boolean (
+ value, e_attachment_view_get_dragging (
+ E_ATTACHMENT_VIEW (object)));
+ return;
+
case PROP_EDITABLE:
g_value_set_boolean (
value, e_attachment_view_get_editable (
@@ -278,6 +291,14 @@ attachment_paned_constructed (GObject *object)
priv->notebook, "page");
e_mutual_binding_new (
+ object, "dragging",
+ priv->icon_view, "dragging");
+
+ e_mutual_binding_new (
+ object, "dragging",
+ priv->tree_view, "dragging");
+
+ e_mutual_binding_new (
object, "editable",
priv->icon_view, "editable");
@@ -457,6 +478,9 @@ attachment_paned_class_init (EAttachmentPanedClass *class)
G_PARAM_CONSTRUCT));
g_object_class_override_property (
+ object_class, PROP_DRAGGING, "dragging");
+
+ g_object_class_override_property (
object_class, PROP_EDITABLE, "editable");
}
diff --git a/widgets/misc/e-attachment-tree-view.c b/widgets/misc/e-attachment-tree-view.c
index 09602ca186..8e597adebb 100644
--- a/widgets/misc/e-attachment-tree-view.c
+++ b/widgets/misc/e-attachment-tree-view.c
@@ -37,6 +37,7 @@ struct _EAttachmentTreeViewPrivate {
enum {
PROP_0,
+ PROP_DRAGGING,
PROP_EDITABLE
};
@@ -49,6 +50,12 @@ attachment_tree_view_set_property (GObject *object,
GParamSpec *pspec)
{
switch (property_id) {
+ case PROP_DRAGGING:
+ e_attachment_view_set_dragging (
+ E_ATTACHMENT_VIEW (object),
+ g_value_get_boolean (value));
+ return;
+
case PROP_EDITABLE:
e_attachment_view_set_editable (
E_ATTACHMENT_VIEW (object),
@@ -66,6 +73,12 @@ attachment_tree_view_get_property (GObject *object,
GParamSpec *pspec)
{
switch (property_id) {
+ case PROP_DRAGGING:
+ g_value_set_boolean (
+ value, e_attachment_view_get_dragging (
+ E_ATTACHMENT_VIEW (object)));
+ return;
+
case PROP_EDITABLE:
g_value_set_boolean (
value, e_attachment_view_get_editable (
@@ -468,6 +481,9 @@ attachment_tree_view_class_init (EAttachmentTreeViewClass *class)
tree_view_class->row_activated = attachment_tree_view_row_activated;
g_object_class_override_property (
+ object_class, PROP_DRAGGING, "dragging");
+
+ g_object_class_override_property (
object_class, PROP_EDITABLE, "editable");
}
diff --git a/widgets/misc/e-attachment-view.c b/widgets/misc/e-attachment-view.c
index 60ce09860d..cc587bf80b 100644
--- a/widgets/misc/e-attachment-view.c
+++ b/widgets/misc/e-attachment-view.c
@@ -824,6 +824,15 @@ attachment_view_class_init (EAttachmentViewIface *iface)
g_object_interface_install_property (
iface,
g_param_spec_boolean (
+ "dragging",
+ "Dragging",
+ NULL,
+ FALSE,
+ G_PARAM_READWRITE));
+
+ g_object_interface_install_property (
+ iface,
+ g_param_spec_boolean (
"editable",
"Editable",
NULL,
@@ -1025,6 +1034,7 @@ e_attachment_view_set_editable (EAttachmentView *view,
g_return_if_fail (E_IS_ATTACHMENT_VIEW (view));
priv = e_attachment_view_get_private (view);
+
priv->editable = editable;
if (editable)
@@ -1035,6 +1045,33 @@ e_attachment_view_set_editable (EAttachmentView *view,
g_object_notify (G_OBJECT (view), "editable");
}
+gboolean
+e_attachment_view_get_dragging (EAttachmentView *view)
+{
+ EAttachmentViewPrivate *priv;
+
+ g_return_val_if_fail (E_IS_ATTACHMENT_VIEW (view), FALSE);
+
+ priv = e_attachment_view_get_private (view);
+
+ return priv->dragging;
+}
+
+void
+e_attachment_view_set_dragging (EAttachmentView *view,
+ gboolean dragging)
+{
+ EAttachmentViewPrivate *priv;
+
+ g_return_if_fail (E_IS_ATTACHMENT_VIEW (view));
+
+ priv = e_attachment_view_get_private (view);
+
+ priv->dragging = dragging;
+
+ g_object_notify (G_OBJECT (view), "dragging");
+}
+
GtkTargetList *
e_attachment_view_get_target_list (EAttachmentView *view)
{
@@ -1507,10 +1544,7 @@ e_attachment_view_drag_begin (EAttachmentView *view,
priv = e_attachment_view_get_private (view);
- /* Prevent the user from dragging and dropping to
- * the same attachment view, which would duplicate
- * the attachment. */
- e_attachment_view_drag_dest_unset (view);
+ e_attachment_view_set_dragging (view, TRUE);
g_warn_if_fail (priv->selected == NULL);
priv->selected = e_attachment_view_get_selected_attachments (view);
@@ -1569,9 +1603,7 @@ e_attachment_view_drag_end (EAttachmentView *view,
priv = e_attachment_view_get_private (view);
- /* Restore the previous drag destination state. */
- if (e_attachment_view_get_editable (view))
- e_attachment_view_drag_dest_set (view);
+ e_attachment_view_set_dragging (view, FALSE);
g_list_foreach (priv->selected, (GFunc) g_object_unref, NULL);
g_list_free (priv->selected);
@@ -1698,6 +1730,11 @@ e_attachment_view_drag_motion (EAttachmentView *view,
if (!e_attachment_view_get_editable (view))
return FALSE;
+ /* Disallow drops if we initiated the drag.
+ * This helps prevent duplicate attachments. */
+ if (e_attachment_view_get_dragging (view))
+ return FALSE;
+
actions = gdk_drag_context_get_actions (context);
actions &= priv->drag_actions;
chosen_action = gdk_drag_context_get_suggested_action (context);
@@ -1725,7 +1762,9 @@ e_attachment_view_drag_drop (EAttachmentView *view,
g_return_val_if_fail (E_IS_ATTACHMENT_VIEW (view), FALSE);
g_return_val_if_fail (GDK_IS_DRAG_CONTEXT (context), FALSE);
- return TRUE;
+ /* Disallow drops if we initiated the drag.
+ * This helps prevent duplicate attachments. */
+ return !e_attachment_view_get_dragging (view);
}
void
diff --git a/widgets/misc/e-attachment-view.h b/widgets/misc/e-attachment-view.h
index 071de0705a..79dbacb151 100644
--- a/widgets/misc/e-attachment-view.h
+++ b/widgets/misc/e-attachment-view.h
@@ -109,6 +109,7 @@ struct _EAttachmentViewPrivate {
gint start_x;
gint start_y;
+ guint dragging : 1;
guint editable : 1;
};
@@ -122,6 +123,9 @@ EAttachmentViewPrivate *
e_attachment_view_get_private (EAttachmentView *view);
EAttachmentStore *
e_attachment_view_get_store (EAttachmentView *view);
+gboolean e_attachment_view_get_dragging (EAttachmentView *view);
+void e_attachment_view_set_dragging (EAttachmentView *view,
+ gboolean dragging);
gboolean e_attachment_view_get_editable (EAttachmentView *view);
void e_attachment_view_set_editable (EAttachmentView *view,
gboolean editable);