/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ /* addressbook.c * * Copyright (C) 2000, 2001, 2002 Ximian, Inc. * * 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., 59 Temple Place - Suite 330, * Boston, MA 02111-1307, USA. * * Author: Chris Lahey (clahey@ximian.com) */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "e-util/e-passwords.h" #include "shell/e-user-creatable-items-handler.h" #include "evolution-shell-component-utils.h" #include "e-activity-handler.h" #include "e-contact-editor.h" #include "addressbook-config.h" #include "addressbook.h" #include "addressbook-component.h" #include "addressbook/gui/search/e-addressbook-search-dialog.h" #include "addressbook/gui/widgets/e-addressbook-view.h" #include "addressbook/gui/widgets/eab-gui-util.h" #include "addressbook/printing/e-contact-print.h" #include "addressbook/util/eab-book-util.h" #include /* This is used for the addressbook status bar */ #define EVOLUTION_CONTACTS_PROGRESS_IMAGE "evolution-contacts-mini.png" static GdkPixbuf *progress_icon = NULL; #define d(x) #define PROPERTY_SOURCE_UID "source_uid" #define PROPERTY_FOLDER_URI "folder_uri" #define PROPERTY_SOURCE_UID_IDX 1 #define PROPERTY_FOLDER_URI_IDX 2 typedef struct { gint refs; GHashTable *uid_to_view; GtkWidget *notebook; EBook *book; guint activity_id; BonoboControl *control; BonoboPropertyBag *properties; ESourceList *source_list; char *passwd; EUserCreatableItemsHandler *creatable_items_handler; } AddressbookView; static void addressbook_view_ref (AddressbookView *); static void addressbook_view_unref (AddressbookView *); static void addressbook_authenticate (EBook *book, gboolean previous_failure, ESource *source, EBookCallback cb, gpointer closure); static void book_open_cb (EBook *book, EBookStatus status, gpointer closure); static void set_status_message (EABView *eav, const char *message, AddressbookView *view); static void search_result (EABView *eav, EBookViewStatus status, AddressbookView *view); static EABView * get_current_view (AddressbookView *view) { return EAB_VIEW (gtk_notebook_get_nth_page (GTK_NOTEBOOK (view->notebook), gtk_notebook_get_current_page (GTK_NOTEBOOK (view->notebook)))); } static void save_contact_cb (BonoboUIComponent *uih, void *user_data, const char *path) { AddressbookView *view = (AddressbookView *) user_data; EABView *v = get_current_view (view); if (v) eab_view_save_as(v); } static void view_contact_cb (BonoboUIComponent *uih, void *user_data, const char *path) { AddressbookView *view = (AddressbookView *) user_data; EABView *v = get_current_view (view); if (v) eab_view_view(v); } static void search_cb (BonoboUIComponent *uih, void *user_data, const char *path) { AddressbookView *view = (AddressbookView *) user_data; EABView *v = get_current_view (view); if (v) gtk_widget_show(eab_search_dialog_new(v)); } static void delete_contact_cb (BonoboUIComponent *uih, void *user_data, const char *path) { AddressbookView *view = (AddressbookView *) user_data; EABView *v = get_current_view (view); if (v) eab_view_delete_selection(v); } static void print_cb (BonoboUIComponent *uih, void *user_data, const char *path) { AddressbookView *view = (AddressbookView *) user_data; EABView *v = get_current_view (view); if (v) eab_view_print(v); } static void print_preview_cb (BonoboUIComponent *uih, void *user_data, const char *path) { AddressbookView *view = (AddressbookView *) user_data; EABView *v = get_current_view (view); if (v) eab_view_print_preview(v); } static void stop_loading_cb (BonoboUIComponent *uih, void *user_data, const char *path) { AddressbookView *view = (AddressbookView *) user_data; EABView *v = get_current_view (view); if (v) eab_view_stop(v); } static void cut_contacts_cb (BonoboUIComponent *uih, void *user_data, const char *path) { AddressbookView *view = (AddressbookView *) user_data; EABView *v = get_current_view (view); if (v) eab_view_cut(v); } static void copy_contacts_cb (BonoboUIComponent *uih, void *user_data, const char *path) { AddressbookView *view = (AddressbookView *) user_data; EABView *v = get_current_view (view); if (v) eab_view_copy(v); } static void paste_contacts_cb (BonoboUIComponent *uih, void *user_data, const char *path) { AddressbookView *view = (AddressbookView *) user_data; EABView *v = get_current_view (view); if (v) eab_view_paste(v); } static void select_all_contacts_cb (BonoboUIComponent *uih, void *user_data, const char *path) { AddressbookView *view = (AddressbookView *) user_data; EABView *v = get_current_view (view); if (v) eab_view_select_all (v); } static void send_contact_cb (BonoboUIComponent *uih, void *user_data, const char *path) { AddressbookView *view = (AddressbookView *) user_data; EABView *v = get_current_view (view); if (v) eab_view_send (v); } static void send_contact_to_cb (BonoboUIComponent *uih, void *user_data, const char *path) { AddressbookView *view = (AddressbookView *) user_data; EABView *v = get_current_view (view); if (v) eab_view_send_to (v); } static void copy_contact_to_cb (BonoboUIComponent *uih, void *user_data, const char *path) { AddressbookView *view = (AddressbookView *) user_data; EABView *v = get_current_view (view); if (v) eab_view_copy_to_folder (v); } static void move_contact_to_cb (BonoboUIComponent *uih, void *user_data, const char *path) { AddressbookView *view = (AddressbookView *) user_data; EABView *v = get_current_view (view); if (v) eab_view_move_to_folder (v); } static void forget_passwords_cb (BonoboUIComponent *uih, void *user_data, const char *path) { e_passwords_forget_passwords(); } static void set_status_message (EABView *eav, const char *message, AddressbookView *view) { EActivityHandler *activity_handler = addressbook_component_peek_activity_handler (addressbook_component_peek ()); if (!message || !*message) { if (view->activity_id != 0) { e_activity_handler_operation_finished (activity_handler, view->activity_id); view->activity_id = 0; } } else if (view->activity_id == 0) { char *clientid = g_strdup_printf ("%p", view); if (progress_icon == NULL) progress_icon = gdk_pixbuf_new_from_file (EVOLUTION_IMAGESDIR "/" EVOLUTION_CONTACTS_PROGRESS_IMAGE, NULL); view->activity_id = e_activity_handler_operation_started (activity_handler, clientid, progress_icon, message, TRUE); g_free (clientid); } else { e_activity_handler_operation_progressing (activity_handler, view->activity_id, message, -1.0); } } static void search_result (EABView *eav, EBookViewStatus status, AddressbookView *view) { eab_search_result_dialog (NULL /* XXX */, status); } static void update_command_state (EABView *eav, AddressbookView *view) { BonoboUIComponent *uic; if (eav != get_current_view (view)) return; addressbook_view_ref (view); uic = bonobo_control_get_ui_component (view->control); if (bonobo_ui_component_get_container (uic) != CORBA_OBJECT_NIL) { bonobo_ui_component_set_prop (uic, "/commands/ContactsSaveAsVCard", "sensitive", eab_view_can_save_as (eav) ? "1" : "0", NULL); bonobo_ui_component_set_prop (uic, "/commands/ContactsView", "sensitive", eab_view_can_view (eav) ? "1" : "0", NULL); /* Print Contact */ bonobo_ui_component_set_prop (uic, "/commands/ContactsPrint", "sensitive", eab_view_can_print (eav) ? "1" : "0", NULL); /* Print Contact */ bonobo_ui_component_set_prop (uic, "/commands/ContactsPrintPreview", "sensitive", eab_view_can_print (eav) ? "1" : "0", NULL); /* Delete Contact */ bonobo_ui_component_set_prop (uic, "/commands/ContactDelete", "sensitive", eab_view_can_delete (eav) ? "1" : "0", NULL); bonobo_ui_component_set_prop (uic, "/commands/ContactsCut", "sensitive", eab_view_can_cut (eav) ? "1" : "0", NULL); bonobo_ui_component_set_prop (uic, "/commands/ContactsCopy", "sensitive", eab_view_can_copy (eav) ? "1" : "0", NULL); bonobo_ui_component_set_prop (uic, "/commands/ContactsPaste", "sensitive", eab_view_can_paste (eav) ? "1" : "0", NULL); bonobo_ui_component_set_prop (uic, "/commands/ContactsSelectAll", "sensitive", eab_view_can_select_all (eav) ? "1" : "0", NULL); bonobo_ui_component_set_prop (uic, "/commands/ContactsSendContactToOther", "sensitive", eab_view_can_send (eav) ? "1" : "0", NULL); bonobo_ui_component_set_prop (uic, "/commands/ContactsSendMessageToContact", "sensitive", eab_view_can_send_to (eav) ? "1" : "0", NULL); bonobo_ui_component_set_prop (uic, "/commands/ContactsMoveToFolder", "sensitive", eab_view_can_move_to_folder (eav) ? "1" : "0", NULL); bonobo_ui_component_set_prop (uic, "/commands/ContactsCopyToFolder", "sensitive", eab_view_can_copy_to_folder (eav) ? "1" : "0", NULL); /* Stop */ bonobo_ui_component_set_prop (uic, "/commands/ContactStop", "sensitive", eab_view_can_stop (eav) ? "1" : "0", NULL); } addressbook_view_unref (view); } static BonoboUIVerb verbs [] = { BONOBO_UI_UNSAFE_VERB ("ContactsPrint", print_cb), BONOBO_UI_UNSAFE_VERB ("ContactsPrintPreview", print_preview_cb), BONOBO_UI_UNSAFE_VERB ("ContactsSaveAsVCard", save_contact_cb), BONOBO_UI_UNSAFE_VERB ("ContactsView", view_contact_cb), BONOBO_UI_UNSAFE_VERB ("ContactDelete", delete_contact_cb), BONOBO_UI_UNSAFE_VERB ("ContactStop", stop_loading_cb), BONOBO_UI_UNSAFE_VERB ("ContactsCut", cut_contacts_cb), BONOBO_UI_UNSAFE_VERB ("ContactsCopy", copy_contacts_cb), BONOBO_UI_UNSAFE_VERB ("ContactsPaste", paste_contacts_cb), BONOBO_UI_UNSAFE_VERB ("ContactsSelectAll", select_all_contacts_cb), BONOBO_UI_UNSAFE_VERB ("ContactsSendContactToOther", send_contact_cb), BONOBO_UI_UNSAFE_VERB ("ContactsSendMessageToContact", send_contact_to_cb), BONOBO_UI_UNSAFE_VERB ("ContactsMoveToFolder", move_contact_to_cb), BONOBO_UI_UNSAFE_VERB ("ContactsCopyToFolder", copy_contact_to_cb), BONOBO_UI_UNSAFE_VERB ("ContactsForgetPasswords", forget_passwords_cb), /* ContactsViewPreview is a toggle */ BONOBO_UI_VERB_END }; static EPixmap pixmaps [] = { E_PIXMAP ("/menu/File/FileOps/ContactsSaveAsVCard", "save-as-16.png"), E_PIXMAP ("/menu/File/Print/ContactsPrint", "print.xpm"), E_PIXMAP ("/menu/File/Print/ContactsPrintPreview", "print-preview.xpm"), E_PIXMAP ("/menu/EditPlaceholder/Edit/ContactsCut", "16_cut.png"), E_PIXMAP ("/menu/EditPlaceholder/Edit/ContactsCopy", "16_copy.png"), E_PIXMAP ("/menu/EditPlaceholder/Edit/ContactsPaste", "16_paste.png"), E_PIXMAP ("/menu/EditPlaceholder/Edit/ContactDelete", "evolution-trash-mini.png"), E_PIXMAP ("/Toolbar/ContactsPrint", "buttons/print.png"), E_PIXMAP ("/Toolbar/ContactDelete", "buttons/delete-message.png"), E_PIXMAP_END }; static void control_activate (BonoboControl *control, BonoboUIComponent *uic, AddressbookView *view) { Bonobo_UIContainer remote_ui_container; EABView *v = get_current_view (view); remote_ui_container = bonobo_control_get_remote_ui_container (control, NULL); bonobo_ui_component_set_container (uic, remote_ui_container, NULL); bonobo_object_release_unref (remote_ui_container, NULL); bonobo_ui_component_add_verb_list_with_data ( uic, verbs, view); bonobo_ui_component_freeze (uic, NULL); bonobo_ui_util_set_ui (uic, PREFIX, EVOLUTION_UIDIR "/evolution-addressbook.xml", "evolution-addressbook", NULL); if (v) eab_view_setup_menus (v, uic); e_pixmaps_update (uic, pixmaps); e_user_creatable_items_handler_activate (view->creatable_items_handler, uic); bonobo_ui_component_thaw (uic, NULL); if (v) update_command_state (v, view); } static void control_activate_cb (BonoboControl *control, gboolean activate, AddressbookView *view) { BonoboUIComponent *uic; EABView *v = get_current_view (view); uic = bonobo_control_get_ui_component (control); g_assert (uic != NULL); if (activate) { control_activate (control, uic, view); if (activate && v && v->model) eab_model_force_folder_bar_message (v->model); } else { bonobo_ui_component_unset_container (uic, NULL); eab_view_discard_menus (v); } } static void gather_uids_foreach (char *key, gpointer value, GList **list) { (*list) = g_list_prepend (*list, key); } static void source_list_changed_cb (ESourceList *source_list, AddressbookView *view) { GList *uids, *l; EABView *v; uids = NULL; g_hash_table_foreach (view->uid_to_view, (GHFunc)gather_uids_foreach, &uids); for (l = uids; l; l = l->next) { char *uid = l->data; if (e_source_list_peek_source_by_uid (source_list, uid)) { /* the source still exists, do nothing */ } else { /* the source no longer exists, remove the view and remove it from our hash table. */ v = g_hash_table_lookup (view->uid_to_view, uid); g_hash_table_remove (view->uid_to_view, uid); gtk_notebook_remove_page (GTK_NOTEBOOK (view->notebook), gtk_notebook_page_num (GTK_NOTEBOOK (view->notebook), GTK_WIDGET (v))); g_object_unref (v); } } /* make sure we've got the current view selected and updated properly */ v = get_current_view (view); if (v) { eab_view_setup_menus (v, bonobo_control_get_ui_component (view->control)); update_command_state (v, view); } } static void addressbook_view_clear (AddressbookView *view) { if (view->book) { g_object_unref (view->book); view->book = NULL; } if (view->properties) { bonobo_object_unref (BONOBO_OBJECT(view->properties)); view->properties = NULL; } g_free(view->passwd); view->passwd = NULL; if (view->source_list) { g_object_unref (view->source_list); view->source_list = NULL; } if (view->uid_to_view) { g_hash_table_destroy (view->uid_to_view); view->uid_to_view = NULL; } if (view->creatable_items_handler) { g_object_unref (view->creatable_items_handler); view->creatable_items_handler = NULL; } } static void addressbook_view_ref (AddressbookView *view) { g_assert (view->refs > 0); ++view->refs; } static void addressbook_view_unref (AddressbookView *view) { g_assert (view->refs > 0); --view->refs; if (view->refs == 0) { addressbook_view_clear (view); g_free (view); } } typedef struct { EABView *view; ESource *source; } BookOpenData; static void book_open_cb (EBook *book, EBookStatus status, gpointer closure) { BookOpenData *data = closure; EABView *view = data->view; ESource *source = data->source; g_free (data); /* we always set the "source" property on the EABView, since we use it to reload a previously failed book. */ g_object_set(view, "source", source, NULL); if (status == E_BOOK_ERROR_OK) { g_object_set(view, "book", book, NULL); } else { eab_load_error_dialog (NULL /* XXX */, source, status); } g_object_unref (source); } static void destroy_callback(gpointer data, GObject *where_object_was) { AddressbookView *view = data; addressbook_view_unref (view); } typedef struct { EBookCallback cb; ESource *source; gpointer closure; guint cancelled : 1; } LoadSourceData; static void free_load_source_data (LoadSourceData *data) { if (data->source) g_object_unref (data->source); g_free (data); } static void load_source_auth_cb (EBook *book, EBookStatus status, gpointer closure) { LoadSourceData *data = closure; if (data->cancelled) { free_load_source_data (data); return; } if (status != E_BOOK_ERROR_OK) { if (status == E_BOOK_ERROR_CANCELLED) { /* the user clicked cancel in the password dialog */ GtkWidget *dialog; dialog = gtk_message_dialog_new (NULL, 0, GTK_MESSAGE_WARNING, GTK_BUTTONS_OK, _("Accessing LDAP Server anonymously")); g_signal_connect (dialog, "response", G_CALLBACK(gtk_widget_destroy), NULL); gtk_widget_show (dialog); data->cb (book, E_BOOK_ERROR_OK, data->closure); free_load_source_data (data); return; } else { gchar *uri = e_source_get_uri (data->source); e_passwords_forget_password ("Addressbook", uri); addressbook_authenticate (book, TRUE, data->source, load_source_auth_cb, closure); g_free (uri); return; } } data->cb (book, status, data->closure); free_load_source_data (data); } static gboolean get_remember_password (ESource *source) { const gchar *value; value = e_source_get_property (source, "remember_password"); if (value && !strcasecmp (value, "true")) return TRUE; return FALSE; } static void set_remember_password (ESource *source, gboolean value) { e_source_set_property (source, "remember_password", value ? "true" : "false"); } static void addressbook_authenticate (EBook *book, gboolean previous_failure, ESource *source, EBookCallback cb, gpointer closure) { const char *password = NULL; char *pass_dup = NULL; const gchar *auth; const gchar *user; gchar *uri = e_source_get_uri (source); password = e_passwords_get_password ("Addressbook", uri); auth = e_source_get_property (source, "auth"); if (auth && !strcmp ("ldap/simple-binddn", auth)) user = e_source_get_property (source, "binddn"); else user = e_source_get_property (source, "email_addr"); if (!user) user = ""; if (!password) { char *prompt; gboolean remember; char *failed_auth; if (previous_failure) { failed_auth = _("Failed to authenticate.\n"); } else { failed_auth = ""; } prompt = g_strdup_printf (_("%sEnter password for %s (user %s)"), failed_auth, e_source_peek_name (source), user); remember = get_remember_password (source); pass_dup = e_passwords_ask_password (prompt, "Addressbook", uri, prompt, TRUE, E_PASSWORDS_REMEMBER_FOREVER, &remember, NULL); if (remember != get_remember_password (source)) set_remember_password (source, remember); g_free (prompt); } if (password || pass_dup) { e_book_async_authenticate_user (book, user, password ? password : pass_dup, e_source_get_property (source, "auth"), cb, closure); g_free (pass_dup); } else { /* they hit cancel */ cb (book, E_BOOK_ERROR_CANCELLED, closure); } g_free (uri); } static void load_source_cb (EBook *book, EBookStatus status, gpointer closure) { LoadSourceData *load_source_data = closure; if (load_source_data->cancelled) { free_load_source_data (load_source_data); return; } if (status == E_BOOK_ERROR_OK && book != NULL) { const gchar *auth; auth = e_source_get_property (load_source_data->source, "auth"); /* check if the addressbook needs authentication */ if (auth && strcmp (auth, "none")) { addressbook_authenticate (book, FALSE, load_source_data->source, load_source_auth_cb, closure); return; } } load_source_data->cb (book, status, load_source_data->closure); free_load_source_data (load_source_data); } guint addressbook_load_source (EBook *book, ESource *source, EBookCallback cb, gpointer closure) { LoadSourceData *load_source_data = g_new0 (LoadSourceData, 1); load_source_data->cb = cb; load_source_data->closure = closure; load_source_data->source = g_object_ref (source); load_source_data->cancelled = FALSE; e_book_async_load_source (book, source, load_source_cb, load_source_data); return GPOINTER_TO_UINT (load_source_data); } void addressbook_load_source_cancel (guint id) { LoadSourceData *load_source_data = GUINT_TO_POINTER (id); load_source_data->cancelled = TRUE; } static void default_book_cb (EBook *book, EBookStatus status, gpointer closure) { LoadSourceData *load_source_data = closure; if (status == E_BOOK_ERROR_OK) load_source_data->source = g_object_ref (e_book_get_source (book)); load_source_cb (book, status, closure); } void addressbook_load_default_book (EBookCallback cb, gpointer closure) { LoadSourceData *load_source_data = g_new (LoadSourceData, 1); load_source_data->cb = cb; load_source_data->source = NULL; load_source_data->closure = closure; load_source_data->cancelled = FALSE; e_book_async_get_default_addressbook (default_book_cb, load_source_data); } static void activate_source (AddressbookView *view, ESource *source, const char *uid) { GtkWidget *uid_view; EBook *book; BookOpenData *data; uid_view = g_hash_table_lookup (view->uid_to_view, uid); if (uid_view) { /* there is a view for this uid. make sure that the view actually contains an EBook (if it doesn't contain an EBook a previous load failed. try to load it again */ g_object_get (uid_view, "book", &book, NULL); if (book) { g_object_unref (book); } else { book = e_book_new (); g_object_get (uid_view, "source", &source, NULL); /* source can be NULL here, if a previous load hasn't actually made it to book_open_cb yet. */ if (source) { data = g_new (BookOpenData, 1); data->view = g_object_ref (uid_view); data->source = source; /* transfer the ref we get back from g_object_get */ addressbook_load_source (book, source, book_open_cb, data); } } } else { /* we don't have a view for this uid already set up. */ GtkWidget *label = gtk_label_new (uid); uid_view = eab_view_new (); gtk_widget_show (uid_view); gtk_widget_show (label); g_object_set (uid_view, "type", EAB_VIEW_TABLE, NULL); gtk_notebook_append_page (GTK_NOTEBOOK (view->notebook), uid_view, label); g_hash_table_insert (view->uid_to_view, g_strdup (uid), uid_view); g_signal_connect (uid_view, "status_message", G_CALLBACK(set_status_message), view); g_signal_connect (uid_view, "search_result", G_CALLBACK(search_result), view); g_signal_connect (uid_view, "command_state_change", G_CALLBACK(update_command_state), view); book = e_book_new (); data = g_new (BookOpenData, 1); data->view = g_object_ref (uid_view); data->source = g_object_ref (source); addressbook_load_source (book, source, book_open_cb, data); } gtk_notebook_set_current_page (GTK_NOTEBOOK (view->notebook), gtk_notebook_page_num (GTK_NOTEBOOK (view->notebook), uid_view)); /* change menus/toolbars to reflect the new view, assuming we are already displayed */ if (bonobo_ui_component_get_container (bonobo_control_get_ui_component (view->control)) != CORBA_OBJECT_NIL) { eab_view_setup_menus (EAB_VIEW (uid_view), bonobo_control_get_ui_component (view->control)); update_command_state (EAB_VIEW (uid_view), view); } } static void set_prop (BonoboPropertyBag *bag, const BonoboArg *arg, guint arg_id, CORBA_Environment *ev, gpointer user_data) { AddressbookView *view = user_data; ESource *source; switch (arg_id) { case PROPERTY_FOLDER_URI_IDX: { const gchar *string = BONOBO_ARG_GET_STRING (arg); ESourceGroup *group; group = e_source_group_new ("", string); source = e_source_new ("", ""); e_source_set_group (source, group); /* we use the uri as the uid here. */ activate_source (view, source, string); g_object_unref (group); break; } case PROPERTY_SOURCE_UID_IDX: { const gchar *uid; uid = BONOBO_ARG_GET_STRING (arg); source = e_source_list_peek_source_by_uid (view->source_list, uid); if (source) { activate_source (view, source, uid); } else { g_warning ("Could not find source by UID '%s'!", uid); } break; } default: g_warning ("Unhandled arg %d\n", arg_id); break; } } static void get_prop (BonoboPropertyBag *bag, BonoboArg *arg, guint arg_id, CORBA_Environment *ev, gpointer user_data) { AddressbookView *view = user_data; EABView *v = get_current_view (view); ESource *source = NULL; switch (arg_id) { case PROPERTY_FOLDER_URI_IDX: if (v) { g_object_get (v, "source", &source, NULL); } if (source) { char *uri = e_source_get_uri (source); BONOBO_ARG_SET_STRING (arg, uri); g_free (uri); g_object_unref (source); } else { BONOBO_ARG_SET_STRING (arg, ""); } break; case PROPERTY_SOURCE_UID_IDX: if (v) { g_object_get (v, "source", &source, NULL); } if (source) { BONOBO_ARG_SET_STRING (arg, e_source_peek_uid (source)); g_object_unref (source); } else { BONOBO_ARG_SET_STRING (arg, ""); } break; default: g_warning ("Unhandled arg %d\n", arg_id); } } BonoboControl * addressbook_new_control (void) { AddressbookView *view; view = g_new0 (AddressbookView, 1); view->refs = 1; view->uid_to_view = g_hash_table_new_full (g_str_hash, g_str_equal, (GDestroyNotify)g_free, NULL); view->notebook = gtk_notebook_new (); gtk_notebook_set_show_tabs (GTK_NOTEBOOK (view->notebook), FALSE); gtk_notebook_set_show_border (GTK_NOTEBOOK (view->notebook), FALSE); g_object_weak_ref (G_OBJECT (view->notebook), destroy_callback, view); /* Create the control. */ view->control = bonobo_control_new (view->notebook); gtk_widget_show (view->notebook); view->properties = bonobo_property_bag_new (get_prop, set_prop, view); bonobo_property_bag_add (view->properties, PROPERTY_SOURCE_UID, PROPERTY_SOURCE_UID_IDX, BONOBO_ARG_STRING, NULL, _("UID of the contacts source that the view will display"), 0); bonobo_property_bag_add (view->properties, PROPERTY_FOLDER_URI, PROPERTY_FOLDER_URI_IDX, BONOBO_ARG_STRING, NULL, _("The URI that the address book will display"), 0); bonobo_control_set_properties (view->control, bonobo_object_corba_objref (BONOBO_OBJECT (view->properties)), NULL); view->source_list = e_source_list_new_for_gconf_default ("/apps/evolution/addressbook/sources"); g_signal_connect (view->source_list, "changed", G_CALLBACK (source_list_changed_cb), view); view->creatable_items_handler = e_user_creatable_items_handler_new ("contacts"); g_signal_connect (view->control, "activate", G_CALLBACK (control_activate_cb), view); return view->control; }