diff options
author | Hans Petter Jansson <hpj@ximian.com> | 2004-06-24 06:40:24 +0800 |
---|---|---|
committer | Hans Petter <hansp@src.gnome.org> | 2004-06-24 06:40:24 +0800 |
commit | 54a5d78f7876c7ebbe6e973a7d0321efb48128e0 (patch) | |
tree | c4cf1430105eddc54c3ea70e5aee7648e1effac6 /addressbook/gui/component/addressbook-view.c | |
parent | 00fc3d7f480b020e90de31894f575c54dd78a034 (diff) | |
download | gsoc2013-evolution-54a5d78f7876c7ebbe6e973a7d0321efb48128e0.tar.gz gsoc2013-evolution-54a5d78f7876c7ebbe6e973a7d0321efb48128e0.tar.zst gsoc2013-evolution-54a5d78f7876c7ebbe6e973a7d0321efb48128e0.zip |
Add an x-source-vcard target entry that includes the source book URI.
2004-06-23 Hans Petter Jansson <hpj@ximian.com>
* gui/component/addressbook-view.c: Add an x-source-vcard target entry
that includes the source book URI.
(destroy_merge_context): Implement.
(removed_contact_cb): Implement.
(merged_contact_cb): Implement.
(selector_tree_drag_data_received): Get the source and target books,
and see if we need to remove contacts from source after they're added
to target. Copy contacts sequentially, not in parallel, with a
callback.
* gui/widgets/e-addressbook-view.c: Add an x-source-vcard target entry
that includes the source book URI.
(table_drag_data_delete): Remove. This is handled by the drag target.
(table_drag_data_get): Handle more than one contact. Supply source.
(create_table_view): Don't connect to the delete signal.
* gui/widgets/e-minicard-view.c: Add an x-source-vcard target entry
that includes the source book URI.
(e_minicard_view_drag_data_delete): Remove. This is handled by the
drag target.
(e_minicard_view_drag_data_get): Handle x-source-vcard target.
(e_minicard_view_drag_begin): Don't connect to the delete signal.
(e_minicard_view_dispose): Don't disconnect from the delete signal.
(e_minicard_view_init): Don't init delete_id.
* gui/widgets/e-minicard-view.h: Remove delete_id from struct.
* util/eab-book-util.[ch] (eab_contact_list_from_string): Skip the
source URI if present.
(eab_book_and_contact_list_from_string): Create the source book from
the provided URI, if present.
(eab_book_and_contact_list_to_string): Include the book URI in
generated string.
svn path=/trunk/; revision=26485
Diffstat (limited to 'addressbook/gui/component/addressbook-view.c')
-rw-r--r-- | addressbook/gui/component/addressbook-view.c | 138 |
1 files changed, 115 insertions, 23 deletions
diff --git a/addressbook/gui/component/addressbook-view.c b/addressbook/gui/component/addressbook-view.c index 149bf3521b..cfedd0b949 100644 --- a/addressbook/gui/component/addressbook-view.c +++ b/addressbook/gui/component/addressbook-view.c @@ -93,9 +93,12 @@ struct _AddressbookViewPrivate { enum DndTargetType { DND_TARGET_TYPE_VCARD_LIST, + DND_TARGET_TYPE_SOURCE_VCARD_LIST }; -#define VCARD_TYPE "text/x-vcard" +#define VCARD_TYPE "text/x-vcard" +#define SOURCE_VCARD_TYPE "text/x-source-vcard" static GtkTargetEntry drag_types[] = { + { SOURCE_VCARD_TYPE, 0, DND_TARGET_TYPE_SOURCE_VCARD_LIST }, { VCARD_TYPE, 0, DND_TARGET_TYPE_VCARD_LIST } }; static gint num_drag_types = sizeof(drag_types) / sizeof(drag_types[0]); @@ -791,6 +794,79 @@ selector_tree_drag_motion (GtkWidget *widget, return TRUE; } +typedef struct +{ + guint remove_from_source : 1; + guint copy_done : 1; + gint pending_removals; + + EContact *current_contact; + GList *remaining_contacts; + + EBook *source_book; + EBook *target_book; +} +MergeContext; + +static void +destroy_merge_context (MergeContext *merge_context) +{ + if (merge_context->source_book) + g_object_unref (merge_context->source_book); + if (merge_context->target_book) + g_object_unref (merge_context->target_book); + + g_free (merge_context); +} + +static void +removed_contact_cb (EBook *book, EBookStatus status, gpointer closure) +{ + MergeContext *merge_context = closure; + + merge_context->pending_removals--; + + if (merge_context->copy_done && merge_context->pending_removals == 0) { + /* Finished */ + + destroy_merge_context (merge_context); + } +} + +static void +merged_contact_cb (EBook *book, EBookStatus status, const char *id, gpointer closure) +{ + MergeContext *merge_context = closure; + + if (merge_context->remove_from_source && status == E_BOOK_ERROR_OK) { + /* Remove previous contact from source */ + + e_book_async_remove_contact (merge_context->source_book, merge_context->current_contact, + removed_contact_cb, merge_context); + merge_context->pending_removals++; + } + + g_object_unref (merge_context->current_contact); + + if (merge_context->remaining_contacts) { + /* Copy next contact */ + + merge_context->current_contact = merge_context->remaining_contacts->data; + merge_context->remaining_contacts = g_list_delete_link (merge_context->remaining_contacts, + merge_context->remaining_contacts); + eab_merging_book_add_contact (merge_context->target_book, merge_context->current_contact, + merged_contact_cb, merge_context); + } else if (merge_context->pending_removals == 0) { + /* Finished */ + + destroy_merge_context (merge_context); + } else { + /* Finished, but have pending removals */ + + merge_context->copy_done = TRUE; + } +} + static gboolean selector_tree_drag_data_received (GtkWidget *widget, GdkDragContext *context, @@ -803,12 +879,13 @@ selector_tree_drag_data_received (GtkWidget *widget, { GtkTreePath *path = NULL; GtkTreeViewDropPosition pos; - gpointer source = NULL; + gpointer source, target = NULL; GtkTreeModel *model; GtkTreeIter iter; gboolean success = FALSE; - EBook *book; + EBook *source_book, *target_book; + MergeContext *merge_context; GList *contactlist; GList *l; @@ -821,37 +898,52 @@ selector_tree_drag_data_received (GtkWidget *widget, if (!gtk_tree_model_get_iter (model, &iter, path)) goto finish; - gtk_tree_model_get (model, &iter, 0, &source, -1); + gtk_tree_model_get (model, &iter, 0, &target, -1); - if (E_IS_SOURCE_GROUP (source) || e_source_get_readonly (source)) + if (E_IS_SOURCE_GROUP (target) || e_source_get_readonly (target)) goto finish; - book = e_book_new (source, NULL); - if (!book) { + target_book = e_book_new (target, NULL); + if (!target_book) { g_message (G_STRLOC ":Couldn't create EBook."); return FALSE; } - e_book_open (book, TRUE, NULL); - contactlist = eab_contact_list_from_string (data->data); - - for (l = contactlist; l; l = l->next) { - EContact *contact = l->data; - - /* XXX NULL for a callback /sigh */ - if (contact) - eab_merging_book_add_contact (book, contact, NULL /* XXX */, NULL); - success = TRUE; + e_book_open (target_book, TRUE, NULL); + + eab_book_and_contact_list_from_string (data->data, &source_book, &contactlist); + + if (source_book) { + if (!e_book_open (source_book, FALSE, NULL)) { + g_warning (G_STRLOC ": Couldn't open source EBook."); + g_object_unref (source_book); + source_book = NULL; + } + } else { + g_warning (G_STRLOC ": No source EBook provided."); } - - g_list_foreach (contactlist, (GFunc)g_object_unref, NULL); - g_list_free (contactlist); - g_object_unref (book); + + /* Set up merge context */ + + merge_context = g_new0 (MergeContext, 1); + + merge_context->source_book = source_book; + merge_context->target_book = target_book; + + merge_context->current_contact = contactlist->data; + merge_context->remaining_contacts = g_list_delete_link (contactlist, contactlist); + + merge_context->remove_from_source = context->suggested_action == GDK_ACTION_MOVE ? TRUE : FALSE; + + /* Start merge */ + + eab_merging_book_add_contact (target_book, merge_context->current_contact, + merged_contact_cb, merge_context); finish: if (path) gtk_tree_path_free (path); - if (source) - g_object_unref (source); + if (target) + g_object_unref (target); gtk_drag_finish (context, success, context->action == GDK_ACTION_MOVE, time); |