evolution-3.6.4/addressbook/gui/contact-editor/e-contact-quick-add.c

No issues found

  1 /*
  2  * This program is free software; you can redistribute it and/or
  3  * modify it under the terms of the GNU Lesser General Public
  4  * License as published by the Free Software Foundation; either
  5  * version 2 of the License, or (at your option) version 3.
  6  *
  7  * This program is distributed in the hope that it will be useful,
  8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 10  * Lesser General Public License for more details.
 11  *
 12  * You should have received a copy of the GNU Lesser General Public
 13  * License along with the program; if not, see <http://www.gnu.org/licenses/>
 14  *
 15  *
 16  * Authors:
 17  *		Jon Trowbridge <trow@ximian.com>
 18  *
 19  * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
 20  *
 21  */
 22 
 23 #ifdef HAVE_CONFIG_H
 24 #include <config.h>
 25 #endif
 26 
 27 #include <ctype.h>
 28 #include <string.h>
 29 #include <gtk/gtk.h>
 30 #include <glib/gi18n.h>
 31 
 32 #include <libedataserverui/libedataserverui.h>
 33 
 34 #include <addressbook/util/eab-book-util.h>
 35 #include "e-contact-editor.h"
 36 #include "e-contact-quick-add.h"
 37 #include "eab-contact-merging.h"
 38 #include "libevolution-utils/e-alert-dialog.h"
 39 
 40 typedef struct _QuickAdd QuickAdd;
 41 struct _QuickAdd {
 42 	gchar *name;
 43 	gchar *email;
 44 	gchar *vcard;
 45 	EContact *contact;
 46 	GCancellable *cancellable;
 47 	ESourceRegistry *registry;
 48 	ESource *source;
 49 
 50 	EContactQuickAddCallback cb;
 51 	gpointer closure;
 52 
 53 	GtkWidget *dialog;
 54 	GtkWidget *name_entry;
 55 	GtkWidget *email_entry;
 56 	GtkWidget *combo_box;
 57 
 58 	gint refs;
 59 
 60 };
 61 
 62 static QuickAdd *
 63 quick_add_new (ESourceRegistry *registry)
 64 {
 65 	QuickAdd *qa = g_new0 (QuickAdd, 1);
 66 	qa->contact = e_contact_new ();
 67 	qa->registry = g_object_ref (registry);
 68 	qa->refs = 1;
 69 	return qa;
 70 }
 71 
 72 static void
 73 quick_add_unref (QuickAdd *qa)
 74 {
 75 	if (qa) {
 76 		--qa->refs;
 77 		if (qa->refs == 0) {
 78 			if (qa->cancellable != NULL) {
 79 				g_cancellable_cancel (qa->cancellable);
 80 				g_object_unref (qa->cancellable);
 81 			}
 82 			g_free (qa->name);
 83 			g_free (qa->email);
 84 			g_free (qa->vcard);
 85 			g_object_unref (qa->contact);
 86 			g_object_unref (qa->registry);
 87 			g_free (qa);
 88 		}
 89 	}
 90 }
 91 
 92 static void
 93 quick_add_set_name (QuickAdd *qa,
 94                     const gchar *name)
 95 {
 96 	if (name == qa->name)
 97 		return;
 98 
 99 	g_free (qa->name);
100 	qa->name = g_strdup (name);
101 }
102 
103 static void
104 quick_add_set_email (QuickAdd *qa,
105                      const gchar *email)
106 {
107 	if (email == qa->email)
108 		return;
109 
110 	g_free (qa->email);
111 	qa->email = g_strdup (email);
112 }
113 
114 static void
115 quick_add_set_vcard (QuickAdd *qa,
116                      const gchar *vcard)
117 {
118 	if (vcard == qa->vcard)
119 		return;
120 
121 	g_free (qa->vcard);
122 	qa->vcard = g_strdup (vcard);
123 }
124 
125 static void
126 merge_cb (GObject *source_object,
127           GAsyncResult *result,
128           gpointer user_data)
129 {
130 	ESource *source = E_SOURCE (source_object);
131 	QuickAdd *qa = user_data;
132 	EClient *client = NULL;
133 	GError *error = NULL;
134 
135 	e_client_utils_open_new_finish (source, result, &client, &error);
136 
137 	/* Ignore cancellations. */
138 	if (g_error_matches (error, E_CLIENT_ERROR, E_CLIENT_ERROR_CANCELLED) ||
139 	    g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) {
140 		g_warn_if_fail (client == NULL);
141 		g_error_free (error);
142 		return;
143 	}
144 
145 	if (error != NULL) {
146 		g_warn_if_fail (client == NULL);
147 		if (qa->cb)
148 			qa->cb (NULL, qa->closure);
149 		g_error_free (error);
150 		quick_add_unref (qa);
151 		return;
152 	}
153 
154 	g_return_if_fail (E_IS_CLIENT (client));
155 
156 	if (!e_client_is_readonly (client))
157 		eab_merging_book_add_contact (
158 			qa->registry, E_BOOK_CLIENT (client),
159 			qa->contact, NULL, NULL);
160 	else
161 		e_alert_run_dialog_for_args (
162 			e_shell_get_active_window (NULL),
163 			"addressbook:error-read-only",
164 			e_source_get_display_name (source),
165 			NULL);
166 
167 	if (qa->cb)
168 		qa->cb (qa->contact, qa->closure);
169 
170 	g_object_unref (client);
171 
172 	quick_add_unref (qa);
173 }
174 
175 static void
176 quick_add_merge_contact (QuickAdd *qa)
177 {
178 	if (qa->cancellable != NULL) {
179 		g_cancellable_cancel (qa->cancellable);
180 		g_object_unref (qa->cancellable);
181 	}
182 
183 	qa->cancellable = g_cancellable_new ();
184 
185 	e_client_utils_open_new (
186 		qa->source, E_CLIENT_SOURCE_TYPE_CONTACTS,
187 		FALSE, qa->cancellable, merge_cb, qa);
188 }
189 
190 /* Raise a contact editor with all fields editable,
191  * and hook up all signals accordingly. */
192 
193 static void
194 contact_added_cb (EContactEditor *ce,
195                   const GError *error,
196                   EContact *contact,
197                   gpointer closure)
198 {
199 	QuickAdd *qa;
200 
201 	qa = g_object_get_data (G_OBJECT (ce), "quick_add");
202 
203 	if (qa) {
204 		if (qa->cb)
205 			qa->cb (qa->contact, qa->closure);
206 
207 		/* We don't need to unref qa because we set_data_full below */
208 		g_object_set_data (G_OBJECT (ce), "quick_add", NULL);
209 	}
210 }
211 
212 static void
213 editor_closed_cb (GtkWidget *w,
214                   gpointer closure)
215 {
216 	QuickAdd *qa;
217 
218 	qa = g_object_get_data (G_OBJECT (w), "quick_add");
219 
220 	if (qa)
221 		/* We don't need to unref qa because we set_data_full below */
222 		g_object_set_data (G_OBJECT (w), "quick_add", NULL);
223 }
224 
225 static void
226 ce_have_contact (EBookClient *book_client,
227                  const GError *error,
228                  EContact *contact,
229                  gpointer closure)
230 {
231 	QuickAdd *qa = (QuickAdd *) closure;
232 
233 	if (error) {
234 		if (book_client)
235 			g_object_unref (book_client);
236 		g_warning (
237 			"Failed to find contact, status %d (%s).",
238 			error->code, error->message);
239 		quick_add_unref (qa);
240 	} else {
241 		EShell *shell;
242 		EABEditor *contact_editor;
243 
244 		if (contact) {
245 			/* use found contact */
246 			if (qa->contact)
247 				g_object_unref (qa->contact);
248 			qa->contact = g_object_ref (contact);
249 		}
250 
251 		shell = e_shell_get_default ();
252 		contact_editor = e_contact_editor_new (
253 			shell, book_client, qa->contact, TRUE, TRUE /* XXX */);
254 
255 		/* Mark it as changed so the Save buttons are
256 		 * enabled when we bring up the dialog. */
257 		g_object_set (
258 			contact_editor, "changed", contact != NULL, NULL);
259 
260 		/* We pass this via object data, so that we don't get a
261 		 * dangling pointer referenced if both the "contact_added"
262 		 * and "editor_closed" get emitted.  (Which, based on a
263 		 * backtrace in bugzilla, I think can happen and cause a
264 		 * crash. */
265 		g_object_set_data_full (
266 			G_OBJECT (contact_editor), "quick_add", qa,
267 			(GDestroyNotify) quick_add_unref);
268 
269 		g_signal_connect (
270 			contact_editor, "contact_added",
271 			G_CALLBACK (contact_added_cb), NULL);
272 		g_signal_connect (
273 			contact_editor, "editor_closed",
274 			G_CALLBACK (editor_closed_cb), NULL);
275 
276 		g_object_unref (book_client);
277 	}
278 }
279 
280 static void
281 ce_have_book (GObject *source_object,
282               GAsyncResult *result,
283               gpointer user_data)
284 {
285 	ESource *source = E_SOURCE (source_object);
286 	QuickAdd *qa = user_data;
287 	EClient *client = NULL;
288 	GError *error = NULL;
289 
290 	e_client_utils_open_new_finish (source, result, &client, &error);
291 
292 	/* Ignore cancellations. */
293 	if (g_error_matches (error, E_CLIENT_ERROR, E_CLIENT_ERROR_CANCELLED) ||
294 	    g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) {
295 		g_warn_if_fail (client == NULL);
296 		g_error_free (error);
297 		return;
298 	}
299 
300 	if (error != NULL) {
301 		g_warn_if_fail (client == NULL);
302 		g_warning (
303 			"Couldn't open local address book (%s).",
304 			error->message);
305 		quick_add_unref (qa);
306 		g_error_free (error);
307 		return;
308 	}
309 
310 	g_return_if_fail (E_IS_CLIENT (client));
311 
312 	eab_merging_book_find_contact (
313 		qa->registry, E_BOOK_CLIENT (client),
314 		qa->contact, ce_have_contact, qa);
315 }
316 
317 static void
318 edit_contact (QuickAdd *qa)
319 {
320 	if (qa->cancellable != NULL) {
321 		g_cancellable_cancel (qa->cancellable);
322 		g_object_unref (qa->cancellable);
323 	}
324 
325 	qa->cancellable = g_cancellable_new ();
326 
327 	e_client_utils_open_new (
328 		qa->source, E_CLIENT_SOURCE_TYPE_CONTACTS,
329 		FALSE, qa->cancellable, ce_have_book, qa);
330 }
331 
332 #define QUICK_ADD_RESPONSE_EDIT_FULL 2
333 
334 static void
335 clicked_cb (GtkWidget *w,
336             gint button,
337             gpointer closure)
338 {
339 	QuickAdd *qa = (QuickAdd *) closure;
340 
341 	/* Get data out of entries. */
342 	if (!qa->vcard && (button == GTK_RESPONSE_OK ||
343 			button == QUICK_ADD_RESPONSE_EDIT_FULL)) {
344 		gchar *name = NULL;
345 		gchar *email = NULL;
346 
347 		if (qa->name_entry)
348 			name = gtk_editable_get_chars (
349 				GTK_EDITABLE (qa->name_entry), 0, -1);
350 
351 		if (qa->email_entry)
352 			email = gtk_editable_get_chars (
353 				GTK_EDITABLE (qa->email_entry), 0, -1);
354 
355 		e_contact_set (
356 			qa->contact, E_CONTACT_FULL_NAME,
357 			(name != NULL) ? name : "");
358 
359 		e_contact_set (
360 			qa->contact, E_CONTACT_EMAIL_1,
361 			(email != NULL) ? email : "");
362 
363 		g_free (name);
364 		g_free (email);
365 	}
366 
367 	gtk_widget_destroy (w);
368 
369 	if (button == GTK_RESPONSE_OK) {
370 
371 		/* OK */
372 		quick_add_merge_contact (qa);
373 
374 	} else if (button == QUICK_ADD_RESPONSE_EDIT_FULL) {
375 
376 		/* EDIT FULL */
377 		edit_contact (qa);
378 
379 	} else {
380 		/* CANCEL */
381 		quick_add_unref (qa);
382 	}
383 
384 }
385 
386 static void
387 sanitize_widgets (QuickAdd *qa)
388 {
389 	GtkComboBox *combo_box;
390 	const gchar *active_id;
391 	gboolean enabled = TRUE;
392 
393 	g_return_if_fail (qa != NULL);
394 	g_return_if_fail (qa->dialog != NULL);
395 
396 	combo_box = GTK_COMBO_BOX (qa->combo_box);
397 	active_id = gtk_combo_box_get_active_id (combo_box);
398 	enabled = (active_id != NULL);
399 
400 	gtk_dialog_set_response_sensitive (
401 		GTK_DIALOG (qa->dialog),
402 		QUICK_ADD_RESPONSE_EDIT_FULL, enabled);
403 	gtk_dialog_set_response_sensitive (
404 		GTK_DIALOG (qa->dialog), GTK_RESPONSE_OK, enabled);
405 }
406 
407 static void
408 source_changed (ESourceComboBox *source_combo_box,
409                 QuickAdd *qa)
410 {
411 	ESource *source;
412 
413 	source = e_source_combo_box_ref_active (source_combo_box);
414 
415 	if (source != NULL) {
416 		if (qa->source != NULL)
417 			g_object_unref (qa->source);
418 		qa->source = source;  /* takes reference */
419 	}
420 
421 	sanitize_widgets (qa);
422 }
423 
424 static GtkWidget *
425 build_quick_add_dialog (QuickAdd *qa)
426 {
427 	GtkWidget *container;
428 	GtkWidget *dialog;
429 	GtkWidget *label;
430 	GtkTable *table;
431 	ESource *source;
432 	const gchar *extension_name;
433 	const gint xpad = 0, ypad = 0;
434 
435 	g_return_val_if_fail (qa != NULL, NULL);
436 
437 	dialog = gtk_dialog_new_with_buttons (
438 		_("Contact Quick-Add"),
439 		e_shell_get_active_window (NULL),
440 		0,
441 		_("_Edit Full"), QUICK_ADD_RESPONSE_EDIT_FULL,
442 		GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
443 		GTK_STOCK_OK, GTK_RESPONSE_OK,
444 		NULL);
445 
446 	gtk_widget_ensure_style (dialog);
447 
448 	container = gtk_dialog_get_action_area (GTK_DIALOG (dialog));
449 	gtk_container_set_border_width (GTK_CONTAINER (container), 12);
450 	container = gtk_dialog_get_content_area (GTK_DIALOG (dialog));
451 	gtk_container_set_border_width (GTK_CONTAINER (container), 0);
452 
453 	g_signal_connect (
454 		dialog, "response",
455 		G_CALLBACK (clicked_cb), qa);
456 
457 	qa->dialog = dialog;
458 
459 	qa->name_entry = gtk_entry_new ();
460 	if (qa->name)
461 		gtk_entry_set_text (GTK_ENTRY (qa->name_entry), qa->name);
462 
463 	qa->email_entry = gtk_entry_new ();
464 	if (qa->email)
465 		gtk_entry_set_text (GTK_ENTRY (qa->email_entry), qa->email);
466 
467 	if (qa->vcard) {
468 		/* when adding vCard, then do not allow change name or email */
469 		gtk_widget_set_sensitive (qa->name_entry, FALSE);
470 		gtk_widget_set_sensitive (qa->email_entry, FALSE);
471 	}
472 
473 	extension_name = E_SOURCE_EXTENSION_ADDRESS_BOOK;
474 	source = e_source_registry_ref_default_address_book (qa->registry);
475 
476 	qa->combo_box = e_source_combo_box_new (qa->registry, extension_name);
477 	e_source_combo_box_set_active (
478 		E_SOURCE_COMBO_BOX (qa->combo_box), source);
479 
480 	g_object_unref (source);
481 
482 	source_changed (E_SOURCE_COMBO_BOX (qa->combo_box), qa);
483 	g_signal_connect (
484 		qa->combo_box, "changed",
485 		G_CALLBACK (source_changed), qa);
486 
487 	table = GTK_TABLE (gtk_table_new (3, 2, FALSE));
488 	gtk_table_set_row_spacings (table, 6);
489 	gtk_table_set_col_spacings (table, 12);
490 
491 	label = gtk_label_new_with_mnemonic (_("_Full name"));
492 	gtk_label_set_mnemonic_widget ((GtkLabel *) label, qa->name_entry);
493 	gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
494 
495 	gtk_table_attach (
496 		table, label,
497 		0, 1, 0, 1,
498 		GTK_FILL, 0, xpad, ypad);
499 	gtk_table_attach (
500 		table, qa->name_entry,
501 		1, 2, 0, 1,
502 		GTK_EXPAND | GTK_FILL, 0, xpad, ypad);
503 
504 	label = gtk_label_new_with_mnemonic (_("E_mail"));
505 	gtk_label_set_mnemonic_widget ((GtkLabel *) label, qa->email_entry);
506 	gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
507 
508 	gtk_table_attach (
509 		table, label,
510 		0, 1, 1, 2,
511 		GTK_FILL, 0, xpad, ypad);
512 	gtk_table_attach (
513 		table, qa->email_entry,
514 		1, 2, 1, 2,
515 		GTK_EXPAND | GTK_FILL, 0, xpad, ypad);
516 
517 	label = gtk_label_new_with_mnemonic (_("_Select Address Book"));
518 	gtk_label_set_mnemonic_widget ((GtkLabel *) label, qa->combo_box);
519 	gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
520 
521 	gtk_table_attach (
522 		table, label,
523 		0, 1, 2, 3,
524 		GTK_FILL, 0, xpad, ypad);
525 	gtk_table_attach (
526 		table, qa->combo_box,
527 		1, 2, 2, 3,
528 		GTK_EXPAND | GTK_FILL, 0, xpad, ypad);
529 
530 	gtk_container_set_border_width (GTK_CONTAINER (table), 12);
531 	container = gtk_dialog_get_content_area (GTK_DIALOG (dialog));
532 	gtk_box_pack_start (
533 		GTK_BOX (container), GTK_WIDGET (table), FALSE, FALSE, 0);
534 	gtk_widget_show_all (GTK_WIDGET (table));
535 
536 	return dialog;
537 }
538 
539 void
540 e_contact_quick_add (ESourceRegistry *registry,
541                      const gchar *in_name,
542                      const gchar *email,
543                      EContactQuickAddCallback cb,
544                      gpointer closure)
545 {
546 	QuickAdd *qa;
547 	GtkWidget *dialog;
548 	gchar *name = NULL;
549 	gint len;
550 
551 	g_return_if_fail (E_IS_SOURCE_REGISTRY (registry));
552 
553 	/* We need to have *something* to work with. */
554 	if (in_name == NULL && email == NULL) {
555 		if (cb)
556 			cb (NULL, closure);
557 		return;
558 	}
559 
560 	if (in_name) {
561 		name = g_strdup (in_name);
562 
563 		/* Remove extra whitespace and the quotes some mailers put around names. */
564 		g_strstrip (name);
565 		len = strlen (name);
566 		if ((name[0] == '\'' && name[len - 1] == '\'') ||
567 			(name[0] == '"' && name[len - 1] == '"')) {
568 			name[0] = ' ';
569 			name[len - 1] = ' ';
570 		}
571 		g_strstrip (name);
572 	}
573 
574 	qa = quick_add_new (registry);
575 	qa->cb = cb;
576 	qa->closure = closure;
577 	if (name)
578 		quick_add_set_name (qa, name);
579 	if (email)
580 		quick_add_set_email (qa, email);
581 
582 	dialog = build_quick_add_dialog (qa);
583 	gtk_widget_show_all (dialog);
584 
585 	g_free (name);
586 }
587 
588 void
589 e_contact_quick_add_free_form (ESourceRegistry *registry,
590                                const gchar *text,
591                                EContactQuickAddCallback cb,
592                                gpointer closure)
593 {
594 	gchar *name = NULL, *email = NULL;
595 	const gchar *last_at, *s;
596 	gboolean in_quote;
597 
598 	g_return_if_fail (E_IS_SOURCE_REGISTRY (registry));
599 
600 	if (text == NULL) {
601 		e_contact_quick_add (registry, NULL, NULL, cb, closure);
602 		return;
603 	}
604 
605 	/* Look for things that look like e-mail addresses embedded in text */
606 	in_quote = FALSE;
607 	last_at = NULL;
608 	for (s = text; *s; ++s) {
609 		if (*s == '@' && !in_quote)
610 			last_at = s;
611 		else if (*s == '"')
612 			in_quote = !in_quote;
613 	}
614 
615 	if (last_at == NULL) {
616 		/* No at sign, so we treat it all as the name */
617 		name = g_strdup (text);
618 	} else {
619 		gboolean bad_char = FALSE;
620 
621 		/* walk backwards to whitespace or a < or a quote... */
622 		while (last_at >= text && !bad_char
623 		       && !(isspace ((gint) *last_at) ||
624 			  *last_at == '<' ||
625 			  *last_at == '"')) {
626 			/* Check for some stuff that can't appear in a legal e-mail address. */
627 			if (*last_at == '['
628 			    || *last_at == ']'
629 			    || *last_at == '('
630 			    || *last_at == ')')
631 				bad_char = TRUE;
632 			--last_at;
633 		}
634 		if (last_at < text)
635 			last_at = text;
636 
637 		/* ...and then split the text there */
638 		if (!bad_char) {
639 			if (text < last_at)
640 				name = g_strndup (text, last_at - text);
641 			email = g_strdup (last_at);
642 		}
643 	}
644 
645 	/* If all else has failed, make it the name. */
646 	if (name == NULL && email == NULL)
647 		name = g_strdup (text);
648 
649 	/* Clean up email, remove bracketing <>s */
650 	if (email && *email) {
651 		gboolean changed = FALSE;
652 		g_strstrip (email);
653 		if (*email == '<') {
654 			*email = ' ';
655 			changed = TRUE;
656 		}
657 		if (email[strlen (email) - 1] == '>') {
658 			email[strlen (email) - 1] = ' ';
659 			changed = TRUE;
660 		}
661 		if (changed)
662 			g_strstrip (email);
663 	}
664 
665 	e_contact_quick_add (registry, name, email, cb, closure);
666 
667 	g_free (name);
668 	g_free (email);
669 }
670 
671 void
672 e_contact_quick_add_email (ESourceRegistry *registry,
673                            const gchar *email,
674                            EContactQuickAddCallback cb,
675                            gpointer closure)
676 {
677 	gchar *name = NULL;
678 	gchar *addr = NULL;
679 	gchar *lt, *gt;
680 
681 	/* Handle something of the form "Foo <foo@bar.com>".  This is more
682 	 * more forgiving than the free-form parser, allowing for unquoted
683 	 * whitespace since we know the whole string is an email address. */
684 
685 	lt = (email != NULL) ? strchr (email, '<') : NULL;
686 	gt = (lt != NULL) ? strchr (email, '>') : NULL;
687 
688 	if (lt != NULL && gt != NULL && (gt - lt) > 0) {
689 		name = g_strndup (email, lt - email);
690 		addr = g_strndup (lt + 1, gt - lt - 1);
691 	} else {
692 		addr = g_strdup (email);
693 	}
694 
695 	e_contact_quick_add (registry, name, addr, cb, closure);
696 
697 	g_free (name);
698 	g_free (addr);
699 }
700 
701 void
702 e_contact_quick_add_vcard (ESourceRegistry *registry,
703                            const gchar *vcard,
704                            EContactQuickAddCallback cb,
705                            gpointer closure)
706 {
707 	QuickAdd *qa;
708 	GtkWidget *dialog;
709 	EContact *contact;
710 
711 	g_return_if_fail (E_IS_SOURCE_REGISTRY (registry));
712 
713 	/* We need to have *something* to work with. */
714 	if (vcard == NULL) {
715 		if (cb)
716 			cb (NULL, closure);
717 		return;
718 	}
719 
720 	qa = quick_add_new (registry);
721 	qa->cb = cb;
722 	qa->closure = closure;
723 	quick_add_set_vcard (qa, vcard);
724 
725 	contact = e_contact_new_from_vcard (qa->vcard);
726 
727 	if (contact) {
728 		GList *emails;
729 		gchar *name;
730 		EContactName *contact_name;
731 
732 		g_object_unref (qa->contact);
733 		qa->contact = contact;
734 
735 		contact_name = e_contact_get (qa->contact, E_CONTACT_NAME);
736 		name = e_contact_name_to_string (contact_name);
737 		quick_add_set_name (qa, name);
738 		g_free (name);
739 		e_contact_name_free (contact_name);
740 
741 		emails = e_contact_get (qa->contact, E_CONTACT_EMAIL);
742 		if (emails) {
743 			quick_add_set_email (qa, emails->data);
744 
745 			g_list_foreach (emails, (GFunc) g_free, NULL);
746 			g_list_free (emails);
747 		}
748 	} else {
749 		if (cb)
750 			cb (NULL, closure);
751 
752 		quick_add_unref (qa);
753 		g_warning ("Contact's vCard parsing failed!");
754 		return;
755 	}
756 
757 	dialog = build_quick_add_dialog (qa);
758 	gtk_widget_show_all (dialog);
759 }