diff options
author | Matthew Barnes <mbarnes@redhat.com> | 2010-05-25 21:14:51 +0800 |
---|---|---|
committer | Matthew Barnes <mbarnes@redhat.com> | 2010-05-25 21:14:51 +0800 |
commit | f49077cfb57ade9013674487a1f371da7c038709 (patch) | |
tree | 58ebabbe624409eed22ed13578eab3ed2d4d0206 /widgets | |
parent | d3c7420fb977fe5c337f2c917839a6e982a47902 (diff) | |
parent | 9fb0290d914e63512f6e3fc719b6b0249d787656 (diff) | |
download | gsoc2013-evolution-f49077cfb57ade9013674487a1f371da7c038709.tar.gz gsoc2013-evolution-f49077cfb57ade9013674487a1f371da7c038709.tar.zst gsoc2013-evolution-f49077cfb57ade9013674487a1f371da7c038709.zip |
Merge branch 'gnome-2-30' into express2
Diffstat (limited to 'widgets')
-rw-r--r-- | widgets/misc/e-attachment-icon-view.c | 15 | ||||
-rw-r--r-- | widgets/misc/e-attachment-paned.c | 62 | ||||
-rw-r--r-- | widgets/misc/e-attachment-tree-view.c | 15 | ||||
-rw-r--r-- | widgets/misc/e-attachment-view.c | 196 | ||||
-rw-r--r-- | widgets/misc/e-attachment-view.h | 9 |
5 files changed, 212 insertions, 85 deletions
diff --git a/widgets/misc/e-attachment-icon-view.c b/widgets/misc/e-attachment-icon-view.c index edfecb57d8..57301213dd 100644 --- a/widgets/misc/e-attachment-icon-view.c +++ b/widgets/misc/e-attachment-icon-view.c @@ -130,6 +130,20 @@ attachment_icon_view_button_release_event (GtkWidget *widget, } static gboolean +attachment_icon_view_motion_notify_event (GtkWidget *widget, + GdkEventMotion *event) +{ + EAttachmentView *view = E_ATTACHMENT_VIEW (widget); + + if (e_attachment_view_motion_notify_event (view, event)) + return TRUE; + + /* Chain up to parent's motion_notify_event() method. */ + return GTK_WIDGET_CLASS (parent_class)-> + motion_notify_event (widget, event); +} + +static gboolean attachment_icon_view_key_press_event (GtkWidget *widget, GdkEventKey *event) { @@ -408,6 +422,7 @@ attachment_icon_view_class_init (EAttachmentIconViewClass *class) widget_class = GTK_WIDGET_CLASS (class); widget_class->button_press_event = attachment_icon_view_button_press_event; widget_class->button_release_event = attachment_icon_view_button_release_event; + widget_class->motion_notify_event = attachment_icon_view_motion_notify_event; widget_class->key_press_event = attachment_icon_view_key_press_event; widget_class->drag_begin = attachment_icon_view_drag_begin; widget_class->drag_end = attachment_icon_view_drag_end; diff --git a/widgets/misc/e-attachment-paned.c b/widgets/misc/e-attachment-paned.c index 8b4c2bfb96..d47fe9c8c7 100644 --- a/widgets/misc/e-attachment-paned.c +++ b/widgets/misc/e-attachment-paned.c @@ -92,36 +92,6 @@ attachment_paned_notify_cb (EAttachmentPaned *paned, } static void -attachment_paned_sync_icon_view (EAttachmentPaned *paned) -{ - EAttachmentView *source; - EAttachmentView *target; - - source = E_ATTACHMENT_VIEW (paned->priv->tree_view); - target = E_ATTACHMENT_VIEW (paned->priv->icon_view); - - /* Only sync if the tree view is active. This prevents the - * two views from endlessly trying to sync with each other. */ - if (e_attachment_paned_get_active_view (paned) == 1) - e_attachment_view_sync_selection (source, target); -} - -static void -attachment_paned_sync_tree_view (EAttachmentPaned *paned) -{ - EAttachmentView *source; - EAttachmentView *target; - - source = E_ATTACHMENT_VIEW (paned->priv->icon_view); - target = E_ATTACHMENT_VIEW (paned->priv->tree_view); - - /* Only sync if the icon view is active. This prevents the - * two views from endlessly trying to sync with each other. */ - if (e_attachment_paned_get_active_view (paned) == 0) - e_attachment_view_sync_selection (source, target); -} - -static void attachment_paned_update_status (EAttachmentPaned *paned) { EAttachmentView *view; @@ -509,7 +479,6 @@ static void attachment_paned_init (EAttachmentPaned *paned) { EAttachmentView *view; - GtkTreeSelection *selection; GtkSizeGroup *size_group; GtkWidget *container; GtkWidget *widget; @@ -662,17 +631,6 @@ attachment_paned_init (EAttachmentPaned *paned) paned->priv->status_label = g_object_ref (widget); gtk_widget_hide (widget); - selection = gtk_tree_view_get_selection ( - GTK_TREE_VIEW (paned->priv->tree_view)); - - g_signal_connect_swapped ( - selection, "changed", - G_CALLBACK (attachment_paned_sync_icon_view), paned); - - g_signal_connect_swapped ( - paned->priv->icon_view, "selection-changed", - G_CALLBACK (attachment_paned_sync_tree_view), paned); - g_signal_connect_swapped ( paned->priv->expander, "notify::expanded", G_CALLBACK (attachment_paned_notify_cb), paned); @@ -750,11 +708,31 @@ void e_attachment_paned_set_active_view (EAttachmentPaned *paned, gint active_view) { + EAttachmentView *source; + EAttachmentView *target; + g_return_if_fail (E_IS_ATTACHMENT_PANED (paned)); g_return_if_fail (active_view >= 0 && active_view < NUM_VIEWS); + if (active_view == paned->priv->active_view) + return; + paned->priv->active_view = active_view; + /* Synchronize the item selection of the view we're + * switching TO with the view we're switching FROM. */ + if (active_view == 0) { + /* from tree view to icon view */ + source = E_ATTACHMENT_VIEW (paned->priv->tree_view); + target = E_ATTACHMENT_VIEW (paned->priv->icon_view); + } else { + /* from icon view to tree view */ + source = E_ATTACHMENT_VIEW (paned->priv->icon_view); + target = E_ATTACHMENT_VIEW (paned->priv->tree_view); + } + + e_attachment_view_sync_selection (source, target); + g_object_notify (G_OBJECT (paned), "active-view"); } diff --git a/widgets/misc/e-attachment-tree-view.c b/widgets/misc/e-attachment-tree-view.c index 5729a68069..09602ca186 100644 --- a/widgets/misc/e-attachment-tree-view.c +++ b/widgets/misc/e-attachment-tree-view.c @@ -144,6 +144,20 @@ attachment_tree_view_button_release_event (GtkWidget *widget, } static gboolean +attachment_tree_view_motion_notify_event (GtkWidget *widget, + GdkEventMotion *event) +{ + EAttachmentView *view = E_ATTACHMENT_VIEW (widget); + + if (e_attachment_view_motion_notify_event (view, event)) + return TRUE; + + /* Chain up to parent's motion_notify_event() method. */ + return GTK_WIDGET_CLASS (parent_class)-> + motion_notify_event (widget, event); +} + +static gboolean attachment_tree_view_key_press_event (GtkWidget *widget, GdkEventKey *event) { @@ -440,6 +454,7 @@ attachment_tree_view_class_init (EAttachmentTreeViewClass *class) widget_class = GTK_WIDGET_CLASS (class); widget_class->button_press_event = attachment_tree_view_button_press_event; widget_class->button_release_event = attachment_tree_view_button_release_event; + widget_class->motion_notify_event = attachment_tree_view_motion_notify_event; widget_class->key_press_event = attachment_tree_view_key_press_event; widget_class->drag_begin = attachment_tree_view_drag_begin; widget_class->drag_end = attachment_tree_view_drag_end; diff --git a/widgets/misc/e-attachment-view.c b/widgets/misc/e-attachment-view.c index 5a5db57e07..2ff6fb4dab 100644 --- a/widgets/misc/e-attachment-view.c +++ b/widgets/misc/e-attachment-view.c @@ -875,6 +875,12 @@ e_attachment_view_finalize (EAttachmentView *view) priv = e_attachment_view_get_private (view); g_ptr_array_free (priv->handlers, TRUE); + + g_list_foreach (priv->event_list, (GFunc) gdk_event_free, NULL); + g_list_free (priv->event_list); + + g_list_foreach (priv->selected, (GFunc) g_object_unref, NULL); + g_list_free (priv->selected); } EAttachmentViewPrivate * @@ -1074,80 +1080,149 @@ gboolean e_attachment_view_button_press_event (EAttachmentView *view, GdkEventButton *event) { + EAttachmentViewPrivate *priv; GtkTreePath *path; gboolean editable; - gboolean item_clicked; + gboolean handled = FALSE; + gboolean path_is_selected = FALSE; g_return_val_if_fail (E_IS_ATTACHMENT_VIEW (view), FALSE); g_return_val_if_fail (event != NULL, FALSE); - editable = e_attachment_view_get_editable (view); + priv = e_attachment_view_get_private (view); - /* If the user clicked on a selected item, retain the current - * selection. If the user clicked on an unselected item, select - * the clicked item only. If the user did not click on an item, - * clear the current selection. */ - 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); - item_clicked = TRUE; - } else { - e_attachment_view_unselect_all (view); - item_clicked = FALSE; + if (g_list_find (priv->event_list, event) != NULL) + return FALSE; + + if (priv->event_list != NULL) { + /* Save the event to be propagated in order. */ + priv->event_list = g_list_append ( + priv->event_list, + gdk_event_copy ((GdkEvent *) event)); + return TRUE; } - /* Cancel drag and drop if there are no selected items, - * or if any of the selected items are loading or saving. */ + editable = e_attachment_view_get_editable (view); + path = e_attachment_view_get_path_at_pos (view, event->x, event->y); + path_is_selected = e_attachment_view_path_is_selected (view, path); + if (event->button == 1 && event->type == GDK_BUTTON_PRESS) { GList *selected, *iter; gboolean busy = FALSE; selected = e_attachment_view_get_selected_attachments (view); + for (iter = selected; iter != NULL; iter = iter->next) { EAttachment *attachment = iter->data; busy |= e_attachment_get_loading (attachment); busy |= e_attachment_get_saving (attachment); } - if (selected == NULL || busy) - e_attachment_view_drag_source_unset (view); + + /* Prepare for dragging if the clicked item is selected + * and none of the selected items are loading or saving. */ + if (path_is_selected && !busy) { + priv->start_x = event->x; + priv->start_y = event->y; + priv->event_list = g_list_append ( + priv->event_list, + gdk_event_copy ((GdkEvent *) event)); + handled = TRUE; + } + g_list_foreach (selected, (GFunc) g_object_unref, NULL); g_list_free (selected); } if (event->button == 3 && event->type == GDK_BUTTON_PRESS) { + /* If the user clicked on a selected item, retain the + * current selection. If the user clicked on an unselected + * item, select the clicked item only. If the user did not + * click on an item, clear the current selection. */ + if (path == NULL) + e_attachment_view_unselect_all (view); + else if (!path_is_selected) { + e_attachment_view_unselect_all (view); + e_attachment_view_select_path (view, path); + } + /* Non-editable attachment views should only show a * popup menu when right-clicking on an attachment, * but editable views can show the menu any time. */ - if (item_clicked || editable) { + if (path != NULL || editable) { e_attachment_view_show_popup_menu ( view, event, NULL, NULL); - return TRUE; + handled = TRUE; } } - return FALSE; + if (path != NULL) + gtk_tree_path_free (path); + + return handled; } gboolean e_attachment_view_button_release_event (EAttachmentView *view, GdkEventButton *event) { + EAttachmentViewPrivate *priv; + GtkWidget *widget = GTK_WIDGET (view); + GList *iter; + g_return_val_if_fail (E_IS_ATTACHMENT_VIEW (view), FALSE); g_return_val_if_fail (event != NULL, FALSE); - /* Restore the attachment view as a drag source, in case - * we had to cancel during a button press event. */ - if (event->button == 1) - e_attachment_view_drag_source_set (view); + priv = e_attachment_view_get_private (view); + + for (iter = priv->event_list; iter != NULL; iter = iter->next) { + GdkEvent *event = iter->data; + + gtk_propagate_event (widget, event); + gdk_event_free (event); + } + + g_list_free (priv->event_list); + priv->event_list = NULL; return FALSE; } gboolean +e_attachment_view_motion_notify_event (EAttachmentView *view, + GdkEventMotion *event) +{ + EAttachmentViewPrivate *priv; + GtkWidget *widget = GTK_WIDGET (view); + GdkDragContext *context; + GtkTargetList *targets; + + g_return_val_if_fail (E_IS_ATTACHMENT_VIEW (view), FALSE); + g_return_val_if_fail (event != NULL, FALSE); + + priv = e_attachment_view_get_private (view); + + if (priv->event_list == NULL) + return FALSE; + + if (!gtk_drag_check_threshold ( + widget, priv->start_x, priv->start_y, event->x, event->y)) + return TRUE; + + g_list_foreach (priv->event_list, (GFunc) gdk_event_free, NULL); + g_list_free (priv->event_list); + priv->event_list = NULL; + + targets = gtk_drag_source_get_target_list (widget); + + context = gtk_drag_begin ( + widget, targets, GDK_ACTION_COPY, 1, (GdkEvent *) event); + + gtk_drag_set_icon_default (context); + + return TRUE; +} + +gboolean e_attachment_view_key_press_event (EAttachmentView *view, GdkEventKey *event) { @@ -1201,7 +1276,10 @@ e_attachment_view_path_is_selected (EAttachmentView *view, EAttachmentViewIface *iface; g_return_val_if_fail (E_IS_ATTACHMENT_VIEW (view), FALSE); - g_return_val_if_fail (path != NULL, FALSE); + + /* Handle NULL paths gracefully. */ + if (path == NULL) + return FALSE; iface = E_ATTACHMENT_VIEW_GET_IFACE (view); g_return_val_if_fail (iface->path_is_selected != NULL, FALSE); @@ -1287,18 +1365,23 @@ e_attachment_view_sync_selection (EAttachmentView *view, void e_attachment_view_drag_source_set (EAttachmentView *view) { + EAttachmentViewIface *iface; GtkTargetEntry *targets; GtkTargetList *list; gint n_targets; g_return_if_fail (E_IS_ATTACHMENT_VIEW (view)); + iface = E_ATTACHMENT_VIEW_GET_IFACE (view); + if (iface->drag_source_set == NULL) + return; + list = gtk_target_list_new (NULL, 0); gtk_target_list_add_uri_targets (list, 0); targets = gtk_target_table_new_from_list (list, &n_targets); - gtk_drag_source_set ( - GTK_WIDGET (view), GDK_BUTTON1_MASK, + iface->drag_source_set ( + view, GDK_BUTTON1_MASK, targets, n_targets, GDK_ACTION_COPY); gtk_target_table_free (targets, n_targets); @@ -1308,34 +1391,55 @@ e_attachment_view_drag_source_set (EAttachmentView *view) void e_attachment_view_drag_source_unset (EAttachmentView *view) { + EAttachmentViewIface *iface; + g_return_if_fail (E_IS_ATTACHMENT_VIEW (view)); - gtk_drag_source_unset (GTK_WIDGET (view)); + iface = E_ATTACHMENT_VIEW_GET_IFACE (view); + if (iface->drag_source_unset == NULL) + return; + + iface->drag_source_unset (view); } void e_attachment_view_drag_begin (EAttachmentView *view, GdkDragContext *context) { + EAttachmentViewPrivate *priv; + g_return_if_fail (E_IS_ATTACHMENT_VIEW (view)); g_return_if_fail (GDK_IS_DRAG_CONTEXT (context)); + 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); + + g_warn_if_fail (priv->selected == NULL); + priv->selected = e_attachment_view_get_selected_attachments (view); } void e_attachment_view_drag_end (EAttachmentView *view, GdkDragContext *context) { + EAttachmentViewPrivate *priv; + g_return_if_fail (E_IS_ATTACHMENT_VIEW (view)); g_return_if_fail (GDK_IS_DRAG_CONTEXT (context)); + 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); + + g_list_foreach (priv->selected, (GFunc) g_object_unref, NULL); + g_list_free (priv->selected); + priv->selected = NULL; } static void @@ -1363,8 +1467,8 @@ e_attachment_view_drag_data_get (EAttachmentView *view, guint info, guint time) { + EAttachmentViewPrivate *priv; EAttachmentStore *store; - GList *selected; struct { gchar **uris; @@ -1378,19 +1482,16 @@ e_attachment_view_drag_data_get (EAttachmentView *view, status.uris = NULL; status.done = FALSE; + priv = e_attachment_view_get_private (view); store = e_attachment_view_get_store (view); - selected = e_attachment_view_get_selected_attachments (view); - if (selected == NULL) + if (priv->selected == NULL) return; e_attachment_store_get_uris_async ( - store, selected, (GAsyncReadyCallback) + store, priv->selected, (GAsyncReadyCallback) attachment_view_got_uris_cb, &status); - g_list_foreach (selected, (GFunc) g_object_unref, NULL); - g_list_free (selected); - /* We can't return until we have results, so crank * the main loop until the callback gets triggered. */ while (!status.done) @@ -1407,19 +1508,22 @@ void e_attachment_view_drag_dest_set (EAttachmentView *view) { EAttachmentViewPrivate *priv; + EAttachmentViewIface *iface; GtkTargetEntry *targets; gint n_targets; g_return_if_fail (E_IS_ATTACHMENT_VIEW (view)); + iface = E_ATTACHMENT_VIEW_GET_IFACE (view); + if (iface->drag_dest_set == NULL) + return; + priv = e_attachment_view_get_private (view); targets = gtk_target_table_new_from_list ( priv->target_list, &n_targets); - gtk_drag_dest_set ( - GTK_WIDGET (view), GTK_DEST_DEFAULT_ALL, - targets, n_targets, priv->drag_actions); + iface->drag_dest_set (view, targets, n_targets, priv->drag_actions); gtk_target_table_free (targets, n_targets); } @@ -1427,9 +1531,15 @@ e_attachment_view_drag_dest_set (EAttachmentView *view) void e_attachment_view_drag_dest_unset (EAttachmentView *view) { + EAttachmentViewIface *iface; + g_return_if_fail (E_IS_ATTACHMENT_VIEW (view)); - gtk_drag_dest_unset (GTK_WIDGET (view)); + iface = E_ATTACHMENT_VIEW_GET_IFACE (view); + if (iface->drag_dest_unset == NULL) + return; + + iface->drag_dest_unset (view); } gboolean diff --git a/widgets/misc/e-attachment-view.h b/widgets/misc/e-attachment-view.h index 89d2d28664..071de0705a 100644 --- a/widgets/misc/e-attachment-view.h +++ b/widgets/misc/e-attachment-view.h @@ -103,6 +103,12 @@ struct _EAttachmentViewPrivate { GtkUIManager *ui_manager; guint merge_id; + /* Multi-DnD State */ + GList *event_list; + GList *selected; + gint start_x; + gint start_y; + guint editable : 1; }; @@ -139,6 +145,9 @@ gboolean e_attachment_view_button_press_event gboolean e_attachment_view_button_release_event (EAttachmentView *view, GdkEventButton *event); +gboolean e_attachment_view_motion_notify_event + (EAttachmentView *view, + GdkEventMotion *event); gboolean e_attachment_view_key_press_event (EAttachmentView *view, GdkEventKey *event); |