diff options
Diffstat (limited to 'addressbook/gui/contact-editor/e-contact-quick-add.c')
-rw-r--r-- | addressbook/gui/contact-editor/e-contact-quick-add.c | 731 |
1 files changed, 519 insertions, 212 deletions
diff --git a/addressbook/gui/contact-editor/e-contact-quick-add.c b/addressbook/gui/contact-editor/e-contact-quick-add.c index e8d623afb0..5814205c4d 100644 --- a/addressbook/gui/contact-editor/e-contact-quick-add.c +++ b/addressbook/gui/contact-editor/e-contact-quick-add.c @@ -1,286 +1,395 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ - -/* - * e-contact-quick-add.c - * - * Copyright (C) 2001 Ximian, Inc. - * - * Developed by Jon Trowbridge <trow@ximian.com> - */ - /* * This program is free software; you can redistribute it and/or - * modify it under the terms of version 2 of the GNU General Public - * License as published by the Free Software Foundation. - * + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) version 3. + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA. + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with the program; if not, see <http://www.gnu.org/licenses/> + * + * + * Authors: + * Jon Trowbridge <trow@ximian.com> + * + * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) + * */ +#ifdef HAVE_CONFIG_H #include <config.h> +#endif + #include <ctype.h> -#include <glib.h> -#include <gtk/gtkentry.h> -#include <gtk/gtklabel.h> -#include <gtk/gtktable.h> -#include <libgnome/gnome-defs.h> -#include <libgnome/gnome-i18n.h> -#include <libgnomeui/gnome-app.h> -#include <libgnomeui/gnome-dialog.h> -#include <libgnomeui/gnome-stock.h> -#include <gal/widgets/e-unicode.h> -#include <addressbook/gui/component/addressbook.h> -#include <addressbook/backend/ebook/e-book.h> -#include <addressbook/backend/ebook/e-book-util.h> -#include <addressbook/backend/ebook/e-card.h> +#include <string.h> +#include <gtk/gtk.h> +#include <glib/gi18n.h> + +#include <addressbook/util/eab-book-util.h> #include "e-contact-editor.h" #include "e-contact-quick-add.h" -#include "e-card-merging.h" +#include "eab-contact-merging.h" typedef struct _QuickAdd QuickAdd; struct _QuickAdd { gchar *name; gchar *email; - ECard *card; + gchar *vcard; + EContact *contact; + GCancellable *cancellable; + EClientCache *client_cache; + ESource *source; EContactQuickAddCallback cb; gpointer closure; + GtkWidget *dialog; GtkWidget *name_entry; GtkWidget *email_entry; + GtkWidget *combo_box; gint refs; }; static QuickAdd * -quick_add_new (void) +quick_add_new (EClientCache *client_cache) { QuickAdd *qa = g_new0 (QuickAdd, 1); - qa->card = e_card_new (""); + qa->contact = e_contact_new (); + qa->client_cache = g_object_ref (client_cache); qa->refs = 1; return qa; } static void -quick_add_ref (QuickAdd *qa) -{ - if (qa) { - ++qa->refs; - } -} - -static void quick_add_unref (QuickAdd *qa) { if (qa) { --qa->refs; if (qa->refs == 0) { + if (qa->cancellable != NULL) { + g_cancellable_cancel (qa->cancellable); + g_object_unref (qa->cancellable); + } g_free (qa->name); g_free (qa->email); - gtk_object_unref (GTK_OBJECT (qa->card)); + g_free (qa->vcard); + g_object_unref (qa->contact); + g_object_unref (qa->client_cache); g_free (qa); } } } static void -quick_add_set_name (QuickAdd *qa, const gchar *name) +quick_add_set_name (QuickAdd *qa, + const gchar *name) { - ECardName *card_name; - if (name == qa->name) return; g_free (qa->name); - - card_name = e_card_name_from_string (name); - qa->name = e_card_name_to_string (card_name); - - gtk_object_set (GTK_OBJECT (qa->card), - "full_name", qa->name, - NULL); - - e_card_name_unref (card_name); + qa->name = g_strdup (name); } static void -quick_add_set_email (QuickAdd *qa, const gchar *email) +quick_add_set_email (QuickAdd *qa, + const gchar *email) { - ECardSimple *simple; - if (email == qa->email) return; g_free (qa->email); qa->email = g_strdup (email); +} + +static void +quick_add_set_vcard (QuickAdd *qa, + const gchar *vcard) +{ + if (vcard == qa->vcard) + return; - simple = e_card_simple_new (qa->card); - e_card_simple_set (simple, E_CARD_SIMPLE_FIELD_EMAIL, email); - e_card_simple_sync_card (simple); - gtk_object_unref (GTK_OBJECT (simple)); + g_free (qa->vcard); + qa->vcard = g_strdup (vcard); } static void -merge_cb (EBook *book, EBookStatus status, gpointer closure) +merge_cb (GObject *source_object, + GAsyncResult *result, + gpointer user_data) { - QuickAdd *qa = (QuickAdd *) closure; + QuickAdd *qa = user_data; + EClient *client; + GError *error = NULL; + + client = e_client_cache_get_client_finish ( + E_CLIENT_CACHE (source_object), result, &error); + + /* Sanity check. */ + g_return_if_fail ( + ((client != NULL) && (error == NULL)) || + ((client == NULL) && (error != NULL))); + + /* Ignore cancellations. */ + if (g_error_matches (error, E_CLIENT_ERROR, E_CLIENT_ERROR_CANCELLED) || + g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) { + g_warn_if_fail (client == NULL); + g_error_free (error); + return; + } - if (book != NULL) { - e_card_merging_book_add_card (book, qa->card, NULL, NULL); - if (qa->cb) - qa->cb (qa->card, qa->closure); - gtk_object_unref (GTK_OBJECT (book)); - } else { - /* Something went wrong. */ + if (error != NULL) { if (qa->cb) qa->cb (NULL, qa->closure); + g_error_free (error); + quick_add_unref (qa); + return; + } + + if (!e_client_is_readonly (client)) { + ESourceRegistry *registry; + + registry = e_client_cache_ref_registry (qa->client_cache); + + eab_merging_book_add_contact ( + registry, E_BOOK_CLIENT (client), + qa->contact, NULL, NULL); + + g_object_unref (registry); + } else { + ESource *source = e_client_get_source (client); + + e_alert_run_dialog_for_args ( + e_shell_get_active_window (NULL), + "addressbook:error-read-only", + e_source_get_display_name (source), + NULL); } - + + if (qa->cb) + qa->cb (qa->contact, qa->closure); + + g_object_unref (client); + quick_add_unref (qa); } static void -quick_add_merge_card (QuickAdd *qa) +quick_add_merge_contact (QuickAdd *qa) { - EBook *book; + if (qa->cancellable != NULL) { + g_cancellable_cancel (qa->cancellable); + g_object_unref (qa->cancellable); + } - quick_add_ref (qa); + qa->cancellable = g_cancellable_new (); - book = e_book_new (); - if (!addressbook_load_default_book (book, merge_cb, qa)) { - gtk_object_unref (GTK_OBJECT (book)); - merge_cb (book, E_BOOK_STATUS_OTHER_ERROR, qa); - } + e_client_cache_get_client ( + qa->client_cache, qa->source, + E_SOURCE_EXTENSION_ADDRESS_BOOK, + qa->cancellable, merge_cb, qa); } - -/* - * Raise a contact editor with all fields editable, and hook up all signals accordingly. - */ +/* Raise a contact editor with all fields editable, + * and hook up all signals accordingly. */ static void -card_added_cb (EContactEditor *ce, EBookStatus status, ECard *card, gpointer closure) +contact_added_cb (EContactEditor *ce, + const GError *error, + EContact *contact, + gpointer closure) { - QuickAdd *qa = (QuickAdd *) gtk_object_get_data (GTK_OBJECT (ce), "quick_add"); + QuickAdd *qa; - if (qa) { + qa = g_object_get_data (G_OBJECT (ce), "quick_add"); + if (qa) { if (qa->cb) - qa->cb (qa->card, qa->closure); - + qa->cb (qa->contact, qa->closure); + /* We don't need to unref qa because we set_data_full below */ - gtk_object_set_data (GTK_OBJECT (ce), "quick_add", NULL); + g_object_set_data (G_OBJECT (ce), "quick_add", NULL); } } static void -editor_closed_cb (GtkWidget *w, gpointer closure) +editor_closed_cb (GtkWidget *w, + gpointer closure) { - QuickAdd *qa = (QuickAdd *) gtk_object_get_data (GTK_OBJECT (w), "quick_add"); + QuickAdd *qa; + + qa = g_object_get_data (G_OBJECT (w), "quick_add"); if (qa) /* We don't need to unref qa because we set_data_full below */ - gtk_object_set_data (GTK_OBJECT (w), "quick_add", NULL); - - gtk_object_unref (GTK_OBJECT (w)); + g_object_set_data (G_OBJECT (w), "quick_add", NULL); } static void -ce_have_book (EBook *book, EBookStatus status, gpointer closure) +ce_have_contact (EBookClient *book_client, + const GError *error, + EContact *contact, + gpointer closure) { QuickAdd *qa = (QuickAdd *) closure; - if (book == NULL) { - g_warning ("Couldn't open local address book."); + if (error) { + if (book_client) + g_object_unref (book_client); + g_warning ( + "Failed to find contact, status %d (%s).", + error->code, error->message); quick_add_unref (qa); } else { - EContactEditor *contact_editor = e_contact_editor_new (book, qa->card, TRUE, TRUE /* XXX */); - - /* mark it as changed so the Save buttons are enabled when we bring up the dialog. */ - gtk_object_set (GTK_OBJECT(contact_editor), - "changed", TRUE, - NULL); - - /* We pass this via object data, so that we don't get a dangling pointer referenced if both - the "card_added" and "editor_closed" get emitted. (Which, based on a backtrace in bugzilla, - I think can happen and cause a crash. */ - gtk_object_set_data_full (GTK_OBJECT (contact_editor), "quick_add", qa, - (GtkDestroyNotify) quick_add_unref); - - gtk_signal_connect (GTK_OBJECT (contact_editor), - "card_added", - GTK_SIGNAL_FUNC (card_added_cb), - NULL); - gtk_signal_connect (GTK_OBJECT (contact_editor), - "editor_closed", - GTK_SIGNAL_FUNC (editor_closed_cb), - NULL); - - gtk_object_unref (GTK_OBJECT (book)); + EShell *shell; + EABEditor *contact_editor; + + if (contact) { + /* use found contact */ + if (qa->contact) + g_object_unref (qa->contact); + qa->contact = g_object_ref (contact); + } + + shell = e_shell_get_default (); + contact_editor = e_contact_editor_new ( + shell, book_client, qa->contact, TRUE, TRUE /* XXX */); + + /* Mark it as changed so the Save buttons are + * enabled when we bring up the dialog. */ + g_object_set ( + contact_editor, "changed", contact != NULL, NULL); + + /* We pass this via object data, so that we don't get a + * dangling pointer referenced if both the "contact_added" + * and "editor_closed" get emitted. (Which, based on a + * backtrace in bugzilla, I think can happen and cause a + * crash. */ + g_object_set_data_full ( + G_OBJECT (contact_editor), "quick_add", qa, + (GDestroyNotify) quick_add_unref); + + g_signal_connect ( + contact_editor, "contact_added", + G_CALLBACK (contact_added_cb), NULL); + g_signal_connect ( + contact_editor, "editor_closed", + G_CALLBACK (editor_closed_cb), NULL); + + g_object_unref (book_client); + } +} + +static void +ce_have_book (GObject *source_object, + GAsyncResult *result, + gpointer user_data) +{ + QuickAdd *qa = user_data; + EClient *client; + ESourceRegistry *registry; + GError *error = NULL; + + client = e_client_cache_get_client_finish ( + E_CLIENT_CACHE (source_object), result, &error); + + /* Sanity check. */ + g_return_if_fail ( + ((client != NULL) && (error == NULL)) || + ((client == NULL) && (error != NULL))); + + /* Ignore cancellations. */ + if (g_error_matches (error, E_CLIENT_ERROR, E_CLIENT_ERROR_CANCELLED) || + g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) { + g_warn_if_fail (client == NULL); + g_error_free (error); + return; } + + if (error != NULL) { + g_warning ("%s", error->message); + quick_add_unref (qa); + g_error_free (error); + return; + } + + registry = e_client_cache_ref_registry (qa->client_cache); + + eab_merging_book_find_contact ( + registry, E_BOOK_CLIENT (client), + qa->contact, ce_have_contact, qa); + + g_object_unref (registry); } static void -edit_card (QuickAdd *qa) +edit_contact (QuickAdd *qa) { - EBook *book; - book = e_book_new (); - if (!addressbook_load_default_book (book, ce_have_book, qa)) { - gtk_object_unref (GTK_OBJECT (book)); - ce_have_book (book, E_BOOK_STATUS_OTHER_ERROR, qa); + if (qa->cancellable != NULL) { + g_cancellable_cancel (qa->cancellable); + g_object_unref (qa->cancellable); } + + qa->cancellable = g_cancellable_new (); + + e_client_cache_get_client ( + qa->client_cache, qa->source, + E_SOURCE_EXTENSION_ADDRESS_BOOK, + qa->cancellable, ce_have_book, qa); } +#define QUICK_ADD_RESPONSE_EDIT_FULL 2 + static void -clicked_cb (GtkWidget *w, gint button, gpointer closure) +clicked_cb (GtkWidget *w, + gint button, + gpointer closure) { QuickAdd *qa = (QuickAdd *) closure; /* Get data out of entries. */ - if (button == 0 || button == 1) { + if (!qa->vcard && (button == GTK_RESPONSE_OK || + button == QUICK_ADD_RESPONSE_EDIT_FULL)) { gchar *name = NULL; gchar *email = NULL; - if (qa->name_entry) { - gchar *tmp; - tmp = gtk_editable_get_chars (GTK_EDITABLE (qa->name_entry), 0, -1); - name = e_utf8_from_gtk_string (qa->name_entry, tmp); - g_free (tmp); - } + if (qa->name_entry) + name = gtk_editable_get_chars ( + GTK_EDITABLE (qa->name_entry), 0, -1); - if (qa->email_entry) { - gchar *tmp; - tmp = gtk_editable_get_chars (GTK_EDITABLE (qa->email_entry), 0, -1); - email = e_utf8_from_gtk_string (qa->email_entry, tmp); - g_free (tmp); - } + if (qa->email_entry) + email = gtk_editable_get_chars ( + GTK_EDITABLE (qa->email_entry), 0, -1); + + e_contact_set ( + qa->contact, E_CONTACT_FULL_NAME, + (name != NULL) ? name : ""); + + e_contact_set ( + qa->contact, E_CONTACT_EMAIL_1, + (email != NULL) ? email : ""); - quick_add_set_name (qa, name); - quick_add_set_email (qa, email); - g_free (name); g_free (email); } gtk_widget_destroy (w); - if (button == 0) { + if (button == GTK_RESPONSE_OK) { /* OK */ - quick_add_merge_card (qa); + quick_add_merge_contact (qa); + + } else if (button == QUICK_ADD_RESPONSE_EDIT_FULL) { - } else if (button == 1) { - /* EDIT FULL */ - edit_card (qa); + edit_contact (qa); } else { /* CANCEL */ @@ -289,74 +398,177 @@ clicked_cb (GtkWidget *w, gint button, gpointer closure) } +static void +sanitize_widgets (QuickAdd *qa) +{ + GtkComboBox *combo_box; + const gchar *active_id; + gboolean enabled = TRUE; + + g_return_if_fail (qa != NULL); + g_return_if_fail (qa->dialog != NULL); + + combo_box = GTK_COMBO_BOX (qa->combo_box); + active_id = gtk_combo_box_get_active_id (combo_box); + enabled = (active_id != NULL); + + gtk_dialog_set_response_sensitive ( + GTK_DIALOG (qa->dialog), + QUICK_ADD_RESPONSE_EDIT_FULL, enabled); + gtk_dialog_set_response_sensitive ( + GTK_DIALOG (qa->dialog), GTK_RESPONSE_OK, enabled); +} + +static void +source_changed (ESourceComboBox *source_combo_box, + QuickAdd *qa) +{ + ESource *source; + + source = e_source_combo_box_ref_active (source_combo_box); + + if (source != NULL) { + if (qa->source != NULL) + g_object_unref (qa->source); + qa->source = source; /* takes reference */ + } + + sanitize_widgets (qa); +} + static GtkWidget * build_quick_add_dialog (QuickAdd *qa) { + GtkWidget *container; GtkWidget *dialog; + GtkWidget *label; GtkTable *table; - const gint xpad=1, ypad=1; + ESource *source; + ESourceRegistry *registry; + const gchar *extension_name; + const gint xpad = 0, ypad = 0; g_return_val_if_fail (qa != NULL, NULL); - dialog = gnome_dialog_new (_("Contact Quick-Add"), - GNOME_STOCK_BUTTON_OK, - _("Edit Full"), - GNOME_STOCK_BUTTON_CANCEL, - NULL); + dialog = gtk_dialog_new_with_buttons ( + _("Contact Quick-Add"), + e_shell_get_active_window (NULL), + 0, + _("_Edit Full"), QUICK_ADD_RESPONSE_EDIT_FULL, + GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, + GTK_STOCK_OK, GTK_RESPONSE_OK, + NULL); - gtk_signal_connect (GTK_OBJECT (dialog), - "clicked", - clicked_cb, - qa); + gtk_widget_ensure_style (dialog); - qa->name_entry = gtk_entry_new (); - if (qa->name) { - gchar *str = e_utf8_to_gtk_string (qa->name_entry, qa->name); - gtk_entry_set_text (GTK_ENTRY (qa->name_entry), str); - g_free (str); - } + container = gtk_dialog_get_action_area (GTK_DIALOG (dialog)); + gtk_container_set_border_width (GTK_CONTAINER (container), 12); + container = gtk_dialog_get_content_area (GTK_DIALOG (dialog)); + gtk_container_set_border_width (GTK_CONTAINER (container), 0); + + g_signal_connect ( + dialog, "response", + G_CALLBACK (clicked_cb), qa); + qa->dialog = dialog; + + qa->name_entry = gtk_entry_new (); + if (qa->name) + gtk_entry_set_text (GTK_ENTRY (qa->name_entry), qa->name); qa->email_entry = gtk_entry_new (); - if (qa->email) { - gchar *str = e_utf8_to_gtk_string (qa->email_entry, qa->email); - gtk_entry_set_text (GTK_ENTRY (qa->email_entry), str); - g_free (str); + if (qa->email) + gtk_entry_set_text (GTK_ENTRY (qa->email_entry), qa->email); + + if (qa->vcard) { + /* when adding vCard, then do not allow change name or email */ + gtk_widget_set_sensitive (qa->name_entry, FALSE); + gtk_widget_set_sensitive (qa->email_entry, FALSE); } - table = GTK_TABLE (gtk_table_new (2, 2, FALSE)); - - gtk_table_attach (table, gtk_label_new (_("Full Name")), - 0, 1, 0, 1, - 0, 0, xpad, ypad); - gtk_table_attach (table, qa->name_entry, - 1, 2, 0, 1, - GTK_EXPAND | GTK_FILL, GTK_EXPAND, xpad, ypad); - gtk_table_attach (table, gtk_label_new (_("E-mail")), - 0, 1, 1, 2, - 0, 0, xpad, ypad); - gtk_table_attach (table, qa->email_entry, - 1, 2, 1, 2, - GTK_EXPAND | GTK_FILL, GTK_EXPAND, xpad, ypad); - - gtk_box_pack_start (GTK_BOX (GNOME_DIALOG (dialog)->vbox), - GTK_WIDGET (table), - TRUE, TRUE, 0); + extension_name = E_SOURCE_EXTENSION_ADDRESS_BOOK; + registry = e_client_cache_ref_registry (qa->client_cache); + source = e_source_registry_ref_default_address_book (registry); + g_object_unref (registry); + + qa->combo_box = e_client_combo_box_new ( + qa->client_cache, extension_name); + e_source_combo_box_set_active ( + E_SOURCE_COMBO_BOX (qa->combo_box), source); + + g_object_unref (source); + + source_changed (E_SOURCE_COMBO_BOX (qa->combo_box), qa); + g_signal_connect ( + qa->combo_box, "changed", + G_CALLBACK (source_changed), qa); + + table = GTK_TABLE (gtk_table_new (3, 2, FALSE)); + gtk_table_set_row_spacings (table, 6); + gtk_table_set_col_spacings (table, 12); + + label = gtk_label_new_with_mnemonic (_("_Full name")); + gtk_label_set_mnemonic_widget ((GtkLabel *) label, qa->name_entry); + gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5); + + gtk_table_attach ( + table, label, + 0, 1, 0, 1, + GTK_FILL, 0, xpad, ypad); + gtk_table_attach ( + table, qa->name_entry, + 1, 2, 0, 1, + GTK_EXPAND | GTK_FILL, 0, xpad, ypad); + + label = gtk_label_new_with_mnemonic (_("E_mail")); + gtk_label_set_mnemonic_widget ((GtkLabel *) label, qa->email_entry); + gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5); + + gtk_table_attach ( + table, label, + 0, 1, 1, 2, + GTK_FILL, 0, xpad, ypad); + gtk_table_attach ( + table, qa->email_entry, + 1, 2, 1, 2, + GTK_EXPAND | GTK_FILL, 0, xpad, ypad); + + label = gtk_label_new_with_mnemonic (_("_Select Address Book")); + gtk_label_set_mnemonic_widget ((GtkLabel *) label, qa->combo_box); + gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5); + + gtk_table_attach ( + table, label, + 0, 1, 2, 3, + GTK_FILL, 0, xpad, ypad); + gtk_table_attach ( + table, qa->combo_box, + 1, 2, 2, 3, + GTK_EXPAND | GTK_FILL, 0, xpad, ypad); + + gtk_container_set_border_width (GTK_CONTAINER (table), 12); + container = gtk_dialog_get_content_area (GTK_DIALOG (dialog)); + gtk_box_pack_start ( + GTK_BOX (container), GTK_WIDGET (table), FALSE, FALSE, 0); gtk_widget_show_all (GTK_WIDGET (table)); - - + return dialog; } void -e_contact_quick_add (const gchar *in_name, const gchar *email, - EContactQuickAddCallback cb, gpointer closure) +e_contact_quick_add (EClientCache *client_cache, + const gchar *in_name, + const gchar *email, + EContactQuickAddCallback cb, + gpointer closure) { QuickAdd *qa; GtkWidget *dialog; gchar *name = NULL; gint len; + g_return_if_fail (E_IS_CLIENT_CACHE (client_cache)); + /* We need to have *something* to work with. */ if (in_name == NULL && email == NULL) { if (cb) @@ -370,14 +582,15 @@ e_contact_quick_add (const gchar *in_name, const gchar *email, /* Remove extra whitespace and the quotes some mailers put around names. */ g_strstrip (name); len = strlen (name); - if ((name[0] == '\'' && name[len-1] == '\'') || (name[0] == '"' && name[len-1] == '"')) { + if ((name[0] == '\'' && name[len - 1] == '\'') || + (name[0] == '"' && name[len - 1] == '"')) { name[0] = ' '; - name[len-1] = ' '; + name[len - 1] = ' '; } g_strstrip (name); } - qa = quick_add_new (); + qa = quick_add_new (client_cache); qa->cb = cb; qa->closure = closure; if (name) @@ -392,14 +605,19 @@ e_contact_quick_add (const gchar *in_name, const gchar *email, } void -e_contact_quick_add_free_form (const gchar *text, EContactQuickAddCallback cb, gpointer closure) +e_contact_quick_add_free_form (EClientCache *client_cache, + const gchar *text, + EContactQuickAddCallback cb, + gpointer closure) { - gchar *name=NULL, *email=NULL; + gchar *name = NULL, *email = NULL; const gchar *last_at, *s; gboolean in_quote; + g_return_if_fail (E_IS_CLIENT_CACHE (client_cache)); + if (text == NULL) { - e_contact_quick_add (NULL, NULL, cb, closure); + e_contact_quick_add (client_cache, NULL, NULL, cb, closure); return; } @@ -413,16 +631,17 @@ e_contact_quick_add_free_form (const gchar *text, EContactQuickAddCallback cb, g in_quote = !in_quote; } - if (last_at == NULL) { /* No at sign, so we treat it all as the name */ name = g_strdup (text); } else { gboolean bad_char = FALSE; - + /* walk backwards to whitespace or a < or a quote... */ while (last_at >= text && !bad_char - && !(isspace ((gint) *last_at) || *last_at == '<' || *last_at == '"')) { + && !(isspace ((gint) *last_at) || + *last_at == '<' || + *last_at == '"')) { /* Check for some stuff that can't appear in a legal e-mail address. */ if (*last_at == '[' || *last_at == ']' @@ -437,16 +656,14 @@ e_contact_quick_add_free_form (const gchar *text, EContactQuickAddCallback cb, g /* ...and then split the text there */ if (!bad_char) { if (text < last_at) - name = g_strndup (text, last_at-text); + name = g_strndup (text, last_at - text); email = g_strdup (last_at); } } /* If all else has failed, make it the name. */ - if (name == NULL && email == NULL) + if (name == NULL && email == NULL) name = g_strdup (text); - - /* Clean up email, remove bracketing <>s */ if (email && *email) { @@ -456,16 +673,106 @@ e_contact_quick_add_free_form (const gchar *text, EContactQuickAddCallback cb, g *email = ' '; changed = TRUE; } - if (email[strlen (email)-1] == '>') { - email[strlen (email)-1] = ' '; + if (email[strlen (email) - 1] == '>') { + email[strlen (email) - 1] = ' '; changed = TRUE; } if (changed) g_strstrip (email); } - - e_contact_quick_add (name, email, cb, closure); + e_contact_quick_add (client_cache, name, email, cb, closure); + g_free (name); g_free (email); } + +void +e_contact_quick_add_email (EClientCache *client_cache, + const gchar *email, + EContactQuickAddCallback cb, + gpointer closure) +{ + gchar *name = NULL; + gchar *addr = NULL; + gchar *lt, *gt; + + /* Handle something of the form "Foo <foo@bar.com>". This is more + * more forgiving than the free-form parser, allowing for unquoted + * whitespace since we know the whole string is an email address. */ + + lt = (email != NULL) ? strchr (email, '<') : NULL; + gt = (lt != NULL) ? strchr (email, '>') : NULL; + + if (lt != NULL && gt != NULL && (gt - lt) > 0) { + name = g_strndup (email, lt - email); + addr = g_strndup (lt + 1, gt - lt - 1); + } else { + addr = g_strdup (email); + } + + e_contact_quick_add (client_cache, name, addr, cb, closure); + + g_free (name); + g_free (addr); +} + +void +e_contact_quick_add_vcard (EClientCache *client_cache, + const gchar *vcard, + EContactQuickAddCallback cb, + gpointer closure) +{ + QuickAdd *qa; + GtkWidget *dialog; + EContact *contact; + + g_return_if_fail (E_IS_CLIENT_CACHE (client_cache)); + + /* We need to have *something* to work with. */ + if (vcard == NULL) { + if (cb) + cb (NULL, closure); + return; + } + + qa = quick_add_new (client_cache); + qa->cb = cb; + qa->closure = closure; + quick_add_set_vcard (qa, vcard); + + contact = e_contact_new_from_vcard (qa->vcard); + + if (contact) { + GList *emails; + gchar *name; + EContactName *contact_name; + + g_object_unref (qa->contact); + qa->contact = contact; + + contact_name = e_contact_get (qa->contact, E_CONTACT_NAME); + name = e_contact_name_to_string (contact_name); + quick_add_set_name (qa, name); + g_free (name); + e_contact_name_free (contact_name); + + emails = e_contact_get (qa->contact, E_CONTACT_EMAIL); + if (emails) { + quick_add_set_email (qa, emails->data); + + g_list_foreach (emails, (GFunc) g_free, NULL); + g_list_free (emails); + } + } else { + if (cb) + cb (NULL, closure); + + quick_add_unref (qa); + g_warning ("Contact's vCard parsing failed!"); + return; + } + + dialog = build_quick_add_dialog (qa); + gtk_widget_show_all (dialog); +} |