/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ /* * eab-vcard-control.c * * Copyright (C) 1999-2008 Novell, Inc. (www.novell.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. * * 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., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. * * Authors: * Chris Lahey * Chris Toshok */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include "eab-vcard-control.h" #include "eab-contact-merging.h" typedef struct { EABContactDisplay *display; GList *card_list; GtkWidget *label; EABContactDisplayRenderMode render_mode; } EABVCardControl; #define VCARD_CONTROL_ID "OAFIID:GNOME_Evolution_Addressbook_VCard_Control:" BASE_VERSION /* * Bonobo::PersistStream * * These two functions implement the Bonobo::PersistStream load and * save methods which allow data to be loaded into and out of the * BonoboObject. */ static char * stream_read (Bonobo_Stream stream) { Bonobo_Stream_iobuf *buffer; CORBA_Environment ev; char *data = NULL; gint length = 0; CORBA_exception_init (&ev); do { #define READ_CHUNK_SIZE 65536 Bonobo_Stream_read (stream, READ_CHUNK_SIZE, &buffer, &ev); if (ev._major != CORBA_NO_EXCEPTION) { CORBA_exception_free (&ev); return NULL; } if (buffer->_length <= 0) break; data = g_realloc (data, length + buffer->_length + 1); memcpy (data + length, buffer->_buffer, buffer->_length); length += buffer->_length; CORBA_free (buffer); } while (1); CORBA_free (buffer); CORBA_exception_free (&ev); if (data) data[length] = '\0'; else data = g_strdup(""); return data; } /* stream_read */ /* * This function implements the Bonobo::PersistStream:load method. */ static void pstream_load (BonoboPersistStream *ps, const Bonobo_Stream stream, Bonobo_Persist_ContentType type, void *data, CORBA_Environment *ev) { GList *list; char *vcard; EABVCardControl *vcard_control = data; if (type && g_ascii_strcasecmp (type, "text/vCard") != 0 && g_ascii_strcasecmp (type, "text/x-vCard") != 0) { CORBA_exception_set (ev, CORBA_USER_EXCEPTION, ex_Bonobo_Persist_WrongDataType, NULL); return; } if ((vcard = stream_read (stream)) == NULL) { CORBA_exception_set (ev, CORBA_USER_EXCEPTION, ex_Bonobo_Persist_FileNotFound, NULL); return; } g_list_foreach ( vcard_control->card_list, (GFunc) g_object_unref, NULL); g_list_free (vcard_control->card_list); list = eab_contact_list_from_string (vcard); g_free(vcard); vcard_control->card_list = list; if (list) { eab_contact_display_render (vcard_control->display, E_CONTACT (list->data), vcard_control->render_mode); } if (list && list->next) { char *message; int length = g_list_length (list) - 1; message = g_strdup_printf (ngettext("There is one other contact.", "There are %d other contacts.", length), length); gtk_label_set_text (GTK_LABEL (vcard_control->label), message); g_free (message); gtk_widget_show (vcard_control->label); } else { gtk_widget_hide (vcard_control->label); } } /* pstream_load */ /* * This function implements the Bonobo::PersistStream:save method. */ static void pstream_save (BonoboPersistStream *ps, const Bonobo_Stream stream, Bonobo_Persist_ContentType type, void *data, CORBA_Environment *ev) { EABVCardControl *vcard_control = data; char *vcard; int length; if (type && g_ascii_strcasecmp (type, "text/vCard") != 0 && g_ascii_strcasecmp (type, "text/x-vCard") != 0) { CORBA_exception_set (ev, CORBA_USER_EXCEPTION, ex_Bonobo_Persist_WrongDataType, NULL); return; } vcard = eab_contact_list_to_string (vcard_control->card_list); length = strlen (vcard); bonobo_stream_client_write (stream, vcard, length, ev); g_free (vcard); } /* pstream_save */ static Bonobo_Persist_ContentTypeList * pstream_get_content_types (BonoboPersistStream *ps, void *closure, CORBA_Environment *ev) { return bonobo_persist_generate_content_types (2, "text/vCard", "text/x-vCard"); } static void book_open_cb (EBook *book, EBookStatus status, gpointer closure) { GList *list = closure; if (status == E_BOOK_ERROR_OK) { GList *p; for (p = list; p; p = p->next) { /* XXX argh, more passing of NULL's for callbacks */ eab_merging_book_add_contact (book, E_CONTACT (p->data), NULL, NULL); } } if (book) g_object_unref (book); g_list_foreach (list, (GFunc) g_object_unref, NULL); g_list_free (list); } static void save_in_addressbook(GtkWidget *button, gpointer data) { EABVCardControl *vcard_control = data; GList *list, *p; list = g_list_copy (vcard_control->card_list); for (p = list; p; p = p->next) g_object_ref (p->data); addressbook_load_default_book (book_open_cb, list); } static void toggle_full_vcard(GtkWidget *button, gpointer data) { EABVCardControl *vcard_control = data; char *label; if (!vcard_control->card_list) return; if (vcard_control->render_mode == EAB_CONTACT_DISPLAY_RENDER_NORMAL) { vcard_control->render_mode = EAB_CONTACT_DISPLAY_RENDER_COMPACT; label = _("Show Full vCard"); } else { vcard_control->render_mode = EAB_CONTACT_DISPLAY_RENDER_NORMAL; label = _("Show Compact vCard"); } gtk_button_set_label (GTK_BUTTON (button), label); eab_contact_display_render (vcard_control->display, E_CONTACT (vcard_control->card_list->data), vcard_control->render_mode); } static void free_struct (gpointer data, GObject *where_object_was) { EABVCardControl *vcard_control = data; g_list_foreach ( vcard_control->card_list, (GFunc) g_object_unref, NULL); g_list_free (vcard_control->card_list); g_free (vcard_control); } BonoboControl * eab_vcard_control_new (void) { BonoboControl *control; BonoboPersistStream *stream; GtkWidget *display; GtkWidget *button1, *button2; GtkWidget *bbox; GtkWidget *vbox; EABVCardControl *vcard_control = g_new (EABVCardControl, 1); vcard_control->card_list = NULL; vcard_control->display = NULL; vcard_control->label = NULL; vcard_control->render_mode = EAB_CONTACT_DISPLAY_RENDER_COMPACT; /* Create the control. */ display = eab_contact_display_new (); vcard_control->display = EAB_CONTACT_DISPLAY (display); bbox = gtk_hbutton_box_new (); gtk_button_box_set_layout (GTK_BUTTON_BOX (bbox), GTK_BUTTONBOX_START); gtk_box_set_spacing (GTK_BOX (bbox), 12); button1 = gtk_button_new_with_label(_("Show Full vCard")); g_signal_connect (button1, "clicked", G_CALLBACK (toggle_full_vcard), vcard_control); gtk_box_pack_start (GTK_BOX (bbox), button1, FALSE, FALSE, 0); button2 = gtk_button_new_with_label(_("Save in addressbook")); g_signal_connect (button2, "clicked", G_CALLBACK (save_in_addressbook), vcard_control); gtk_box_pack_start (GTK_BOX (bbox), button2, FALSE, FALSE, 0); /* This is intentionally not shown. */ vcard_control->label = gtk_label_new (""); vbox = gtk_vbox_new (FALSE, 0); gtk_box_pack_start (GTK_BOX (vbox), bbox, FALSE, FALSE, 0); gtk_box_pack_start (GTK_BOX (vbox), display, TRUE, TRUE, 0); gtk_box_pack_start (GTK_BOX (vbox), vcard_control->label, TRUE, TRUE, 0); gtk_widget_show_all (bbox); gtk_widget_show (display); gtk_widget_show (vbox); control = bonobo_control_new (vbox); g_object_weak_ref (G_OBJECT (control), free_struct, vcard_control); stream = bonobo_persist_stream_new (pstream_load, pstream_save, pstream_get_content_types, VCARD_CONTROL_ID, vcard_control); if (stream == NULL) { bonobo_object_unref (BONOBO_OBJECT (control)); return NULL; } bonobo_object_add_interface (BONOBO_OBJECT (control), BONOBO_OBJECT (stream)); return control; }