evolution-3.6.4/addressbook/gui/merging/eab-contact-merging.c

No issues found

Incomplete coverage

Tool Failure ID Location Function Message Data
clang-analyzer no-output-found eab-contact-merging.c Message(text='Unable to locate XML output from invoke-clang-analyzer') None
clang-analyzer no-output-found eab-contact-merging.c Message(text='Unable to locate XML output from invoke-clang-analyzer') None
Failure running clang-analyzer ('no-output-found')
Message
Unable to locate XML output from invoke-clang-analyzer
Failure running clang-analyzer ('no-output-found')
Message
Unable to locate XML output from invoke-clang-analyzer
  1 /*
  2  * Code for checking for duplicates when doing EContact work.
  3  *
  4  * This program is free software; you can redistribute it and/or
  5  * modify it under the terms of the GNU Lesser General Public
  6  * License as published by the Free Software Foundation; either
  7  * version 2 of the License, or (at your option) version 3.
  8  *
  9  * This program is distributed in the hope that it will be useful,
 10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
 11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 12  * Lesser General Public License for more details.
 13  *
 14  * You should have received a copy of the GNU Lesser General Public
 15  * License along with the program; if not, see <http://www.gnu.org/licenses/>
 16  *
 17  *
 18  * Authors:
 19  *		Christopher James Lahey <clahey@ximian.com>
 20  *		Chris Toshok <toshok@ximian.com>
 21  *
 22  * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
 23  *
 24  */
 25 
 26 #ifdef HAVE_CONFIG_H
 27 #include <config.h>
 28 #endif
 29 
 30 #include "eab-contact-merging.h"
 31 #include "eab-contact-compare.h"
 32 #include <gtk/gtk.h>
 33 #include <string.h>
 34 #include "addressbook/gui/widgets/eab-contact-display.h"
 35 #include "e-util/e-util.h"
 36 #include "e-util/e-util-private.h"
 37 #include <glib/gi18n.h>
 38 
 39 typedef struct dropdown_data dropdown_data;
 40 typedef enum {
 41 	E_CONTACT_MERGING_ADD,
 42 	E_CONTACT_MERGING_COMMIT,
 43 	E_CONTACT_MERGING_FIND
 44 } EContactMergingOpType;
 45 
 46 typedef struct {
 47 	EContactMergingOpType op;
 48 	ESourceRegistry *registry;
 49 	EBookClient *book_client;
 50 	/*contact is the new contact which the user has tried to add to the addressbook*/
 51 	EContact *contact;
 52 	/*match is the duplicate contact already existing in the addressbook*/
 53 	EContact *match;
 54 	GList *avoid;
 55 	EABMergingAsyncCallback cb;
 56 	EABMergingIdAsyncCallback id_cb;
 57 	EABMergingContactAsyncCallback c_cb;
 58 	gpointer closure;
 59 } EContactMergingLookup;
 60 
 61 struct dropdown_data {
 62 	EContact *match;
 63 	EContactField field;
 64 };
 65 static void match_query_callback (EContact *contact, EContact *match, EABContactMatchType type, gpointer closure);
 66 
 67 #define SIMULTANEOUS_MERGING_REQUESTS 20
 68 
 69 static GList *merging_queue = NULL;
 70 static gint running_merge_requests = 0;
 71 
 72 static void
 73 add_lookup (EContactMergingLookup *lookup)
 74 {
 75 	if (running_merge_requests < SIMULTANEOUS_MERGING_REQUESTS) {
 76 		running_merge_requests++;
 77 		eab_contact_locate_match_full (
 78 			lookup->registry, lookup->book_client,
 79 			lookup->contact, lookup->avoid,
 80 			match_query_callback, lookup);
 81 	}
 82 	else {
 83 		merging_queue = g_list_append (merging_queue, lookup);
 84 	}
 85 }
 86 
 87 static void
 88 finished_lookup (void)
 89 {
 90 	running_merge_requests--;
 91 
 92 	while (running_merge_requests < SIMULTANEOUS_MERGING_REQUESTS) {
 93 		EContactMergingLookup *lookup;
 94 
 95 		if (!merging_queue)
 96 			break;
 97 
 98 		lookup = merging_queue->data;
 99 
100 		merging_queue = g_list_remove_link (merging_queue, merging_queue);
101 
102 		running_merge_requests++;
103 		eab_contact_locate_match_full (
104 			lookup->registry, lookup->book_client,
105 			lookup->contact, lookup->avoid,
106 			match_query_callback, lookup);
107 	}
108 }
109 
110 static void
111 free_lookup (EContactMergingLookup *lookup)
112 {
113 	g_object_unref (lookup->registry);
114 	g_object_unref (lookup->book_client);
115 	g_object_unref (lookup->contact);
116 	g_list_free (lookup->avoid);
117 	if (lookup->match)
118 		g_object_unref (lookup->match);
119 	g_free (lookup);
120 }
121 
122 static void
123 final_id_cb (EBookClient *book_client,
124              const GError *error,
125              const gchar *id,
126              gpointer closure)
127 {
128 	EContactMergingLookup *lookup = closure;
129 
130 	if (lookup->id_cb)
131 		lookup->id_cb (
132 			lookup->book_client,
133 			error, id, lookup->closure);
134 
135 	free_lookup (lookup);
136 
137 	finished_lookup ();
138 }
139 
140 static void
141 final_cb_as_id (EBookClient *book_client,
142                 const GError *error,
143                 gpointer closure)
144 {
145 	EContactMergingLookup *lookup = closure;
146 
147 	if (lookup->id_cb)
148 		lookup->id_cb (
149 			lookup->book_client,
150 			error, lookup->contact ?
151 				e_contact_get_const (
152 				lookup->contact, E_CONTACT_UID) : NULL,
153 			lookup->closure);
154 
155 	free_lookup (lookup);
156 
157 	finished_lookup ();
158 }
159 
160 static void
161 final_cb (EBookClient *book_client,
162           const GError *error,
163           gpointer closure)
164 {
165 	EContactMergingLookup *lookup = closure;
166 
167 	if (lookup->cb)
168 		lookup->cb (lookup->book_client, error, lookup->closure);
169 
170 	free_lookup (lookup);
171 
172 	finished_lookup ();
173 }
174 
175 static void
176 modify_contact_ready_cb (GObject *source_object,
177                          GAsyncResult *result,
178                          gpointer user_data)
179 {
180 	EBookClient *book_client = E_BOOK_CLIENT (source_object);
181 	EContactMergingLookup *lookup = user_data;
182 	GError *error = NULL;
183 
184 	g_return_if_fail (book_client != NULL);
185 	g_return_if_fail (lookup != NULL);
186 
187 	e_book_client_modify_contact_finish (book_client, result, &error);
188 
189 	if (lookup->op == E_CONTACT_MERGING_ADD)
190 		final_cb_as_id (book_client, error, lookup);
191 	else
192 		final_cb (book_client, error, lookup);
193 
194 	if (error)
195 		g_error_free (error);
196 }
197 
198 static void
199 add_contact_ready_cb (GObject *source_object,
200                       GAsyncResult *result,
201                       gpointer user_data)
202 {
203 	EBookClient *book_client = E_BOOK_CLIENT (source_object);
204 	EContactMergingLookup *lookup = user_data;
205 	gchar *uid = NULL;
206 	GError *error = NULL;
207 
208 	g_return_if_fail (book_client != NULL);
209 	g_return_if_fail (lookup != NULL);
210 
211 	if (!e_book_client_add_contact_finish (book_client, result, &uid, &error))
212 		uid = NULL;
213 
214 	final_id_cb (book_client, error, uid, lookup);
215 
216 	if (error)
217 		g_error_free (error);
218 }
219 
220 static void
221 doit (EContactMergingLookup *lookup,
222       gboolean force_modify)
223 {
224 	if (lookup->op == E_CONTACT_MERGING_ADD) {
225 		if (force_modify)
226 			e_book_client_modify_contact (lookup->book_client, lookup->contact, NULL, modify_contact_ready_cb, lookup);
227 		else
228 			e_book_client_add_contact (lookup->book_client, lookup->contact, NULL, add_contact_ready_cb, lookup);
229 	} else if (lookup->op == E_CONTACT_MERGING_COMMIT)
230 		e_book_client_modify_contact (lookup->book_client, lookup->contact, NULL, modify_contact_ready_cb, lookup);
231 }
232 
233 static void
234 cancelit (EContactMergingLookup *lookup)
235 {
236 	GError *error = e_client_error_create (E_CLIENT_ERROR_CANCELLED, NULL);
237 
238 	if (lookup->op == E_CONTACT_MERGING_ADD) {
239 		final_id_cb (lookup->book_client, error, NULL, lookup);
240 	} else if (lookup->op == E_CONTACT_MERGING_COMMIT) {
241 		final_cb (lookup->book_client, error, lookup);
242 	}
243 
244 	g_error_free (error);
245 }
246 
247 static void
248 dialog_map (GtkWidget *window,
249             GdkEvent *event,
250             GtkWidget *table)
251 {
252 	GtkAllocation allocation;
253 	gint h, w;
254 
255 	gtk_widget_get_allocation (table, &allocation);
256 
257 	/* Spacing around the table */
258 	w = allocation.width + 30;
259 	/* buttons and outer spacing */
260 	h = allocation.height + 60;
261 	if (w > 400)
262 		w = 400;
263 	if (h > 450)
264 		h = 450;
265 
266 	gtk_widget_set_size_request (window, w, h);
267 }
268 
269 static void
270 dropdown_changed (GtkWidget *dropdown,
271                   dropdown_data *data)
272 {
273 	gchar *str;
274 	str = gtk_combo_box_text_get_active_text (GTK_COMBO_BOX_TEXT (dropdown));
275 
276 	if (g_ascii_strcasecmp (str, ""))
277 		e_contact_set (data->match, data->field, str);
278 	else
279 		e_contact_set (data->match, data->field, NULL);
280 	return;
281 }
282 
283 static void
284 remove_contact_ready_cb (GObject *source_object,
285                          GAsyncResult *result,
286                          gpointer user_data)
287 {
288 	EBookClient *book_client = E_BOOK_CLIENT (source_object);
289 	EContactMergingLookup *lookup = user_data;
290 	GError *error = NULL;
291 
292 	g_return_if_fail (book_client != NULL);
293 	g_return_if_fail (lookup != NULL);
294 
295 	e_book_client_remove_contact_finish (book_client, result, &error);
296 
297 	if (error != NULL) {
298 		g_warning (
299 			"%s: Failed to remove contact: %s",
300 			G_STRFUNC, error->message);
301 		g_error_free (error);
302 	}
303 
304 	e_book_client_add_contact (
305 		book_client, lookup->contact, NULL,
306 		add_contact_ready_cb, lookup);
307 }
308 
309 static gint
310 mergeit (EContactMergingLookup *lookup)
311 {
312 	GtkWidget *scrolled_window, *label, *hbox, *dropdown;
313 	GtkWidget *content_area;
314 	GtkWidget *dialog;
315 	GtkTable *table;
316 	EContactField field;
317 	gchar *str = NULL, *string = NULL, *string1 = NULL;
318 	gint num_of_email;
319 	GList *email_attr_list;
320 	gint row = -1;
321 	gint value = 0, result;
322 
323 	dialog = gtk_dialog_new ();
324 	gtk_window_set_title (GTK_WINDOW (dialog), _("Merge Contact"));
325 	gtk_container_set_border_width (GTK_CONTAINER (dialog), 5);
326 
327 	content_area = gtk_dialog_get_content_area (GTK_DIALOG (dialog));
328 
329 	scrolled_window = gtk_scrolled_window_new (NULL, NULL);
330 	gtk_scrolled_window_set_policy (
331 		GTK_SCROLLED_WINDOW (scrolled_window),
332 		GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
333 
334 	table = (GtkTable *) gtk_table_new (20, 2, FALSE);
335 	gtk_container_set_border_width ((GtkContainer *) table, 12);
336 	gtk_table_set_row_spacings (table, 6);
337 	gtk_table_set_col_spacings (table, 2);
338 
339 	gtk_dialog_add_buttons (
340 		GTK_DIALOG (dialog),
341 		GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
342 		_("_Merge"), GTK_RESPONSE_OK,
343 		NULL);
344 
345 	email_attr_list = e_contact_get_attributes (lookup->match, E_CONTACT_EMAIL);
346 	num_of_email = g_list_length (email_attr_list);
347 
348 	/*we match all the string fields of the already existing contact and the new contact.*/
349 	for (field = E_CONTACT_FULL_NAME; field != (E_CONTACT_LAST_SIMPLE_STRING -1); field++) {
350 		dropdown_data *data = NULL;
351 		string = (gchar *) e_contact_get_const (lookup->contact, field);
352 		string1 = (gchar *) e_contact_get_const (lookup->match, field);
353 
354 		/*the field must exist in the new as well as the duplicate contact*/
355 		if (string && *string) {
356 			/*Four email id's present, should be compared with all email id's in duplicate contact */
357 			/*Merge only if number of email id's in existing contact is less than 4 */
358 			if ((field == E_CONTACT_EMAIL_1 || field == E_CONTACT_EMAIL_2
359 			    || field == E_CONTACT_EMAIL_3 || field == E_CONTACT_EMAIL_4) && (num_of_email < 4)) {
360 				EContactField use_field = field;
361 				row++;
362 				str = (gchar *) e_contact_get_const (lookup->contact, use_field);
363 				switch (num_of_email)
364 				{
365 				case 0:
366 					use_field = E_CONTACT_EMAIL_1;
367 					break;
368 				case 1:
369 					/*New contact has email that is NOT equal to email in duplicate contact*/
370 					if ((str && *str) && (g_ascii_strcasecmp (e_contact_get_const (lookup->match, E_CONTACT_EMAIL_1),str))) {
371 						use_field = E_CONTACT_EMAIL_2;
372 						break;
373 					}
374 					else/*Either the new contact has no email OR the email already exist in the duplicate contact */
375 						continue;
376 				case 2:
377 					/*New contact has email and it is equal to neither of the 2 emails in the duplicate contact*/
378 					if ((str && *str) &&
379 							(g_ascii_strcasecmp (str,e_contact_get_const (lookup->match, E_CONTACT_EMAIL_1))) &&
380 							(g_ascii_strcasecmp (e_contact_get_const (lookup->match, E_CONTACT_EMAIL_2),str))) {
381 						use_field = E_CONTACT_EMAIL_3;
382 						break;
383 					}
384 					else
385 						continue;
386 				case 3:
387 					/*New contact has email and it is equal to none of the 3 emails in the duplicate contact*/
388 					if ((str && *str) &&
389 							(g_ascii_strcasecmp (e_contact_get_const (lookup->match, E_CONTACT_EMAIL_1),str)) &&
390 							(g_ascii_strcasecmp (e_contact_get_const (lookup->match, E_CONTACT_EMAIL_2),str)) &&
391 							(g_ascii_strcasecmp (e_contact_get_const (lookup->match, E_CONTACT_EMAIL_3),str)))
392 						use_field = E_CONTACT_EMAIL_4;
393 					else
394 						continue;
395 				}
396 				label = gtk_label_new (_("Email"));
397 				hbox = gtk_hbox_new (FALSE, 0);
398 				gtk_box_pack_start (GTK_BOX (hbox), (GtkWidget *) label, FALSE, FALSE, 0);
399 				gtk_table_attach_defaults (table, (GtkWidget *) hbox, 0, 1, row, row + 1);
400 
401 				dropdown = gtk_combo_box_text_new ();
402 				gtk_combo_box_text_append_text (GTK_COMBO_BOX_TEXT (dropdown), string);
403 
404 				data = g_new0 (dropdown_data, 1);
405 
406 				gtk_combo_box_text_append_text (GTK_COMBO_BOX_TEXT (dropdown), "");
407 
408 				gtk_combo_box_set_active (GTK_COMBO_BOX (dropdown), 0);
409 				data->field = use_field;
410 				data->match = lookup->match;
411 				e_contact_set (lookup->match, use_field, string);
412 				g_signal_connect (
413 					dropdown, "changed",
414 					G_CALLBACK (dropdown_changed), data);
415 
416 				hbox = gtk_hbox_new (FALSE, 0);
417 				gtk_box_pack_start (GTK_BOX (hbox), (GtkWidget *) dropdown, FALSE, FALSE, 0);
418 				gtk_table_attach_defaults (table, (GtkWidget *) hbox, 1, 2, row, row + 1);
419 				gtk_widget_show ((GtkWidget *) dropdown);
420 				continue;
421 			}
422 			if (((field == E_CONTACT_FULL_NAME) && (!g_ascii_strcasecmp (string, string1)))) {
423 				row++;
424 				label = gtk_label_new (e_contact_pretty_name (field));
425 				hbox = gtk_hbox_new (FALSE, 0);
426 				gtk_box_pack_start (GTK_BOX (hbox), (GtkWidget *) label, FALSE, FALSE, 0);
427 				gtk_table_attach_defaults (table, (GtkWidget *) hbox, 0, 1, row, row + 1);
428 
429 				label = gtk_label_new (string);
430 				hbox = gtk_hbox_new (FALSE, 0);
431 				gtk_box_pack_start (GTK_BOX (hbox), (GtkWidget *) label, FALSE, FALSE, 0);
432 				gtk_table_attach_defaults (table, (GtkWidget *) hbox, 1, 2, row, row + 1);
433 				continue;
434 			}
435 
436 			/*for all string fields except name and email*/
437 			if (!(string1 && *string1) || (g_ascii_strcasecmp (string, string1))) {
438 				row++;
439 				label = gtk_label_new (e_contact_pretty_name (field));
440 				hbox = gtk_hbox_new (FALSE, 0);
441 				gtk_box_pack_start (GTK_BOX (hbox), (GtkWidget *) label, FALSE, FALSE, 0);
442 				gtk_table_attach_defaults (table, (GtkWidget *) hbox, 0, 1, row, row + 1);
443 				data = g_new0 (dropdown_data, 1);
444 				dropdown = gtk_combo_box_text_new ();
445 				gtk_combo_box_text_append_text (GTK_COMBO_BOX_TEXT (dropdown), string);
446 				e_contact_set (lookup->match, field, string);
447 
448 				if (string1 && *string1)
449 					gtk_combo_box_text_append_text (GTK_COMBO_BOX_TEXT (dropdown), string1);
450 				else
451 					gtk_combo_box_text_append_text (GTK_COMBO_BOX_TEXT (dropdown), "");
452 
453 				gtk_combo_box_set_active (GTK_COMBO_BOX (dropdown), 0);
454 				data->field = field;
455 				data->match = lookup->match;
456 
457 				if (field == E_CONTACT_NICKNAME || field == E_CONTACT_GIVEN_NAME)
458 					gtk_widget_set_sensitive ((GtkWidget *) dropdown, FALSE);
459 
460 				g_signal_connect (
461 					dropdown, "changed",
462 					G_CALLBACK (dropdown_changed), data);
463 
464 				hbox = gtk_hbox_new (FALSE, 0);
465 				gtk_box_pack_start (GTK_BOX (hbox), (GtkWidget *) dropdown, FALSE, FALSE, 0);
466 				gtk_table_attach_defaults (table, (GtkWidget *) hbox, 1, 2, row, row + 1);
467 				gtk_widget_show_all ((GtkWidget *) dropdown);
468 			}
469 		}
470 	}
471 
472 	gtk_window_set_default_size (GTK_WINDOW (dialog), 420, 300);
473 	gtk_scrolled_window_add_with_viewport (GTK_SCROLLED_WINDOW (scrolled_window), GTK_WIDGET (table));
474 	gtk_box_pack_start (GTK_BOX (content_area), GTK_WIDGET (scrolled_window), TRUE, TRUE, 0);
475 	gtk_widget_show (scrolled_window);
476 	g_signal_connect (
477 		dialog, "map-event",
478 		G_CALLBACK (dialog_map), table);
479 	gtk_widget_show_all ((GtkWidget *) table);
480 	result = gtk_dialog_run (GTK_DIALOG (dialog));
481 
482 	switch (result) {
483 	case GTK_RESPONSE_OK:
484 		g_object_unref (lookup->contact);
485 		lookup->contact = g_object_ref (lookup->match);
486 		e_book_client_remove_contact (
487 			lookup->book_client,
488 			lookup->match, NULL,
489 			remove_contact_ready_cb, lookup);
490 		value = 1;
491 		break;
492 	case GTK_RESPONSE_CANCEL:
493 	default:
494 		value = 0;
495 		break;
496 	}
497 	gtk_widget_destroy (dialog);
498 	g_list_free_full (email_attr_list, (GDestroyNotify) e_vcard_attribute_free);
499 	return value;
500 }
501 
502 static gboolean
503 check_if_same (EContact *contact,
504                EContact *match)
505 {
506 	EContactField field;
507 	GList *email_attr_list;
508 	gint num_of_email;
509 	gchar *str = NULL, *string = NULL, *string1 = NULL;
510 	gboolean res = TRUE;
511 
512 	email_attr_list = e_contact_get_attributes (match, E_CONTACT_EMAIL);
513 	num_of_email = g_list_length (email_attr_list);
514 
515 	for (field = E_CONTACT_FULL_NAME; res && field != (E_CONTACT_LAST_SIMPLE_STRING -1); field++) {
516 
517 		if ((field == E_CONTACT_EMAIL_1 || field == E_CONTACT_EMAIL_2
518 		     || field == E_CONTACT_EMAIL_3 || field == E_CONTACT_EMAIL_4) && (num_of_email < 4)) {
519 			str = (gchar *) e_contact_get_const (contact, field);
520 			switch (num_of_email)
521 			{
522 			case 0:
523 				res = FALSE;
524 				break;
525 			case 1:
526 				if ((str && *str) && (g_ascii_strcasecmp (e_contact_get_const (match, E_CONTACT_EMAIL_1),str)))
527 					res = FALSE;
528 				break;
529 			case 2:
530 				if ((str && *str) && (g_ascii_strcasecmp (str,e_contact_get_const (match, E_CONTACT_EMAIL_1))) &&
531 						(g_ascii_strcasecmp (e_contact_get_const (match, E_CONTACT_EMAIL_2),str)))
532 					res = FALSE;
533 				break;
534 			case 3:
535 				if ((str && *str) && (g_ascii_strcasecmp (e_contact_get_const (match, E_CONTACT_EMAIL_1),str)) &&
536 						(g_ascii_strcasecmp (e_contact_get_const (match, E_CONTACT_EMAIL_2),str)) &&
537 						(g_ascii_strcasecmp (e_contact_get_const (match, E_CONTACT_EMAIL_3),str)))
538 					res = FALSE;
539 				break;
540 			}
541 		}
542 		else {
543 			string = (gchar *) e_contact_get_const (contact, field);
544 			string1 = (gchar *) e_contact_get_const (match, field);
545 			if ((string && *string) && (string1 && *string1) && (g_ascii_strcasecmp (string1, string))) {
546 				res = FALSE;
547 				break;
548 			/*if the field entry exist in either of the contacts,we'll have to give the choice and thus merge button should be sensitive*/
549 			} else if ((string && *string) && !(string1 && *string1)) {
550 				res = FALSE;
551 				break;
552 			}
553 		}
554 	}
555 
556 	g_list_free_full (email_attr_list, (GDestroyNotify) e_vcard_attribute_free);
557 
558 	return res;
559 }
560 
561 static void
562 response (GtkWidget *dialog,
563           gint response,
564           EContactMergingLookup *lookup)
565 {
566 	static gint merge_response;
567 
568 	switch (response) {
569 	case 0:
570 		doit (lookup, FALSE);
571 		break;
572 	case 1:
573 		cancelit (lookup);
574 		break;
575 	case 2:
576 		merge_response = mergeit (lookup);
577 		if (merge_response)
578 			break;
579 		return;
580 	case GTK_RESPONSE_DELETE_EVENT:
581 		cancelit (lookup);
582 		break;
583 	}
584 
585 	gtk_widget_destroy (dialog);
586 }
587 
588 static void
589 match_query_callback (EContact *contact,
590                       EContact *match,
591                       EABContactMatchType type,
592                       gpointer closure)
593 {
594 	EContactMergingLookup *lookup = closure;
595 	gint flag;
596 	gboolean same_uids;
597 
598 	if (lookup->op == E_CONTACT_MERGING_FIND) {
599 		if (lookup->c_cb)
600 			lookup->c_cb (
601 				lookup->book_client, NULL,
602 				(gint) type <= (gint)
603 				EAB_CONTACT_MATCH_VAGUE ? NULL : match,
604 				lookup->closure);
605 
606 		free_lookup (lookup);
607 		finished_lookup ();
608 		return;
609 	}
610 
611 	/* if had same UID, then we are editing old contact, thus force commit change to it */
612 	same_uids = contact && match
613 		&& e_contact_get_const (contact, E_CONTACT_UID)
614 		&& e_contact_get_const (match, E_CONTACT_UID)
615 		&& g_str_equal (e_contact_get_const (contact, E_CONTACT_UID), e_contact_get_const (match, E_CONTACT_UID));
616 
617 	if ((gint) type <= (gint) EAB_CONTACT_MATCH_VAGUE || same_uids) {
618 		doit (lookup, same_uids);
619 	} else {
620 		GtkBuilder *builder;
621 		GtkWidget *container;
622 		GtkWidget *merge_button;
623 		GtkWidget *widget;
624 
625 		/* XXX I think we're leaking the GtkBuilder. */
626 		builder = gtk_builder_new ();
627 
628 		lookup->match = g_object_ref (match);
629 		if (lookup->op == E_CONTACT_MERGING_ADD) {
630 			/* Compares all the values of contacts and return true, if they match */
631 			flag = check_if_same (contact, match);
632 			e_load_ui_builder_definition (
633 				builder, "eab-contact-duplicate-detected.ui");
634 			merge_button = e_builder_get_widget (builder, "button5");
635 			/* Merge Button not sensitive when all values are same */
636 			if (flag)
637 				gtk_widget_set_sensitive (GTK_WIDGET (merge_button), FALSE);
638 		} else if (lookup->op == E_CONTACT_MERGING_COMMIT) {
639 			e_load_ui_builder_definition (
640 				builder, "eab-contact-commit-duplicate-detected.ui");
641 		} else {
642 			doit (lookup, FALSE);
643 			return;
644 		}
645 
646 		widget = e_builder_get_widget (builder, "custom-old-contact");
647 		eab_contact_display_set_mode (
648 			EAB_CONTACT_DISPLAY (widget),
649 			EAB_CONTACT_DISPLAY_RENDER_COMPACT);
650 		eab_contact_display_set_contact (
651 			EAB_CONTACT_DISPLAY (widget), match);
652 
653 		widget = e_builder_get_widget (builder, "custom-new-contact");
654 		eab_contact_display_set_mode (
655 			EAB_CONTACT_DISPLAY (widget),
656 			EAB_CONTACT_DISPLAY_RENDER_COMPACT);
657 		eab_contact_display_set_contact (
658 			EAB_CONTACT_DISPLAY (widget), contact);
659 
660 		widget = e_builder_get_widget (builder, "dialog-duplicate-contact");
661 
662 		gtk_widget_ensure_style (widget);
663 
664 		container = gtk_dialog_get_action_area (GTK_DIALOG (widget));
665 		gtk_container_set_border_width (GTK_CONTAINER (container), 12);
666 
667 		container = gtk_dialog_get_content_area (GTK_DIALOG (widget));
668 		gtk_container_set_border_width (GTK_CONTAINER (container), 0);
669 
670 		g_signal_connect (
671 			widget, "response",
672 			G_CALLBACK (response), lookup);
673 
674 		gtk_widget_show_all (widget);
675 	}
676 }
677 
678 gboolean
679 eab_merging_book_add_contact (ESourceRegistry *registry,
680                               EBookClient *book_client,
681                               EContact *contact,
682                               EABMergingIdAsyncCallback cb,
683                               gpointer closure)
684 {
685 	EContactMergingLookup *lookup;
686 
687 	g_return_val_if_fail (E_IS_SOURCE_REGISTRY (registry), FALSE);
688 
689 	lookup = g_new (EContactMergingLookup, 1);
690 
691 	lookup->op = E_CONTACT_MERGING_ADD;
692 	lookup->registry = g_object_ref (registry);
693 	lookup->book_client = g_object_ref (book_client);
694 	lookup->contact = g_object_ref (contact);
695 	lookup->id_cb = cb;
696 	lookup->closure = closure;
697 	lookup->avoid = NULL;
698 	lookup->match = NULL;
699 
700 	add_lookup (lookup);
701 
702 	return TRUE;
703 }
704 
705 gboolean
706 eab_merging_book_modify_contact (ESourceRegistry *registry,
707                                  EBookClient *book_client,
708                                  EContact *contact,
709                                  EABMergingAsyncCallback cb,
710                                  gpointer closure)
711 {
712 	EContactMergingLookup *lookup;
713 
714 	g_return_val_if_fail (E_IS_SOURCE_REGISTRY (registry), FALSE);
715 
716 	lookup = g_new (EContactMergingLookup, 1);
717 
718 	lookup->op = E_CONTACT_MERGING_COMMIT;
719 	lookup->registry = g_object_ref (registry);
720 	lookup->book_client = g_object_ref (book_client);
721 	lookup->contact = g_object_ref (contact);
722 	lookup->cb = cb;
723 	lookup->closure = closure;
724 	lookup->avoid = g_list_append (NULL, contact);
725 	lookup->match = NULL;
726 
727 	add_lookup (lookup);
728 
729 	return TRUE;
730 }
731 
732 gboolean
733 eab_merging_book_find_contact (ESourceRegistry *registry,
734                                EBookClient *book_client,
735                                EContact *contact,
736                                EABMergingContactAsyncCallback cb,
737                                gpointer closure)
738 {
739 	EContactMergingLookup *lookup;
740 
741 	lookup = g_new (EContactMergingLookup, 1);
742 
743 	lookup->op = E_CONTACT_MERGING_FIND;
744 	lookup->registry = g_object_ref (registry);
745 	lookup->book_client = g_object_ref (book_client);
746 	lookup->contact = g_object_ref (contact);
747 	lookup->c_cb = cb;
748 	lookup->closure = closure;
749 	lookup->avoid = g_list_append (NULL, contact);
750 	lookup->match = NULL;
751 
752 	add_lookup (lookup);
753 
754 	return TRUE;
755 }