From 86d3ffedacdaa16e49d98875f4804c3423466462 Mon Sep 17 00:00:00 2001 From: Srinivasa Ragavan Date: Wed, 18 Apr 2007 08:34:24 +0000 Subject: Committing Contact Merging patch from Ebby Wiselyn svn path=/trunk/; revision=33428 --- addressbook/ChangeLog | 10 + .../merging/eab-contact-duplicate-detected.glade | 11 + addressbook/gui/merging/eab-contact-merging.c | 294 ++++++++++++++++++++- 3 files changed, 309 insertions(+), 6 deletions(-) diff --git a/addressbook/ChangeLog b/addressbook/ChangeLog index 1431d352ee..210a531008 100644 --- a/addressbook/ChangeLog +++ b/addressbook/ChangeLog @@ -1,3 +1,13 @@ +2007-04-18 Srinivasa Ragavan + + ** Committed Contact Merging patch from Ebby Wiselyn + + * gui/merging/eab-contact-duplicate-detected.glade: + * gui/merging/eab-contact-merging.c: (free_lookup), (dialog_map), + (dropdown_changed), (mergeit), (check_if_same), (response), + (match_query_callback), (eab_merging_book_add_contact), + (eab_merging_book_commit_contact): + 2007-04-10 Elizabeth Greene ** Fix for bug #426743. diff --git a/addressbook/gui/merging/eab-contact-duplicate-detected.glade b/addressbook/gui/merging/eab-contact-duplicate-detected.glade index b16c1662f5..4d6b4802ad 100644 --- a/addressbook/gui/merging/eab-contact-duplicate-detected.glade +++ b/addressbook/gui/merging/eab-contact-duplicate-detected.glade @@ -56,6 +56,17 @@ 0 + + + True + True + True + Merge + GTK_RELIEF_NORMAL + True + 2 + + 0 diff --git a/addressbook/gui/merging/eab-contact-merging.c b/addressbook/gui/merging/eab-contact-merging.c index a8a2917ade..2296647a11 100644 --- a/addressbook/gui/merging/eab-contact-merging.c +++ b/addressbook/gui/merging/eab-contact-merging.c @@ -14,12 +14,18 @@ #include "eab-contact-merging.h" #include "eab-contact-compare.h" #include +#include +#include +#include #include #include #include +#include #include "addressbook/gui/widgets/eab-contact-display.h" #include "e-util/e-util-private.h" +#include +typedef struct dropdown_data dropdown_data; typedef enum { E_CONTACT_MERGING_ADD, E_CONTACT_MERGING_COMMIT @@ -28,13 +34,20 @@ typedef enum { typedef struct { EContactMergingOpType op; EBook *book; + /*contact is the new contact which the user has tried to add to the addressbook*/ EContact *contact; + /*match is the duplicate contact already existing in the addressbook*/ + EContact *match; GList *avoid; EBookIdCallback id_cb; EBookCallback cb; gpointer closure; } EContactMergingLookup; +struct dropdown_data { + EContact *match; + EContactField field; +}; static void match_query_callback (EContact *contact, EContact *match, EABContactMatchType type, gpointer closure); #define SIMULTANEOUS_MERGING_REQUESTS 20 @@ -62,7 +75,7 @@ finished_lookup (void) while (running_merge_requests < SIMULTANEOUS_MERGING_REQUESTS) { EContactMergingLookup *lookup; - + if (!merging_queue) break; @@ -81,7 +94,8 @@ free_lookup (EContactMergingLookup *lookup) g_object_unref (lookup->book); g_object_unref (lookup->contact); g_list_free (lookup->avoid); - + if(lookup->match) + g_object_unref (lookup->match); g_free (lookup); } @@ -130,11 +144,263 @@ cancelit (EContactMergingLookup *lookup) } } +gboolean +dialog_map (GtkWidget *window, GdkEvent *event, GtkWidget *table) +{ + int h, w; + + /* Spacing around the table */ + w = table->allocation.width + 30; + /* buttons and outer spacing */ + h = table->allocation.height + 60; + if (w > 400) + w = 400; + if (h > 450) + h = 450; + gtk_widget_set_usize (window, w, h); +} + static void -response (GtkWidget *dialog, int response, EContactMergingLookup *lookup) +dropdown_changed (GtkWidget *dropdown, dropdown_data *data) { + char *str; + str = gtk_combo_box_get_active_text (dropdown); + + if (g_ascii_strcasecmp(str, "")) + e_contact_set (data->match, data->field, str); + else + e_contact_set (data->match, data->field, NULL); + return; +} + +static int +mergeit (EContactMergingLookup *lookup) +{ + GtkWidget *scrolled_window, *label, *hbox, *dropdown; + GtkDialog *dialog; + GtkTable *table; + EContactField field; + char *str = NULL, *string = NULL, *string1 = NULL; + int num_of_email; + GList *email_attr_list; + int row = -1; + int value; + + dialog = (GtkDialog *)(gtk_dialog_new_with_buttons (_("Merge Contact"), NULL, GTK_DIALOG_NO_SEPARATOR, NULL)); + gtk_container_border_width (GTK_CONTAINER(dialog), 5); + + scrolled_window = gtk_scrolled_window_new (NULL, NULL); + gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_window), + GTK_POLICY_AUTOMATIC, + GTK_POLICY_AUTOMATIC); + + table = (GtkTable *) gtk_table_new (20, 2, FALSE); + gtk_container_set_border_width ((GtkContainer *) table, 12); + gtk_table_set_row_spacings (table, 6); + gtk_table_set_col_spacings (table, 2); + + gtk_dialog_add_buttons ((GtkDialog *) dialog, + GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, + _("Merge"), GTK_RESPONSE_OK, + NULL); + + email_attr_list = e_contact_get_attributes (lookup->match, E_CONTACT_EMAIL); + num_of_email = g_list_length (email_attr_list); + + /*we match all the string fields of the already existing contact and the new contact.*/ + for(field = E_CONTACT_FULL_NAME; field != (E_CONTACT_LAST_SIMPLE_STRING -1) ; field++) { + dropdown_data *data = NULL; + string = e_contact_get_const (lookup->contact, field); + string1 = e_contact_get_const (lookup->match, field); + + /*the field must exist in the new as well as the duplicate contact*/ + if (string && *string) { + /*Four email id's present, should be compared with all email id's in duplicate contact */ + /*Merge only if number of email id's in existing contact is less than 4 */ + if ((field == E_CONTACT_EMAIL_1 || field == E_CONTACT_EMAIL_2 + || field == E_CONTACT_EMAIL_3 || field == E_CONTACT_EMAIL_4) && (num_of_email < 4)) { + row++; + str = e_contact_get_const (lookup->contact, field); + switch(num_of_email) + { + case 0: + field = E_CONTACT_EMAIL_1; + break; + case 1: + /*New contact has email that is NOT equal to email in duplicate contact*/ + if((str && *str) && (g_ascii_strcasecmp(e_contact_get_const (lookup->match, E_CONTACT_EMAIL_1),str))) { + field = E_CONTACT_EMAIL_2; + break; + } + else/*Either the new contact has no email OR the email already exist in the duplicate contact*/ + continue; + case 2: + /*New contact has email and it is equal to neither of the 2 emails in the duplicate contact*/ + if((str && *str) && + (g_ascii_strcasecmp(str,e_contact_get_const (lookup->match, E_CONTACT_EMAIL_1))) && + (g_ascii_strcasecmp(e_contact_get_const (lookup->match, E_CONTACT_EMAIL_2),str))) { + field = E_CONTACT_EMAIL_3; + break; + } + else + continue; + case 3: + /*New contact has email and it is equal to none of the 3 emails in the duplicate contact*/ + if((str && *str) && + (g_ascii_strcasecmp(e_contact_get_const (lookup->match, E_CONTACT_EMAIL_1),str)) && + (g_ascii_strcasecmp(e_contact_get_const (lookup->match, E_CONTACT_EMAIL_2),str)) && + (g_ascii_strcasecmp(e_contact_get_const (lookup->match, E_CONTACT_EMAIL_3),str))) + field = E_CONTACT_EMAIL_4; + else + continue; + } + label = gtk_label_new (_("Email")); + hbox = gtk_hbox_new (FALSE, 0); + gtk_box_pack_start (GTK_BOX(hbox), (GtkWidget*)label, FALSE, FALSE, 0); + gtk_table_attach_defaults (table, (GtkWidget *)hbox, 0, 1, row, row + 1); + + dropdown = gtk_combo_box_new_text(); + gtk_combo_box_append_text (dropdown, string); + + data = g_new0 (dropdown_data, 1); + + gtk_combo_box_append_text (dropdown, ""); + + gtk_combo_box_set_active (dropdown, 0); + data->field = field; + data->match = lookup->match; + e_contact_set (lookup->match, field, string); + g_signal_connect (dropdown, "changed", G_CALLBACK(dropdown_changed), data); + + hbox = gtk_hbox_new (FALSE, 0); + gtk_box_pack_start (GTK_BOX(hbox), (GtkWidget*)dropdown, FALSE, FALSE, 0); + gtk_table_attach_defaults (table, (GtkWidget *)hbox, 1, 2, row, row + 1); + gtk_widget_show ((GtkWidget *)dropdown); + continue; + } + if (((field == E_CONTACT_FULL_NAME) && (!g_ascii_strcasecmp(string, string1)))) { + row++; + label = gtk_label_new (e_contact_pretty_name(field)); + hbox = gtk_hbox_new (FALSE, 0); + gtk_box_pack_start (GTK_BOX(hbox), (GtkWidget*)label, FALSE, FALSE, 0); + gtk_table_attach_defaults (table, (GtkWidget *)hbox, 0, 1, row, row + 1); + + label = gtk_label_new (string); + hbox = gtk_hbox_new (FALSE, 0); + gtk_box_pack_start (GTK_BOX(hbox), (GtkWidget*)label, FALSE, FALSE, 0); + gtk_table_attach_defaults (table, (GtkWidget*)hbox, 1, 2, row, row + 1); + continue; + } + + /*for all string fields except name and email*/ + if(!(string1 && *string1) || (g_ascii_strcasecmp(string, string1))) { + row++; + label = gtk_label_new (e_contact_pretty_name(field)); + hbox = gtk_hbox_new (FALSE, 0); + gtk_box_pack_start (GTK_BOX(hbox), (GtkWidget*)label, FALSE, FALSE, 0); + gtk_table_attach_defaults (table, (GtkWidget *)hbox, 0, 1, row, row + 1); + data = g_new0 (dropdown_data, 1); + dropdown = gtk_combo_box_new_text(); + gtk_combo_box_append_text (dropdown, string); + e_contact_set (lookup->match, field, string); + + if (string1 && *string1) + gtk_combo_box_append_text (dropdown, string1); + else + gtk_combo_box_append_text (dropdown, ""); + + gtk_combo_box_set_active (dropdown, 0); + data->field = field; + data->match = lookup->match; + + if (field == E_CONTACT_NICKNAME || field == E_CONTACT_GIVEN_NAME) + gtk_widget_set_sensitive ((GtkWidget *)dropdown, FALSE); + + g_signal_connect (dropdown, "changed", G_CALLBACK(dropdown_changed), data); + hbox = gtk_hbox_new (FALSE, 0); + gtk_box_pack_start (GTK_BOX(hbox), (GtkWidget*)dropdown, FALSE, FALSE, 0); + gtk_table_attach_defaults (table, (GtkWidget *)hbox, 1, 2, row, row + 1); + gtk_widget_show_all ((GtkWidget *)dropdown); + } + } + } + + gtk_window_set_default_size (GTK_WINDOW (dialog), 420, 300); + gtk_scrolled_window_add_with_viewport (GTK_SCROLLED_WINDOW (scrolled_window), GTK_WIDGET (table)); + gtk_box_pack_start (GTK_BOX (dialog->vbox), GTK_WIDGET (scrolled_window), TRUE, TRUE, 0); + gtk_widget_show (scrolled_window); + g_signal_connect (dialog, "map-event", G_CALLBACK (dialog_map), table); + gtk_widget_show_all ((GtkWidget *)table); + gint result = gtk_dialog_run (dialog); + + switch (result) + { + case GTK_RESPONSE_OK: + lookup->contact = lookup->match; + e_book_async_remove_contact (lookup->book, lookup->match, NULL, lookup); + e_book_async_add_contact (lookup->book, lookup->contact, final_id_cb, lookup); + value = 1; + break; + case GTK_RESPONSE_CANCEL: + value = 0; + break; + } gtk_widget_destroy (dialog); + g_list_free (email_attr_list); + return value; +} + +static gboolean +check_if_same (EContact *contact, EContact *match) +{ + EContactField field; + GList *email_attr_list; + int num_of_email; + char *str = NULL, *string = NULL, *string1 = NULL; + + for(field = E_CONTACT_FULL_NAME; field != (E_CONTACT_LAST_SIMPLE_STRING -1) ; field++) { + email_attr_list = e_contact_get_attributes (match, E_CONTACT_EMAIL); + num_of_email = g_list_length (email_attr_list); + + if ((field == E_CONTACT_EMAIL_1 || field == E_CONTACT_EMAIL_2 + || field == E_CONTACT_EMAIL_3 || field == E_CONTACT_EMAIL_4) && (num_of_email<4)) { + str = e_contact_get_const (contact, field); + switch(num_of_email) + { + case 0: + return FALSE; + case 1: + if((str && *str) && (g_ascii_strcasecmp(e_contact_get_const (match, E_CONTACT_EMAIL_1),str))) + return FALSE; + case 2: + if((str && *str) && (g_ascii_strcasecmp(str,e_contact_get_const (match, E_CONTACT_EMAIL_1))) && + (g_ascii_strcasecmp(e_contact_get_const (match, E_CONTACT_EMAIL_2),str))) + return FALSE; + case 3: + if((str && *str) && (g_ascii_strcasecmp(e_contact_get_const (match, E_CONTACT_EMAIL_1),str)) && + (g_ascii_strcasecmp(e_contact_get_const (match, E_CONTACT_EMAIL_2),str)) && + (g_ascii_strcasecmp(e_contact_get_const (match, E_CONTACT_EMAIL_3),str))) + return FALSE; + } + } + else { + string = e_contact_get_const (contact, field); + string1 = e_contact_get_const (match, field); + if ((string && *string) && (string1 && *string1) && (g_ascii_strcasecmp(string1,string))) + return FALSE; + /*if the field entry exist in either of the contacts,we'll have to give the choice and thus merge button should be sensitive*/ + else if ((string && *string) && !(string1 && *string1)) + return FALSE; + } + } + g_list_free (email_attr_list); + return TRUE; +} +static void +response (GtkWidget *dialog, int response, EContactMergingLookup *lookup) +{ + static int merge_response; switch (response) { case 0: doit (lookup); @@ -142,10 +408,16 @@ response (GtkWidget *dialog, int response, EContactMergingLookup *lookup) case 1: cancelit (lookup); break; + case 2: + merge_response = mergeit (lookup); + if (merge_response) + break; + return; case GTK_RESPONSE_DELETE_EVENT: cancelit (lookup); break; } + gtk_widget_destroy (dialog); } static void @@ -153,19 +425,27 @@ match_query_callback (EContact *contact, EContact *match, EABContactMatchType ty { EContactMergingLookup *lookup = closure; char *gladefile; + int flag; if ((gint) type <= (gint) EAB_CONTACT_MATCH_VAGUE) { doit (lookup); } else { GladeXML *ui; - - GtkWidget *widget; + GtkWidget *widget, *merge_button; + + lookup->match = g_object_ref (match); if (lookup->op == E_CONTACT_MERGING_ADD) { + /* Compares all the values of contacts and return true, if they match */ + flag = check_if_same (contact, match); gladefile = g_build_filename (EVOLUTION_GLADEDIR, "eab-contact-duplicate-detected.glade", NULL); ui = glade_xml_new (gladefile, NULL, NULL); + merge_button = GTK_BUTTON (glade_xml_get_widget (ui, "button5")); + /* Merge Button not sensitive when all values are same */ + if (flag) + gtk_widget_set_sensitive ((GtkWidget *)merge_button, FALSE); g_free (gladefile); } else if (lookup->op == E_CONTACT_MERGING_COMMIT) { gladefile = g_build_filename (EVOLUTION_GLADEDIR, @@ -215,6 +495,7 @@ eab_merging_book_add_contact (EBook *book, lookup->id_cb = cb; lookup->closure = closure; lookup->avoid = NULL; + lookup->match = NULL; add_lookup (lookup); @@ -228,7 +509,7 @@ eab_merging_book_commit_contact (EBook *book, gpointer closure) { EContactMergingLookup *lookup; - + lookup = g_new (EContactMergingLookup, 1); lookup->op = E_CONTACT_MERGING_COMMIT; @@ -237,6 +518,7 @@ eab_merging_book_commit_contact (EBook *book, lookup->cb = cb; lookup->closure = closure; lookup->avoid = g_list_append (NULL, contact); + lookup->match = NULL; add_lookup (lookup); -- cgit v1.2.3