diff options
Diffstat (limited to 'addressbook/gui')
35 files changed, 916 insertions, 1066 deletions
diff --git a/addressbook/gui/Makefile.am b/addressbook/gui/Makefile.am index a737452bd3..630744169e 100644 --- a/addressbook/gui/Makefile.am +++ b/addressbook/gui/Makefile.am @@ -1 +1 @@ -SUBDIRS = merging contact-editor contact-list-editor widgets component +SUBDIRS = merging widgets contact-editor contact-list-editor component diff --git a/addressbook/gui/component/Makefile.am b/addressbook/gui/component/Makefile.am index 9bfdabe13d..0e4747f2a5 100644 --- a/addressbook/gui/component/Makefile.am +++ b/addressbook/gui/component/Makefile.am @@ -30,8 +30,8 @@ libevolution_addressbook_la_SOURCES = \ addressbook-config.h \ autocompletion-config.c \ autocompletion-config.h \ - addressbook.c \ - addressbook.h \ + eab-composer-util.c \ + eab-composer-util.h \ e-book-shell-content.c \ e-book-shell-content.h \ e-book-shell-module.c \ @@ -53,6 +53,7 @@ endif libevolution_addressbook_la_LIBADD = \ $(SMIME_LIB) \ $(top_builddir)/e-util/libeutil.la \ + $(top_builddir)/composer/libcomposer.la \ $(top_builddir)/addressbook/printing/libecontactprint.la \ $(top_builddir)/shell/libeshell.la \ $(top_builddir)/addressbook/gui/merging/libeabbookmerging.la \ diff --git a/addressbook/gui/component/addressbook.c b/addressbook/gui/component/addressbook.c deleted file mode 100644 index c8285d8171..0000000000 --- a/addressbook/gui/component/addressbook.c +++ /dev/null @@ -1,338 +0,0 @@ -/* - * This program is free software; you can redistribute it and/or - * 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 - * 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: - * Chris Lahey <clahey@ximian.com> - * - * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) - * - */ - -#include <config.h> - -#include <string.h> - -#include <gtk/gtk.h> -#include <glib/gi18n.h> -#include <libebook/e-book.h> -#include <libedataserver/e-url.h> -#include <libedataserverui/e-passwords.h> - -#include "e-util/e-error.h" -#include "addressbook.h" - -#define d(x) - -static void addressbook_authenticate (EBook *book, gboolean previous_failure, - ESource *source, EBookCallback cb, gpointer closure); -static void auth_required_cb (EBook *book, gpointer data); - -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); -} - -/*this function removes of anything present after semicolon -in uri*/ - -static gchar* -remove_parameters_from_uri (const gchar *uri) -{ - char *euri_str; - EUri *euri; - - euri = e_uri_new (uri); - euri_str = e_uri_to_string (euri, FALSE); - e_uri_free (euri); - return euri_str; -} - -static void -load_source_auth_cb (EBook *book, EBookStatus status, gpointer closure) -{ - LoadSourceData *data = closure; - gboolean was_in = g_object_get_data (G_OBJECT (book), "authenticated") != NULL; - - g_object_set_data (G_OBJECT (book), "authenticated", NULL); - - if (data->cancelled) { - free_load_source_data (data); - return; - } - - if (status != E_BOOK_ERROR_OK) { - - /* the user clicked cancel in the password dialog */ - if (status == E_BOOK_ERROR_CANCELLED) { - - if (e_book_check_static_capability (book, "anon-access")) { - - GtkWidget *dialog; - - /* XXX "LDAP" has to be removed from the folowing message - so that it wil valid for other servers which provide - anonymous access*/ - - dialog = gtk_message_dialog_new (NULL, - 0, - GTK_MESSAGE_WARNING, - GTK_BUTTONS_OK, - "%s", _("Accessing LDAP Server anonymously")); - g_signal_connect (dialog, "response", G_CALLBACK(gtk_widget_destroy), NULL); - gtk_widget_show (dialog); - status = E_BOOK_ERROR_OK; - - goto done; - } - } else if (status == E_BOOK_ERROR_INVALID_SERVER_VERSION) { - e_error_run (NULL, "addressbook:server-version", NULL); - status = E_BOOK_ERROR_OK; - goto done; - } else if (status == E_BOOK_ERROR_UNSUPPORTED_AUTHENTICATION_METHOD) { - goto done; - } else { - if (status == E_BOOK_ERROR_AUTHENTICATION_FAILED) { - const gchar *uri = e_book_get_uri (book); - gchar *stripped_uri = remove_parameters_from_uri (uri); - const gchar *auth_domain = e_source_get_property (data->source, "auth-domain"); - const gchar *component_name; - - component_name = auth_domain ? auth_domain : "Addressbook"; - - e_passwords_forget_password (component_name, stripped_uri); - - g_free (stripped_uri); - } else if (was_in) { - /* We already tried to authenticate to the server, and it failed with - other reason than with E_BOOK_ERROR_AUTHENTICATION_FAILED, thus stop - poking with the server and report error to the user. */ - goto done; - } - - g_object_set_data (G_OBJECT (book), "authenticated", GINT_TO_POINTER (1)); - addressbook_authenticate (book, TRUE, data->source, load_source_auth_cb, closure); - return; - } - } - -done: - if (data->cb) - 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 && !g_ascii_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 = remove_parameters_from_uri(e_book_get_uri (book)); - const gchar *auth_domain = e_source_get_property (source, "auth-domain"); - const gchar *component_name; - - component_name = auth_domain ? auth_domain : "Addressbook"; - - password = e_passwords_get_password (component_name, uri); - - auth = e_source_get_property (source, "auth"); - - if (auth && !strcmp ("ldap/simple-binddn", auth)) { - user = e_source_get_property (source, "binddn"); - } - else if (auth && !strcmp ("plain/password", auth)) { - user = e_source_get_property (source, "user"); - if (!user) { - user = e_source_get_property (source, "username"); - } - } - else { - user = e_source_get_property (source, "email_addr"); - } - if (!user) - user = ""; - - if (!password) { - char *prompt; - char *password_prompt; - gboolean remember; - char *failed_auth; - guint32 flags = E_PASSWORDS_REMEMBER_FOREVER|E_PASSWORDS_SECRET|E_PASSWORDS_ONLINE; - - if (previous_failure) { - failed_auth = _("Failed to authenticate.\n"); - flags |= E_PASSWORDS_REPROMPT; - } - else { - failed_auth = ""; - } - - password_prompt = g_strdup_printf (_("Enter password for %s (user %s)"), - e_source_peek_name (source), user); - - prompt = g_strconcat (failed_auth, password_prompt, NULL); - g_free (password_prompt); - - remember = get_remember_password (source); - pass_dup = e_passwords_ask_password ( - _("Enter password"), component_name, - uri, prompt, flags, &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 -auth_required_cb (EBook *book, gpointer data) -{ - LoadSourceData *load_source_data = g_new0(LoadSourceData, 1); - - load_source_data->source = g_object_ref (g_object_ref (e_book_get_source (book))); - load_source_data->cancelled = FALSE; - addressbook_authenticate (book, FALSE, load_source_data->source, - load_source_auth_cb, load_source_data); - - - -} -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"); - if (auth && strcmp (auth, "none")) { - g_signal_connect (book, "auth_required", G_CALLBACK(auth_required_cb), NULL); - - if (e_book_is_online (book)) { - 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 (EBook *book, - 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 (g_object_ref (e_book_get_source (book))); - load_source_data->cancelled = FALSE; - - e_book_async_open (book, FALSE, load_source_cb, load_source_data); - - return GPOINTER_TO_UINT (load_source_data); -} - -void -addressbook_load_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); - EBook *book; - - load_source_data->cb = cb; - load_source_data->source = NULL; - load_source_data->closure = closure; - load_source_data->cancelled = FALSE; - - book = e_book_new_default_addressbook (NULL); - if (!book) - load_source_cb (NULL, E_BOOK_ERROR_OTHER_ERROR, load_source_data); /* XXX we should just use a GError and it's error code here */ - else - e_book_async_open (book, FALSE, default_book_cb, load_source_data); -} diff --git a/addressbook/gui/component/e-book-shell-content.c b/addressbook/gui/component/e-book-shell-content.c index 8190a5958a..c9066c9ef1 100644 --- a/addressbook/gui/component/e-book-shell-content.c +++ b/addressbook/gui/component/e-book-shell-content.c @@ -44,6 +44,16 @@ enum { static gpointer parent_class; static void +book_shell_content_send_message_cb (EBookShellContent *book_shell_content, + EDestination *destination, + EABContactDisplay *display) +{ + GList node = { destination, NULL, NULL }; + + eab_send_message (&node, EAB_DISPOSITION_AS_TO); +} + +static void book_shell_content_set_property (GObject *object, guint property_id, const GValue *value, @@ -176,6 +186,10 @@ book_shell_content_constructed (GObject *object) priv->preview = g_object_ref (widget); gtk_widget_show (widget); + g_signal_connect_swapped ( + priv->preview, "send-message", + book_shell_content_send_message_cb, object); + /* Bind GObject properties to GConf keys. */ bridge = gconf_bridge_get (); diff --git a/addressbook/gui/component/e-book-shell-content.h b/addressbook/gui/component/e-book-shell-content.h index 7f48503a88..e8fe856a86 100644 --- a/addressbook/gui/component/e-book-shell-content.h +++ b/addressbook/gui/component/e-book-shell-content.h @@ -24,10 +24,11 @@ #include <libebook/e-contact.h> -#include <e-shell-content.h> -#include <e-shell-view.h> +#include "shell/e-shell-content.h" +#include "shell/e-shell-view.h" -#include <e-addressbook-view.h> +#include "addressbook/gui/component/eab-composer-util.h" +#include "addressbook/gui/widgets/e-addressbook-view.h" /* Standard GObject macros */ #define E_TYPE_BOOK_SHELL_CONTENT \ diff --git a/addressbook/gui/component/e-book-shell-module.c b/addressbook/gui/component/e-book-shell-module.c index fbe660b7b6..a3f8a7aea0 100644 --- a/addressbook/gui/component/e-book-shell-module.c +++ b/addressbook/gui/component/e-book-shell-module.c @@ -32,10 +32,12 @@ #include "shell/e-shell-window.h" #include "e-util/e-import.h" +#include "addressbook/gui/widgets/eab-gui-util.h" +#include "addressbook/gui/contact-editor/e-contact-editor.h" +#include "addressbook/gui/contact-list-editor/e-contact-list-editor.h" #include "addressbook/importers/evolution-addressbook-importers.h" #include <eab-config.h> -#include <eab-gui-util.h> #include <addressbook-config.h> #include <autocompletion-config.h> @@ -214,6 +216,7 @@ book_shell_module_book_loaded_cb (EBook *book, { EContact *contact; GtkAction *action; + GtkWidget *editor; const gchar *action_name; /* XXX Handle errors better. */ @@ -225,10 +228,12 @@ book_shell_module_book_loaded_cb (EBook *book, action_name = gtk_action_get_name (action); if (strcmp (action_name, "contact-new") == 0) - eab_show_contact_editor (book, contact, TRUE, TRUE); + editor = e_contact_editor_new (book, contact, TRUE, TRUE); if (strcmp (action_name, "contact-new-list") == 0) - eab_show_contact_list_editor (book, contact, TRUE, TRUE); + editor = e_contact_list_editor_new (book, contact, TRUE, TRUE); + + eab_editor_show (EAB_EDITOR (editor)); g_object_unref (contact); g_object_unref (book); diff --git a/addressbook/gui/component/e-book-shell-view-actions.c b/addressbook/gui/component/e-book-shell-view-actions.c index 15838f96bc..646715d88a 100644 --- a/addressbook/gui/component/e-book-shell-view-actions.c +++ b/addressbook/gui/component/e-book-shell-view-actions.c @@ -285,12 +285,30 @@ action_contact_forward_cb (GtkAction *action, { EBookShellContent *book_shell_content; EAddressbookView *view; + GList *list, *iter; book_shell_content = book_shell_view->priv->book_shell_content; view = e_book_shell_content_get_current_view (book_shell_content); g_return_if_fail (view != NULL); - e_addressbook_view_send (view); + list = e_addressbook_view_get_selected (view); + g_return_if_fail (list != NULL); + + /* Convert the list of contacts to a list of destinations. */ + for (iter = list; iter != NULL; iter = iter->next) { + EContact *contact = iter->data; + EDestination *destination; + + destination = e_destination_new (); + e_destination_set_contact (destination, contact, 0); + g_object_unref (contact); + + iter->data = destination; + } + + eab_send_message (list, EAB_DISPOSITION_AS_ATTACHMENT); + g_list_foreach (list, (GFunc) g_object_unref, NULL); + g_list_free (list); } static void @@ -315,6 +333,7 @@ action_contact_new_cb (GtkAction *action, EAddressbookView *view; EAddressbookModel *model; EContact *contact; + GtkWidget *editor; EBook *book; book_shell_content = book_shell_view->priv->book_shell_content; @@ -326,7 +345,8 @@ action_contact_new_cb (GtkAction *action, g_return_if_fail (book != NULL); contact = e_contact_new (); - eab_show_contact_editor (book, contact, TRUE, TRUE); + editor = e_contact_editor_new (book, contact, TRUE, TRUE); + eab_editor_show (EAB_EDITOR (editor)); g_object_unref (contact); } @@ -338,6 +358,7 @@ action_contact_new_list_cb (GtkAction *action, EAddressbookView *view; EAddressbookModel *model; EContact *contact; + GtkWidget *editor; EBook *book; book_shell_content = book_shell_view->priv->book_shell_content; @@ -349,7 +370,8 @@ action_contact_new_list_cb (GtkAction *action, g_return_if_fail (book != NULL); contact = e_contact_new (); - eab_show_contact_list_editor (book, contact, TRUE, TRUE); + editor = e_contact_list_editor_new (book, contact, TRUE, TRUE); + eab_editor_show (EAB_EDITOR (editor)); g_object_unref (contact); } @@ -445,12 +467,30 @@ action_contact_send_message_cb (GtkAction *action, { EBookShellContent *book_shell_content; EAddressbookView *view; + GList *list, *iter; book_shell_content = book_shell_view->priv->book_shell_content; view = e_book_shell_content_get_current_view (book_shell_content); g_return_if_fail (view != NULL); - e_addressbook_view_send_to (view); + list = e_addressbook_view_get_selected (view); + g_return_if_fail (list != NULL); + + /* Convert the list of contacts to a list of destinations. */ + for (iter = list; iter != NULL; iter = iter->next) { + EContact *contact = iter->data; + EDestination *destination; + + destination = e_destination_new (); + e_destination_set_contact (destination, contact, 0); + g_object_unref (contact); + + iter->data = destination; + } + + eab_send_message (list, EAB_DISPOSITION_AS_TO); + g_list_foreach (list, (GFunc) g_object_unref, NULL); + g_list_free (list); } static void diff --git a/addressbook/gui/component/e-book-shell-view-private.c b/addressbook/gui/component/e-book-shell-view-private.c index c3eecb5a8a..90ebad94f8 100644 --- a/addressbook/gui/component/e-book-shell-view-private.c +++ b/addressbook/gui/component/e-book-shell-view-private.c @@ -27,6 +27,31 @@ #include <addressbook.h> static void +open_contact (EBookShellView *book_shell_view, + EContact *contact, + gboolean is_new_contact, + EAddressbookView *view) +{ + EAddressbookModel *model; + GtkWidget *editor; + EBook *book; + gboolean editable; + + model = e_addressbook_view_get_model (view); + book = e_addressbook_model_get_book (model); + editable = e_addressbook_model_get_editable (model); + + if (e_contact_get (contact, E_CONTACT_IS_LIST)) + editor = e_contact_list_editor_new ( + book, contact, is_new_contact, editable); + else + editor = e_contact_editor_new ( + book, contact, is_new_contact, editable); + + eab_editor_show (EAB_EDITOR (editor)); +} + +static void popup_event (EBookShellView *book_shell_view, GdkEventButton *event) { @@ -215,6 +240,10 @@ book_shell_view_activate_selected_source (EBookShellView *book_shell_view, g_object_ref (widget)); g_signal_connect_swapped ( + widget, "open-contact", + G_CALLBACK (open_contact), book_shell_view); + + g_signal_connect_swapped ( widget, "popup-event", G_CALLBACK (popup_event), book_shell_view); diff --git a/addressbook/gui/component/e-book-shell-view-private.h b/addressbook/gui/component/e-book-shell-view-private.h index 0d7fd706f6..d53ced9440 100644 --- a/addressbook/gui/component/e-book-shell-view-private.h +++ b/addressbook/gui/component/e-book-shell-view-private.h @@ -32,15 +32,17 @@ #include <libedataserver/e-sexp.h> #include <libedataserverui/e-source-selector.h> -#include <e-util/gconf-bridge.h> -#include <shell/e-shell-content.h> -#include <shell/e-shell-sidebar.h> +#include "e-util/gconf-bridge.h" +#include "shell/e-shell-content.h" +#include "shell/e-shell-sidebar.h" + +#include "addressbook/gui/contact-editor/e-contact-editor.h" +#include "addressbook/gui/contact-list-editor/e-contact-list-editor.h" +#include "addressbook/gui/widgets/eab-gui-util.h" +#include "addressbook/gui/widgets/e-addressbook-view.h" -#include <eab-gui-util.h> -#include <e-addressbook-view.h> #include <e-book-shell-content.h> #include <e-book-shell-sidebar.h> - #include <e-book-shell-view-actions.h> #define E_BOOK_SHELL_VIEW_GET_PRIVATE(obj) \ diff --git a/addressbook/gui/component/eab-composer-util.c b/addressbook/gui/component/eab-composer-util.c new file mode 100644 index 0000000000..ce3a96cc13 --- /dev/null +++ b/addressbook/gui/component/eab-composer-util.c @@ -0,0 +1,214 @@ +/* + * This program is free software; you can redistribute it and/or + * 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 + * 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/> + * + * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) + * + */ + +#include "eab-composer-util.h" + +#include <glib/gi18n.h> +#include <libebook/e-contact.h> +#include <libebook/e-destination.h> + +#include "mail/em-composer-utils.h" +#include "composer/e-msg-composer.h" +#include "addressbook/util/eab-book-util.h" +#include "addressbook/gui/widgets/eab-gui-util.h" + +static void +eab_send_as_to (GList *destinations) +{ + EMsgComposer *composer; + EComposerHeaderTable *table; + GPtrArray *to_array; + GPtrArray *bcc_array; + + union { + gpointer *pdata; + EDestination **destinations; + } convert; + + if (destinations == NULL) + return; + + composer = e_msg_composer_new (); + table = e_msg_composer_get_header_table (composer); + em_composer_utils_setup_default_callbacks (composer); + + to_array = g_ptr_array_new (); + bcc_array = g_ptr_array_new (); + + /* Sort contacts into "To" and "Bcc" destinations. */ + while (destinations != NULL) { + EDestination *destination = destinations->data; + + if (e_destination_is_evolution_list (destination)) { + if (e_destination_list_show_addresses (destination)) + g_ptr_array_add (to_array, destination); + else + g_ptr_array_add (bcc_array, destination); + } else + g_ptr_array_add (to_array, destination); + + destinations = g_list_next (destinations); + } + + /* Add sentinels to each array. */ + g_ptr_array_add (to_array, NULL); + g_ptr_array_add (bcc_array, NULL); + + /* XXX Acrobatics like this make me question whether NULL-terminated + * arrays are really the best argument type for passing a list of + * destinations to the header table. */ + + /* Add "To" destinations. */ + convert.pdata = to_array->pdata; + e_composer_header_table_set_destinations_to ( + table, convert.destinations); + g_ptr_array_free (to_array, FALSE); + e_destination_freev (convert.destinations); + + /* Add "Bcc" destinations. */ + convert.pdata = bcc_array->pdata; + e_composer_header_table_set_destinations_bcc ( + table, convert.destinations); + g_ptr_array_free (bcc_array, FALSE); + e_destination_freev (convert.destinations); + + gtk_widget_show (GTK_WIDGET (composer)); +} + +static const char * +get_email (EContact *contact, EContactField field_id, gchar **to_free) +{ + char *name = NULL, *mail = NULL; + const char *value = e_contact_get_const (contact, field_id); + + *to_free = NULL; + + if (eab_parse_qp_email (value, &name, &mail)) { + *to_free = g_strdup_printf ("%s <%s>", name, mail); + value = *to_free; + } + + g_free (name); + g_free (mail); + + return value; +} + +static void +eab_send_as_attachment (GList *destinations) +{ + EMsgComposer *composer; + EComposerHeaderTable *table; + CamelMimePart *attachment; + GList *contacts, *iter; + gchar *data; + + if (contacts == NULL) + return; + + composer = e_msg_composer_new (); + table = e_msg_composer_get_header_table (composer); + em_composer_utils_setup_default_callbacks (composer); + + attachment = camel_mime_part_new (); + + contacts = g_list_copy (destinations); + for (iter = contacts; iter != NULL; iter = iter->next) + iter->data = e_destination_get_contact (iter->data); + data = eab_contact_list_to_string (contacts); + g_list_free (contacts); + + camel_mime_part_set_content ( + attachment, data, strlen (data), "text/x-vcard"); + + if (destinations->next != NULL) + camel_mime_part_set_description ( + attachment, _("Multiple vCards")); + else { + EContact *contact; + const gchar *file_as; + gchar *description; + + contact = e_destination_get_contact (destinations->data); + file_as = e_contact_get_const (contact, E_CONTACT_FILE_AS); + description = g_strdup_printf (_("vCard for %s"), file_as); + camel_mime_part_set_description (attachment, description); + g_free (description); + } + + camel_mime_part_set_disposition (attachment, "attachment"); + + e_msg_composer_attach (composer, attachment); + camel_object_unref (attachment); + + if (destinations->next != NULL) + e_composer_header_table_set_subject ( + table, _("Contact information")); + else { + EContact *contact; + gchar *tempstr; + const gchar *tempstr2; + gchar *tempfree = NULL; + + contact = e_destination_get_contact (destinations->data); + tempstr2 = e_contact_get_const (contact, E_CONTACT_FILE_AS); + if (!tempstr2 || !*tempstr2) + tempstr2 = e_contact_get_const (contact, E_CONTACT_FULL_NAME); + if (!tempstr2 || !*tempstr2) + tempstr2 = e_contact_get_const (contact, E_CONTACT_ORG); + if (!tempstr2 || !*tempstr2) { + g_free (tempfree); + tempstr2 = get_email (contact, E_CONTACT_EMAIL_1, &tempfree); + } + if (!tempstr2 || !*tempstr2) { + g_free (tempfree); + tempstr2 = get_email (contact, E_CONTACT_EMAIL_2, &tempfree); + } + if (!tempstr2 || !*tempstr2) { + g_free (tempfree); + tempstr2 = get_email (contact, E_CONTACT_EMAIL_3, &tempfree); + } + + if (!tempstr2 || !*tempstr2) + tempstr = g_strdup_printf (_("Contact information")); + else + tempstr = g_strdup_printf (_("Contact information for %s"), tempstr2); + + e_composer_header_table_set_subject (table, tempstr); + + g_free (tempstr); + g_free (tempfree); + } + + gtk_widget_show (GTK_WIDGET (composer)); +} + +void +eab_send_message (GList *destinations, + EABDisposition disposition) +{ + switch (disposition) { + case EAB_DISPOSITION_AS_TO: + eab_send_as_to (destinations); + break; + + case EAB_DISPOSITION_AS_ATTACHMENT: + eab_send_as_attachment (destinations); + break; + } +} diff --git a/addressbook/gui/component/addressbook.h b/addressbook/gui/component/eab-composer-util.h index 2e25448717..4e9ce581d0 100644 --- a/addressbook/gui/component/addressbook.h +++ b/addressbook/gui/component/eab-composer-util.h @@ -12,20 +12,25 @@ * 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: - * * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) * */ -#ifndef __ADDRESSBOOK_H__ -#define __ADDRESSBOOK_H__ +#ifndef EAB_COMPOSER_UTIL_H +#define EAB_COMPOSER_UTIL_H + +#include <gtk/gtk.h> + +G_BEGIN_DECLS + +typedef enum { + EAB_DISPOSITION_AS_ATTACHMENT, + EAB_DISPOSITION_AS_TO, +} EABDisposition; -#include <libebook/e-book.h> +void eab_send_message (GList *destinations, + EABDisposition disposition); -guint addressbook_load (EBook *book, EBookCallback cb, gpointer closure); -void addressbook_load_cancel (guint id); -void addressbook_load_default_book (EBookCallback open_response, gpointer closure); +G_END_DECLS -#endif /* __ADDRESSBOOK_H__ */ +#endif /* EAB_COMPOSER_UTIL_H */ diff --git a/addressbook/gui/contact-editor/Makefile.am b/addressbook/gui/contact-editor/Makefile.am index bed73df00b..f813db72e8 100644 --- a/addressbook/gui/contact-editor/Makefile.am +++ b/addressbook/gui/contact-editor/Makefile.am @@ -33,10 +33,14 @@ libecontacteditor_la_SOURCES = \ libecontacteditor_la_LDFLAGS = $(NO_UNDEFINED) -libecontacteditor_la_LIBADD = \ - $(WIN32_BOOTSTRAP_LIBS) \ - $(top_builddir)/widgets/misc/libemiscwidgets.la \ - $(top_builddir)/e-util/libeutil.la \ +libecontacteditor_la_LIBADD = \ + $(WIN32_BOOTSTRAP_LIBS) \ + $(top_builddir)/e-util/libeutil.la \ + $(top_builddir)/widgets/misc/libemiscwidgets.la \ + $(top_builddir)/addressbook/util/libeabutil.la \ + $(top_builddir)/addressbook/gui/widgets/libeabwidgets.la \ + $(top_builddir)/addressbook/gui/merging/libeabbookmerging.la \ + $(top_builddir)/addressbook/printing/libecontactprint.la \ $(EVOLUTION_ADDRESSBOOK_LIBS) glade_DATA = \ diff --git a/addressbook/gui/contact-editor/e-contact-editor.c b/addressbook/gui/contact-editor/e-contact-editor.c index 07d4a9ec0f..30d672161a 100644 --- a/addressbook/gui/contact-editor/e-contact-editor.c +++ b/addressbook/gui/contact-editor/e-contact-editor.c @@ -40,7 +40,7 @@ #include <camel/camel.h> -#include "addressbook/gui/component/addressbook.h" +#include "addressbook/util/addressbook.h" #include "addressbook/printing/e-contact-print.h" #include "addressbook/gui/widgets/eab-gui-util.h" #include "e-util/e-util.h" @@ -199,6 +199,54 @@ static const gint email_default [] = { 0, 1, 2, 2 }; #define STRING_IS_EMPTY(x) (!(x) || !(*(x))) #define STRING_MAKE_NON_NULL(x) ((x) ? (x) : "") +static void +e_contact_editor_contact_added (EABEditor *editor, + EBookStatus status, + EContact *contact) +{ + if (status == E_BOOK_ERROR_OK) + return; + + if (status == E_BOOK_ERROR_CANCELLED) + return; + + eab_error_dialog (_("Error adding contact"), status); +} + +static void +e_contact_editor_contact_modified (EABEditor *editor, + EBookStatus status, + EContact *contact) +{ + if (status == E_BOOK_ERROR_OK) + return; + + if (status == E_BOOK_ERROR_CANCELLED) + return; + + eab_error_dialog (_("Error modifying contact"), status); +} + +static void +e_contact_editor_contact_deleted (EABEditor *editor, + EBookStatus status, + EContact *contact) +{ + if (status == E_BOOK_ERROR_OK) + return; + + if (status == E_BOOK_ERROR_CANCELLED) + return; + + eab_error_dialog (_("Error removing contact"), status); +} + +static void +e_contact_editor_closed (EABEditor *editor) +{ + g_object_unref (editor); +} + GType e_contact_editor_get_type (void) { @@ -242,6 +290,10 @@ e_contact_editor_class_init (EContactEditorClass *klass) editor_class->save_contact = e_contact_editor_save_contact; editor_class->is_changed = e_contact_editor_is_changed; editor_class->get_window = e_contact_editor_get_window; + editor_class->contact_added = e_contact_editor_contact_added; + editor_class->contact_modified = e_contact_editor_contact_modified; + editor_class->contact_deleted = e_contact_editor_contact_deleted; + editor_class->editor_closed = e_contact_editor_closed; g_object_class_install_property (object_class, PROP_SOURCE_BOOK, g_param_spec_object ("source_book", @@ -3470,7 +3522,7 @@ contact_editor_destroy_notify (void *data, eab_editor_remove (EAB_EDITOR (data)); } -EContactEditor * +GtkWidget * e_contact_editor_new (EBook *book, EContact *contact, gboolean is_new_contact, @@ -3496,7 +3548,7 @@ e_contact_editor_new (EBook *book, if (book) e_book_async_get_supported_fields (book, (EBookEListCallback)supported_fields_cb, ce); - return ce; + return GTK_WIDGET (ce); } static void diff --git a/addressbook/gui/contact-editor/e-contact-editor.h b/addressbook/gui/contact-editor/e-contact-editor.h index 7fd94698c8..d4af1495c2 100644 --- a/addressbook/gui/contact-editor/e-contact-editor.h +++ b/addressbook/gui/contact-editor/e-contact-editor.h @@ -109,11 +109,11 @@ struct _EContactEditorClass EABEditorClass parent_class; }; -EContactEditor *e_contact_editor_new (EBook *book, - EContact *contact, - gboolean is_new_contact, - gboolean editable); -GType e_contact_editor_get_type (void); +GType e_contact_editor_get_type (void); +GtkWidget *e_contact_editor_new (EBook *book, + EContact *contact, + gboolean is_new_contact, + gboolean editable); G_END_DECLS diff --git a/addressbook/gui/contact-editor/e-contact-quick-add.c b/addressbook/gui/contact-editor/e-contact-quick-add.c index 175af68d43..6de903d16f 100644 --- a/addressbook/gui/contact-editor/e-contact-quick-add.c +++ b/addressbook/gui/contact-editor/e-contact-quick-add.c @@ -29,7 +29,7 @@ #include <libebook/e-book.h> #include <libebook/e-contact.h> #include <libedataserverui/e-source-combo-box.h> -#include <addressbook/gui/component/addressbook.h> +#include <addressbook/util/addressbook.h> #include <addressbook/util/eab-book-util.h> #include "e-contact-editor.h" #include "e-contact-quick-add.h" @@ -195,7 +195,7 @@ ce_have_book (EBook *book, EBookStatus status, gpointer closure) g_warning ("Couldn't open local address book."); quick_add_unref (qa); } else { - EContactEditor *contact_editor = e_contact_editor_new (book, qa->contact, TRUE, TRUE /* XXX */); + GtkWidget *contact_editor = e_contact_editor_new (book, 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, diff --git a/addressbook/gui/contact-editor/eab-editor.c b/addressbook/gui/contact-editor/eab-editor.c index 25a6e5d3e5..d45fb688ea 100644 --- a/addressbook/gui/contact-editor/eab-editor.c +++ b/addressbook/gui/contact-editor/eab-editor.c @@ -310,51 +310,6 @@ eab_editor_get_all_editors (void) return all_editors; } -gboolean -eab_editor_confirm_delete (GtkWindow *parent, gboolean plural, gboolean is_list, char *name) -{ - GtkWidget *dialog; - gint result; - char *msg; - - if (is_list) { - /* contact list(s) */ - if (!plural) - msg = g_strdup_printf (_("Are you sure you want\nto delete contact list (%s)?"), - name?name:""); - else - msg = g_strdup (_("Are you sure you want\nto delete these contact lists?")); - } - else { - /* contact(s) */ - if (!plural) - msg = g_strdup_printf (_("Are you sure you want\nto delete contact (%s)?"), - name?name:""); - else - msg = g_strdup (_("Are you sure you want\nto delete these contacts?")); - } - - dialog = gtk_message_dialog_new (parent, - 0, - GTK_MESSAGE_QUESTION, - GTK_BUTTONS_NONE, - "%s", - msg); - g_free (msg); - - gtk_dialog_add_buttons (GTK_DIALOG (dialog), - GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, - GTK_STOCK_DELETE, GTK_RESPONSE_ACCEPT, - NULL); - - result = gtk_dialog_run(GTK_DIALOG (dialog)); - - gtk_widget_destroy (dialog); - - return (result == GTK_RESPONSE_ACCEPT); -} - - void eab_editor_contact_added (EABEditor *editor, EBookStatus status, EContact *contact) { diff --git a/addressbook/gui/contact-editor/eab-editor.h b/addressbook/gui/contact-editor/eab-editor.h index c106ec75a6..cc95e003e1 100644 --- a/addressbook/gui/contact-editor/eab-editor.h +++ b/addressbook/gui/contact-editor/eab-editor.h @@ -92,7 +92,6 @@ gboolean eab_editor_is_changed (EABEditor *editor); GtkWindow* eab_editor_get_window (EABEditor *editor); gboolean eab_editor_prompt_to_save_changes (EABEditor *editor, GtkWindow *window); -gboolean eab_editor_confirm_delete (GtkWindow *parent, gboolean plural, gboolean is_list, char *name); /* these four generate EABEditor signals */ void eab_editor_contact_added (EABEditor *editor, EBookStatus status, EContact *contact); diff --git a/addressbook/gui/contact-list-editor/e-contact-list-editor.c b/addressbook/gui/contact-list-editor/e-contact-list-editor.c index 7f15ff1350..ccaf9b740f 100644 --- a/addressbook/gui/contact-list-editor/e-contact-list-editor.c +++ b/addressbook/gui/contact-list-editor/e-contact-list-editor.c @@ -34,8 +34,8 @@ #include <libedataserverui/e-source-combo-box.h> -#include "addressbook/gui/component/addressbook.h" #include "addressbook/gui/widgets/eab-gui-util.h" +#include "addressbook/util/addressbook.h" #include "addressbook/util/eab-book-util.h" #include "eab-editor.h" @@ -922,87 +922,6 @@ contact_list_editor_create_name_selector (gchar *name, return GTK_WIDGET (name_selector_entry); } -/**************************** EABEditor Callbacks ****************************/ - -static void -contact_list_editor_show (EABEditor *editor) -{ - gtk_widget_show (WIDGET (DIALOG)); -} - -static void -contact_list_editor_close (EABEditor *editor) -{ - gtk_widget_destroy (WIDGET (DIALOG)); - eab_editor_closed (editor); -} - -static void -contact_list_editor_raise (EABEditor *editor) -{ - gdk_window_raise (WIDGET (DIALOG)->window); -} - -static void -contact_list_editor_save_contact (EABEditor *eab_editor, - gboolean should_close) -{ - EContactListEditor *editor = E_CONTACT_LIST_EDITOR (eab_editor); - EContactListEditorPrivate *priv = editor->priv; - EditorCloseStruct *ecs; - EContact *contact; - - contact = e_contact_list_editor_get_contact (editor); - - if (priv->book == NULL) - return; - - ecs = g_new (EditorCloseStruct, 1); - ecs->editor = g_object_ref (editor); - ecs->should_close = should_close; - - gtk_widget_set_sensitive (WIDGET (DIALOG), FALSE); - priv->in_async_call = TRUE; - - if (priv->is_new_list) - eab_merging_book_add_contact ( - priv->book, contact, (EBookIdCallback) - contact_list_editor_list_added_cb, ecs); - else - eab_merging_book_commit_contact ( - priv->book, contact, (EBookCallback) - contact_list_editor_list_modified_cb, ecs); - - priv->changed = FALSE; -} - -static gboolean -contact_list_editor_is_valid (EABEditor *editor) -{ - GtkEditable *editable; - gboolean valid; - gchar *chars; - - editable = GTK_EDITABLE (WIDGET (LIST_NAME_ENTRY)); - chars = gtk_editable_get_chars (editable, 0, -1); - valid = (chars != NULL && *chars != '\0'); - g_free (chars); - - return valid; -} - -static gboolean -contact_list_editor_is_changed (EABEditor *editor) -{ - return E_CONTACT_LIST_EDITOR_GET_PRIVATE (editor)->changed; -} - -static GtkWindow* -contact_list_editor_get_window (EABEditor *editor) -{ - return GTK_WINDOW (WIDGET (DIALOG)); -} - /***************************** GObject Callbacks *****************************/ static GObject * @@ -1112,6 +1031,135 @@ contact_list_editor_dispose (GObject *object) G_OBJECT_CLASS (parent_class)->dispose (object); } +/**************************** EABEditor Callbacks ****************************/ + +static void +contact_list_editor_show (EABEditor *editor) +{ + gtk_widget_show (WIDGET (DIALOG)); +} + +static void +contact_list_editor_close (EABEditor *editor) +{ + gtk_widget_destroy (WIDGET (DIALOG)); + eab_editor_closed (editor); +} + +static void +contact_list_editor_raise (EABEditor *editor) +{ + gdk_window_raise (WIDGET (DIALOG)->window); +} + +static void +contact_list_editor_save_contact (EABEditor *eab_editor, + gboolean should_close) +{ + EContactListEditor *editor = E_CONTACT_LIST_EDITOR (eab_editor); + EContactListEditorPrivate *priv = editor->priv; + EditorCloseStruct *ecs; + EContact *contact; + + contact = e_contact_list_editor_get_contact (editor); + + if (priv->book == NULL) + return; + + ecs = g_new (EditorCloseStruct, 1); + ecs->editor = g_object_ref (editor); + ecs->should_close = should_close; + + gtk_widget_set_sensitive (WIDGET (DIALOG), FALSE); + priv->in_async_call = TRUE; + + if (priv->is_new_list) + eab_merging_book_add_contact ( + priv->book, contact, (EBookIdCallback) + contact_list_editor_list_added_cb, ecs); + else + eab_merging_book_commit_contact ( + priv->book, contact, (EBookCallback) + contact_list_editor_list_modified_cb, ecs); + + priv->changed = FALSE; +} + +static gboolean +contact_list_editor_is_valid (EABEditor *editor) +{ + GtkEditable *editable; + gboolean valid; + gchar *chars; + + editable = GTK_EDITABLE (WIDGET (LIST_NAME_ENTRY)); + chars = gtk_editable_get_chars (editable, 0, -1); + valid = (chars != NULL && *chars != '\0'); + g_free (chars); + + return valid; +} + +static gboolean +contact_list_editor_is_changed (EABEditor *editor) +{ + return E_CONTACT_LIST_EDITOR_GET_PRIVATE (editor)->changed; +} + +static GtkWindow * +contact_list_editor_get_window (EABEditor *editor) +{ + return GTK_WINDOW (WIDGET (DIALOG)); +} + +static void +contact_list_editor_contact_added (EABEditor *editor, + EBookStatus status, + EContact *contact) +{ + if (status == E_BOOK_ERROR_OK) + return; + + if (status == E_BOOK_ERROR_CANCELLED) + return; + + eab_error_dialog (_("Error adding list"), status); +} + +static void +contact_list_editor_contact_modified (EABEditor *editor, + EBookStatus status, + EContact *contact) +{ + if (status == E_BOOK_ERROR_OK) + return; + + if (status == E_BOOK_ERROR_CANCELLED) + return; + + eab_error_dialog (_("Error modifying list"), status); +} + +static void +contact_list_editor_contact_deleted (EABEditor *editor, + EBookStatus status, + EContact *contact) +{ + if (status == E_BOOK_ERROR_OK) + return; + + if (status == E_BOOK_ERROR_CANCELLED) + return; + + eab_error_dialog (_("Error removing list"), status); +} + +static void +contact_list_editor_closed (EABEditor *editor) +{ + g_object_unref (editor); +} + /****************************** GType Callbacks ******************************/ static void @@ -1137,6 +1185,10 @@ contact_list_editor_class_init (EContactListEditorClass *class) editor_class->is_valid = contact_list_editor_is_valid; editor_class->is_changed = contact_list_editor_is_changed; editor_class->get_window = contact_list_editor_get_window; + editor_class->contact_added = contact_list_editor_contact_added; + editor_class->contact_modified = contact_list_editor_contact_modified; + editor_class->contact_deleted = contact_list_editor_contact_deleted; + editor_class->editor_closed = contact_list_editor_closed; g_object_class_install_property ( object_class, @@ -1274,7 +1326,7 @@ contact_list_editor_destroy_notify (gpointer data, eab_editor_remove (EAB_EDITOR (data)); } -EContactListEditor * +GtkWidget * e_contact_list_editor_new (EBook *book, EContact *list_contact, gboolean is_new_list, @@ -1295,7 +1347,7 @@ e_contact_list_editor_new (EBook *book, "editable", editable, NULL); - return editor; + return GTK_WIDGET (editor); } EBook * diff --git a/addressbook/gui/contact-list-editor/e-contact-list-editor.h b/addressbook/gui/contact-list-editor/e-contact-list-editor.h index a2bd50acf5..2c420fcbd2 100644 --- a/addressbook/gui/contact-list-editor/e-contact-list-editor.h +++ b/addressbook/gui/contact-list-editor/e-contact-list-editor.h @@ -70,7 +70,7 @@ struct _EContactListEditorClass }; GType e_contact_list_editor_get_type (void); -EContactListEditor * e_contact_list_editor_new (EBook *book, +GtkWidget * e_contact_list_editor_new (EBook *book, EContact *list_contact, gboolean is_new_list, gboolean editable); diff --git a/addressbook/gui/merging/eab-contact-compare.c b/addressbook/gui/merging/eab-contact-compare.c index adc6938c8d..b5597abb29 100644 --- a/addressbook/gui/merging/eab-contact-compare.c +++ b/addressbook/gui/merging/eab-contact-compare.c @@ -24,8 +24,8 @@ #include <config.h> #include <ctype.h> #include <string.h> -#include "util/eab-book-util.h" -#include "../component/addressbook.h" +#include "addressbook/util/addressbook.h" +#include "addressbook/util/eab-book-util.h" #include "eab-contact-compare.h" /* This is an "optimistic" combiner: the best of the two outcomes is diff --git a/addressbook/gui/widgets/Makefile.am b/addressbook/gui/widgets/Makefile.am index c06328c2aa..b5afef0374 100644 --- a/addressbook/gui/widgets/Makefile.am +++ b/addressbook/gui/widgets/Makefile.am @@ -10,9 +10,7 @@ INCLUDES = \ -I$(top_srcdir)/filter \ -I$(top_srcdir)/widgets \ -I$(top_srcdir)/addressbook \ - -I$(top_srcdir)/addressbook/gui/contact-editor \ -I$(top_srcdir)/addressbook/gui/merging \ - -I$(top_srcdir)/addressbook/gui/component \ -I$(top_srcdir)/addressbook/util \ -I$(top_srcdir)/widgets/misc \ -I$(top_builddir)/shell \ @@ -56,8 +54,8 @@ libeabwidgets_la_SOURCES = \ gal-view-factory-minicard.h libeabwidgets_la_LIBADD = \ - $(top_builddir)/composer/libcomposer.la \ - $(top_builddir)/widgets/misc/libemiscwidgets.la + $(top_builddir)/widgets/misc/libemiscwidgets.la \ + $(top_builddir)/a11y/addressbook/libevolution-addressbook-a11y.la CLEANFILES = $(BUILT_SOURCES) diff --git a/addressbook/gui/widgets/e-addressbook-reflow-adapter.c b/addressbook/gui/widgets/e-addressbook-reflow-adapter.c index d344641c8f..2a2f1a2d87 100644 --- a/addressbook/gui/widgets/e-addressbook-reflow-adapter.c +++ b/addressbook/gui/widgets/e-addressbook-reflow-adapter.c @@ -54,10 +54,11 @@ enum { enum { DRAG_BEGIN, + OPEN_CONTACT, LAST_SIGNAL }; -static guint e_addressbook_reflow_adapter_signals [LAST_SIGNAL] = {0, }; +static guint signals [LAST_SIGNAL] = {0, }; static void unlink_model(EAddressbookReflowAdapter *adapter) @@ -227,12 +228,20 @@ adapter_drag_begin (EMinicard *card, GdkEvent *event, EAddressbookReflowAdapter gint ret_val = 0; g_signal_emit (adapter, - e_addressbook_reflow_adapter_signals[DRAG_BEGIN], 0, + signals[DRAG_BEGIN], 0, event, &ret_val); return ret_val; } +static void +adapter_open_contact (EMinicard *card, + EContact *contact, + EAddressbookReflowAdapter *adapter) +{ + g_signal_emit (adapter, signals[OPEN_CONTACT], 0, contact); +} + static GnomeCanvasItem * addressbook_incarnate (EReflowModel *erm, int i, GnomeCanvasGroup *parent) { @@ -252,7 +261,10 @@ addressbook_incarnate (EReflowModel *erm, int i, GnomeCanvasGroup *parent) #endif g_signal_connect (item, "drag_begin", - G_CALLBACK(adapter_drag_begin), adapter); + G_CALLBACK (adapter_drag_begin), adapter); + + g_signal_connect (item, "open-contact", + G_CALLBACK (adapter_open_contact), adapter); return item; } @@ -427,7 +439,7 @@ e_addressbook_reflow_adapter_class_init (GObjectClass *object_class) E_TYPE_ADDRESSBOOK_MODEL, G_PARAM_READABLE)); - e_addressbook_reflow_adapter_signals [DRAG_BEGIN] = + signals [DRAG_BEGIN] = g_signal_new ("drag_begin", G_OBJECT_CLASS_TYPE(object_class), G_SIGNAL_RUN_LAST, @@ -436,6 +448,16 @@ e_addressbook_reflow_adapter_class_init (GObjectClass *object_class) e_marshal_INT__POINTER, G_TYPE_INT, 1, G_TYPE_POINTER); + signals [OPEN_CONTACT] = + g_signal_new ("open-contact", + G_OBJECT_CLASS_TYPE (object_class), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (EAddressbookReflowAdapterClass, open_contact), + NULL, NULL, + g_cclosure_marshal_VOID__OBJECT, + G_TYPE_NONE, 1, + E_TYPE_CONTACT); + model_class->set_width = addressbook_set_width; model_class->count = addressbook_count; model_class->height = addressbook_height; diff --git a/addressbook/gui/widgets/e-addressbook-reflow-adapter.h b/addressbook/gui/widgets/e-addressbook-reflow-adapter.h index 99925d2dce..5032f3e2d0 100644 --- a/addressbook/gui/widgets/e-addressbook-reflow-adapter.h +++ b/addressbook/gui/widgets/e-addressbook-reflow-adapter.h @@ -48,7 +48,10 @@ struct _EAddressbookReflowAdapterClass { /* * Signals */ - gint (* drag_begin) (EAddressbookReflowAdapter *adapter, GdkEvent *event); + gint (*drag_begin) (EAddressbookReflowAdapter *adapter, + GdkEvent *event); + void (*open_contact) (EAddressbookReflowAdapter *adapter, + EContact *contact); }; diff --git a/addressbook/gui/widgets/e-addressbook-view.c b/addressbook/gui/widgets/e-addressbook-view.c index 1120ae2569..f7c506ee78 100644 --- a/addressbook/gui/widgets/e-addressbook-view.c +++ b/addressbook/gui/widgets/e-addressbook-view.c @@ -53,7 +53,6 @@ #include "e-util/e-error.h" #include "e-util/e-util-private.h" -#include "e-contact-editor.h" #include <gdk/gdkkeysyms.h> #include <ctype.h> #include <string.h> @@ -69,7 +68,6 @@ static void search_result (EAddressbookView *view, EBookViewStatus status); static void folder_bar_message (EAddressbookView *view, const gchar *status); static void stop_state_changed (GtkObject *object, EAddressbookView *view); static void backend_died (EAddressbookView *view); -static GList *get_selected_contacts (EAddressbookView *view); static void command_state_change (EAddressbookView *view); @@ -98,6 +96,7 @@ enum { }; enum { + OPEN_CONTACT, POPUP_EVENT, COMMAND_STATE_CHANGE, SELECTION_CHANGE, @@ -119,6 +118,14 @@ static guint signals[LAST_SIGNAL]; static GdkAtom clipboard_atom = GDK_NONE; static void +addressbook_view_emit_open_contact (EAddressbookView *view, + EContact *contact, + gboolean is_new_contact) +{ + g_signal_emit (view, signals[OPEN_CONTACT], 0, contact, is_new_contact); +} + +static void addressbook_view_emit_popup_event (EAddressbookView *view, GdkEvent *event) { @@ -132,6 +139,34 @@ addressbook_view_emit_selection_change (EAddressbookView *view) } static void +addressbook_view_open_contact (EAddressbookView *view, + EContact *contact) +{ + addressbook_view_emit_open_contact (view, contact, FALSE); +} + +static void +addressbook_view_create_contact (EAddressbookView *view) +{ + EContact *contact; + + contact = e_contact_new (); + addressbook_view_emit_open_contact (view, contact, TRUE); + g_object_unref (contact); +} + +static void +addressbook_view_create_contact_list (EAddressbookView *view) +{ + EContact *contact; + + contact = e_contact_new (); + e_contact_set (contact, E_CONTACT_IS_LIST, GINT_TO_POINTER (TRUE)); + addressbook_view_emit_open_contact (view, contact, TRUE); + g_object_unref (contact); +} + +static void table_double_click (ETableScrolled *table, gint row, gint col, @@ -140,23 +175,13 @@ table_double_click (ETableScrolled *table, { EAddressbookModel *model; EContact *contact; - EBook *book; - gboolean editable; if (!E_IS_ADDRESSBOOK_TABLE_ADAPTER (view->priv->object)) return; - model = view->priv->model; + model = e_addressbook_view_get_model (view); contact = e_addressbook_model_get_contact (model, row); - editable = e_addressbook_model_get_editable (model); - book = e_addressbook_model_get_book (model); - g_return_if_fail (E_IS_BOOK (book)); - - if (e_contact_get (contact, E_CONTACT_IS_LIST)) - eab_show_contact_list_editor (book, contact, FALSE, editable); - else - eab_show_contact_editor (book, contact, FALSE, editable); - + addressbook_view_emit_open_contact (view, contact, FALSE); g_object_unref (contact); } @@ -209,7 +234,7 @@ table_drag_data_get (ETable *table, model = e_addressbook_view_get_model (view); book = e_addressbook_model_get_book (model); - contact_list = get_selected_contacts (view); + contact_list = e_addressbook_view_get_selected (view); switch (info) { case DND_TARGET_TYPE_VCARD: @@ -300,6 +325,18 @@ addressbook_view_create_minicard_view (EAddressbookView *view) minicard_view = e_minicard_view_widget_new (adapter); g_signal_connect_swapped ( + adapter, "open-contact", + G_CALLBACK (addressbook_view_open_contact), view); + + g_signal_connect_swapped ( + minicard_view, "create-contact", + G_CALLBACK (addressbook_view_create_contact), view); + + g_signal_connect_swapped ( + minicard_view, "create-contact-list", + G_CALLBACK (addressbook_view_create_contact_list), view); + + g_signal_connect_swapped ( minicard_view, "selection_change", G_CALLBACK (addressbook_view_emit_selection_change), view); @@ -644,6 +681,16 @@ addressbook_view_class_init (EAddressbookViewClass *class) G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)); + signals[OPEN_CONTACT] = g_signal_new ( + "open-contact", + G_TYPE_FROM_CLASS (class), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (EAddressbookViewClass, open_contact), + NULL, NULL, + g_cclosure_marshal_VOID__OBJECT, + G_TYPE_NONE, 1, + E_TYPE_CONTACT); + signals[POPUP_EVENT] = g_signal_new ( "popup-event", G_TYPE_FROM_CLASS (class), @@ -801,6 +848,34 @@ e_addressbook_view_get_view_widget (EAddressbookView *view) return view->priv->widget; } +/* Helper for e_addressbook_view_get_selected() */ +static void +add_to_list (gint model_row, gpointer closure) +{ + GList **list = closure; + *list = g_list_prepend (*list, GINT_TO_POINTER (model_row)); +} + +GList * +e_addressbook_view_get_selected (EAddressbookView *view) +{ + GList *list, *iter; + ESelectionModel *selection; + + g_return_val_if_fail (E_IS_ADDRESSBOOK_VIEW (view), NULL); + + list = NULL; + selection = e_addressbook_view_get_selection_model (view); + e_selection_model_foreach (selection, add_to_list, &list); + + for (iter = list; iter != NULL; iter = iter->next) + iter->data = e_addressbook_model_get_contact ( + view->priv->model, GPOINTER_TO_INT (iter->data)); + list = g_list_reverse (list); + + return list; +} + ESelectionModel * e_addressbook_view_get_selection_model (EAddressbookView *view) { @@ -1011,7 +1086,7 @@ e_addressbook_view_print (EAddressbookView *view, query = NULL; g_free (query_string); - contact_list = get_selected_contacts (view); + contact_list = e_addressbook_view_get_selected (view); e_contact_print (book, query, contact_list, action); g_list_foreach (contact_list, (GFunc) g_object_unref, NULL); g_list_free (contact_list); @@ -1054,6 +1129,62 @@ delete_contacts_cb (EBook *book, EBookStatus status, gpointer closure) } } +static gboolean +addressbook_view_confirm_delete (GtkWindow *parent, + gboolean plural, + gboolean is_list, + const gchar *name) +{ + GtkWidget *dialog; + gchar *message; + gint response; + + if (is_list) { + if (plural) { + message = g_strdup ( + _("Are you sure you want to " + "delete these contact lists?")); + } else if (name == NULL) { + message = g_strdup ( + _("Are you sure you want to " + "delete this contact list?")); + } else { + message = g_strdup_printf ( + _("Are you sure you want to delete " + "this contact list (%s)?"), name); + } + } else { + if (plural) { + message = g_strdup ( + _("Are you sure you want to " + "delete these contacts?")); + } else if (name == NULL) { + message = g_strdup ( + _("Are you sure you want to " + "delete this contact?")); + } else { + message = g_strdup_printf ( + _("Are you sure you want to delete " + "this contact (%s)?"), name); + } + } + + dialog = gtk_message_dialog_new ( + parent, 0, GTK_MESSAGE_QUESTION, + GTK_BUTTONS_NONE, "%s", message); + gtk_dialog_add_buttons ( + GTK_DIALOG (dialog), + GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, + GTK_STOCK_DELETE, GTK_RESPONSE_ACCEPT, + NULL); + response = gtk_dialog_run (GTK_DIALOG (dialog)); + gtk_widget_destroy (dialog); + + g_free (message); + + return (response == GTK_RESPONSE_ACCEPT); +} + void e_addressbook_view_delete_selection(EAddressbookView *view, gboolean is_delete) { @@ -1076,7 +1207,7 @@ e_addressbook_view_delete_selection(EAddressbookView *view, gboolean is_delete) view_instance = e_addressbook_view_get_view_instance (view); gal_view = gal_view_instance_get_current_view (view_instance); - list = get_selected_contacts (view); + list = e_addressbook_view_get_selected (view); contact = list->data; if (g_list_next(list)) @@ -1100,9 +1231,9 @@ e_addressbook_view_delete_selection(EAddressbookView *view, gboolean is_delete) } /* confirm delete */ - if (is_delete && - !eab_editor_confirm_delete(GTK_WINDOW(gtk_widget_get_toplevel(view->priv->widget)), - plural, is_list, name)) { + if (is_delete && !addressbook_view_confirm_delete ( + GTK_WINDOW (gtk_widget_get_toplevel ( + view->priv->widget)), plural, is_list, name)) { g_free (name); g_list_foreach (list, (GFunc) g_object_unref, NULL); g_list_free (list); @@ -1168,30 +1299,6 @@ e_addressbook_view_delete_selection(EAddressbookView *view, gboolean is_delete) g_list_free (list); } -static void -add_to_list (int model_row, gpointer closure) -{ - GList **list = closure; - *list = g_list_prepend (*list, GINT_TO_POINTER (model_row)); -} - -static GList * -get_selected_contacts (EAddressbookView *view) -{ - GList *list; - GList *iterator; - ESelectionModel *selection = e_addressbook_view_get_selection_model (view); - - list = NULL; - e_selection_model_foreach (selection, add_to_list, &list); - - for (iterator = list; iterator; iterator = iterator->next) { - iterator->data = e_addressbook_model_get_contact (view->priv->model, GPOINTER_TO_INT (iterator->data)); - } - list = g_list_reverse (list); - return list; -} - void e_addressbook_view_save_as (EAddressbookView *view, gboolean all) @@ -1210,7 +1317,7 @@ e_addressbook_view_save_as (EAddressbookView *view, e_book_get_contacts (book, query, &list, NULL); e_book_query_unref (query); } else - list = get_selected_contacts (view); + list = e_addressbook_view_get_selected (view); if (list != NULL) { eab_contact_list_save (_("Save as vCard..."), list, NULL); @@ -1224,8 +1331,10 @@ e_addressbook_view_view (EAddressbookView *view) { EAddressbookModel *model; EBook *book; - GList *list; + GList *list, *iter; gboolean editable; + gint response; + guint length; g_return_if_fail (E_IS_ADDRESSBOOK_VIEW (view)); @@ -1233,42 +1342,36 @@ e_addressbook_view_view (EAddressbookView *view) book = e_addressbook_model_get_book (model); editable = e_addressbook_model_get_editable (model); - list = get_selected_contacts (view); - eab_show_multiple_contacts (book, list, editable); - g_list_foreach (list, (GFunc) g_object_unref, NULL); - g_list_free (list); -} - -void -e_addressbook_view_send (EAddressbookView *view) -{ - GList *list; - - g_return_if_fail (E_IS_ADDRESSBOOK_VIEW (view)); - - list = get_selected_contacts (view); - - if (list != NULL) { - eab_send_contact_list (list, EAB_DISPOSITION_AS_ATTACHMENT); - g_list_foreach (list, (GFunc) g_object_unref, NULL); - g_list_free (list); + list = e_addressbook_view_get_selected (view); + length = g_list_length (list); + response = GTK_RESPONSE_YES; + + if (length > 5) { + GtkWidget *dialog; + + /* XXX Use e_error_new(). */ + /* XXX Provide a parent window. */ + dialog = gtk_message_dialog_new ( + NULL, 0, GTK_MESSAGE_QUESTION, GTK_BUTTONS_NONE, + _("Opening %d contacts will open %d new windows as " + "well.\nDo you really want to display all of these " + "contacts?"), length, length); + gtk_dialog_add_buttons ( + GTK_DIALOG (dialog), + _("_Don't Display"), GTK_RESPONSE_NO, + _("Display _All Contacts"), GTK_RESPONSE_YES, + NULL); + response = gtk_dialog_run (GTK_DIALOG (dialog)); + gtk_widget_destroy (dialog); } -} - -void -e_addressbook_view_send_to (EAddressbookView *view) -{ - GList *list; - - g_return_if_fail (E_IS_ADDRESSBOOK_VIEW (view)); - list = get_selected_contacts (view); + if (response == GTK_RESPONSE_YES) + for (iter = list; iter != NULL; iter = iter->next) + addressbook_view_emit_open_contact ( + view, iter->data, FALSE); - if (list != NULL) { - eab_send_contact_list (list, EAB_DISPOSITION_AS_TO); - g_list_foreach (list, (GFunc) g_object_unref, NULL); - g_list_free (list); - } + g_list_foreach (list, (GFunc) g_object_unref, NULL); + g_list_free (list); } void @@ -1285,7 +1388,7 @@ e_addressbook_view_copy (EAddressbookView *view) { g_return_if_fail (E_IS_ADDRESSBOOK_VIEW (view)); - view->priv->clipboard_contacts = get_selected_contacts (view); + view->priv->clipboard_contacts = e_addressbook_view_get_selected (view); gtk_selection_owner_set ( view->priv->invisible, @@ -1346,7 +1449,7 @@ view_transfer_contacts (EAddressbookView *view, gboolean delete_from_source, gbo e_book_query_unref(query); } else { - contacts = get_selected_contacts (view); + contacts = e_addressbook_view_get_selected (view); } parent_window = GTK_WINDOW (gtk_widget_get_toplevel (GTK_WIDGET (view))); diff --git a/addressbook/gui/widgets/e-addressbook-view.h b/addressbook/gui/widgets/e-addressbook-view.h index 009222fd71..4e4e7c8178 100644 --- a/addressbook/gui/widgets/e-addressbook-view.h +++ b/addressbook/gui/widgets/e-addressbook-view.h @@ -25,6 +25,7 @@ #include <e-shell-view.h> #include <libebook/e-book.h> +#include <libebook/e-contact.h> #include <widgets/menus/gal-view-instance.h> #include <widgets/misc/e-selection-model.h> @@ -65,6 +66,9 @@ struct _EAddressbookViewClass { GtkVBoxClass parent_class; /* Signals */ + void (*open_contact) (EAddressbookView *view, + EContact *contact, + gboolean is_new_contact); void (*popup_event) (EAddressbookView *view, GdkEvent *event); void (*status_message) (EAddressbookView *view, @@ -85,6 +89,7 @@ GObject * e_addressbook_view_get_view_object (EAddressbookView *view); GtkWidget * e_addressbook_view_get_view_widget (EAddressbookView *view); +GList * e_addressbook_view_get_selected (EAddressbookView *view); ESelectionModel * e_addressbook_view_get_selection_model (EAddressbookView *view); @@ -94,8 +99,6 @@ ESource * e_addressbook_view_get_source (EAddressbookView *view); void e_addressbook_view_save_as (EAddressbookView *view, gboolean all); void e_addressbook_view_view (EAddressbookView *view); -void e_addressbook_view_send (EAddressbookView *view); -void e_addressbook_view_send_to (EAddressbookView *view); void e_addressbook_view_print (EAddressbookView *view, GtkPrintOperationAction action); void e_addressbook_view_delete_selection diff --git a/addressbook/gui/widgets/e-minicard-view-widget.c b/addressbook/gui/widgets/e-minicard-view-widget.c index 0f9ae7c143..3ad49cf2b3 100644 --- a/addressbook/gui/widgets/e-minicard-view-widget.c +++ b/addressbook/gui/widgets/e-minicard-view-widget.c @@ -53,6 +53,8 @@ enum { }; enum { + CREATE_CONTACT, + CREATE_CONTACT_LIST, SELECTION_CHANGE, COLUMN_WIDTH_CHANGED, RIGHT_CLICK, @@ -140,6 +142,24 @@ e_minicard_view_widget_class_init (EMinicardViewWidgetClass *class) 0.0, G_MAXDOUBLE, 150.0, G_PARAM_READWRITE)); + signals [CREATE_CONTACT] = + g_signal_new ("create-contact", + G_OBJECT_CLASS_TYPE (object_class), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (EMinicardViewWidgetClass, create_contact), + NULL, NULL, + g_cclosure_marshal_VOID__VOID, + G_TYPE_NONE, 0); + + signals [CREATE_CONTACT_LIST] = + g_signal_new ("create-contact-list", + G_OBJECT_CLASS_TYPE (object_class), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (EMinicardViewWidgetClass, create_contact_list), + NULL, NULL, + g_cclosure_marshal_VOID__VOID, + G_TYPE_NONE, 0); + signals [SELECTION_CHANGE] = g_signal_new ("selection_change", G_OBJECT_CLASS_TYPE (object_class), @@ -315,6 +335,18 @@ column_width_changed (ESelectionModel *esm, double width, EMinicardViewWidget *w signals [COLUMN_WIDTH_CHANGED], 0, width); } +static void +create_contact (EMinicardView *view, EMinicardViewWidget *widget) +{ + g_signal_emit (widget, signals[CREATE_CONTACT], 0); +} + +static void +create_contact_list (EMinicardView *view, EMinicardViewWidget *widget) +{ + g_signal_emit (widget, signals[CREATE_CONTACT_LIST], 0); +} + static guint right_click (EMinicardView *view, GdkEvent *event, EMinicardViewWidget *widget) { @@ -370,6 +402,12 @@ e_minicard_view_widget_realize (GtkWidget *widget) "column_width_changed", G_CALLBACK (column_width_changed), view); g_signal_connect (view->emv, + "create-contact", + G_CALLBACK (create_contact), view); + g_signal_connect (view->emv, + "create-contact-list", + G_CALLBACK (create_contact_list), view); + g_signal_connect (view->emv, "right_click", G_CALLBACK (right_click), view); diff --git a/addressbook/gui/widgets/e-minicard-view-widget.h b/addressbook/gui/widgets/e-minicard-view-widget.h index 1c4323523f..917d1b588a 100644 --- a/addressbook/gui/widgets/e-minicard-view-widget.h +++ b/addressbook/gui/widgets/e-minicard-view-widget.h @@ -58,6 +58,8 @@ struct _EMinicardViewWidget struct _EMinicardViewWidgetClass { ECanvasClass parent_class; + void (*create_contact) (EMinicardViewWidget *emvw); + void (*create_contact_list) (EMinicardViewWidget *emvw); void (*selection_change) (EMinicardViewWidget *emvw); void (*column_width_changed) (EMinicardViewWidget *emvw, double width); guint (*right_click) (EMinicardViewWidget *emvw); diff --git a/addressbook/gui/widgets/e-minicard-view.c b/addressbook/gui/widgets/e-minicard-view.c index 37ffc8844d..cca2a54a3c 100644 --- a/addressbook/gui/widgets/e-minicard-view.c +++ b/addressbook/gui/widgets/e-minicard-view.c @@ -56,6 +56,8 @@ enum { enum { + CREATE_CONTACT, + CREATE_CONTACT_LIST, RIGHT_CLICK, LAST_SIGNAL }; @@ -383,13 +385,8 @@ e_minicard_view_event (GnomeCanvasItem *item, GdkEvent *event) g_object_get(view->adapter, "editable", &editable, NULL); - if (editable) { - EBook *book; - g_object_get(view, "book", &book, NULL); - - if (book && E_IS_BOOK (book)) - eab_show_contact_editor (book, e_contact_new(), TRUE, editable); - } + if (editable) + e_minicard_view_create_contact (view); return TRUE; } case GDK_BUTTON_PRESS: @@ -547,6 +544,22 @@ e_minicard_view_class_init (EMinicardViewClass *klass) FALSE, G_PARAM_READWRITE)); + signals [CREATE_CONTACT] = + g_signal_new ("create-contact", + G_OBJECT_CLASS_TYPE (object_class), + G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION, + 0, NULL, NULL, + g_cclosure_marshal_VOID__VOID, + G_TYPE_NONE, 0); + + signals [CREATE_CONTACT_LIST] = + g_signal_new ("create-contact-list", + G_OBJECT_CLASS_TYPE (object_class), + G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION, + 0, NULL, NULL, + g_cclosure_marshal_VOID__VOID, + G_TYPE_NONE, 0); + signals [RIGHT_CLICK] = g_signal_new ("right_click", G_OBJECT_CLASS_TYPE (object_class), @@ -655,3 +668,19 @@ e_minicard_view_get_card_list (EMinicardView *view) mal.list = g_list_reverse (mal.list); return mal.list; } + +void +e_minicard_view_create_contact (EMinicardView *view) +{ + g_return_if_fail (E_IS_MINICARD_VIEW (view)); + + g_signal_emit (view, signals[CREATE_CONTACT], 0); +} + +void +e_minicard_view_create_contact_list (EMinicardView *view) +{ + g_return_if_fail (E_IS_MINICARD_VIEW (view)); + + g_signal_emit (view, signals[CREATE_CONTACT_LIST], 0); +} diff --git a/addressbook/gui/widgets/e-minicard-view.h b/addressbook/gui/widgets/e-minicard-view.h index 7d0a5b1842..4cdf9be7be 100644 --- a/addressbook/gui/widgets/e-minicard-view.h +++ b/addressbook/gui/widgets/e-minicard-view.h @@ -91,6 +91,8 @@ void e_minicard_view_remove_selection (EMinicardView *view, void e_minicard_view_jump_to_letter (EMinicardView *view, gunichar letter); GList *e_minicard_view_get_card_list (EMinicardView *view); +void e_minicard_view_create_contact (EMinicardView *view); +void e_minicard_view_create_contact_list (EMinicardView *view); G_END_DECLS diff --git a/addressbook/gui/widgets/e-minicard.c b/addressbook/gui/widgets/e-minicard.c index cbbcc80d5c..3e5e8ec3bf 100644 --- a/addressbook/gui/widgets/e-minicard.c +++ b/addressbook/gui/widgets/e-minicard.c @@ -35,7 +35,6 @@ #include "e-minicard.h" #include "e-minicard-label.h" #include "e-minicard-view.h" -#include "e-contact-editor.h" #include <e-util/e-html-utils.h> #include <e-util/e-icon-factory.h> #include <libebook/e-destination.h> @@ -86,6 +85,7 @@ enum { enum { SELECTED, DRAG_BEGIN, + OPEN_CONTACT, STYLE_SET, LAST_SIGNAL }; @@ -101,7 +101,7 @@ common_location [] = { "OTHER", N_ ("Other Email") } }; -static guint e_minicard_signals [LAST_SIGNAL] = {0, }; +static guint signals [LAST_SIGNAL] = {0, }; GType e_minicard_get_type (void) @@ -200,7 +200,7 @@ e_minicard_class_init (EMinicardClass *class) E_TYPE_CONTACT, G_PARAM_READWRITE)); - e_minicard_signals [SELECTED] = + signals [SELECTED] = g_signal_new ("selected", G_OBJECT_CLASS_TYPE (object_class), G_SIGNAL_RUN_LAST, @@ -209,7 +209,7 @@ e_minicard_class_init (EMinicardClass *class) e_marshal_INT__POINTER, G_TYPE_INT, 1, G_TYPE_POINTER); - e_minicard_signals [DRAG_BEGIN] = + signals [DRAG_BEGIN] = g_signal_new ("drag_begin", G_OBJECT_CLASS_TYPE (object_class), G_SIGNAL_RUN_LAST, @@ -218,7 +218,17 @@ e_minicard_class_init (EMinicardClass *class) e_marshal_INT__POINTER, G_TYPE_INT, 1, G_TYPE_POINTER); - e_minicard_signals [STYLE_SET] = + signals [OPEN_CONTACT] = + g_signal_new ("open-contact", + G_OBJECT_CLASS_TYPE (object_class), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (EMinicardClass, open_contact), + NULL, NULL, + g_cclosure_marshal_VOID__OBJECT, + G_TYPE_NONE, 1, + E_TYPE_CONTACT); + + signals [STYLE_SET] = g_signal_new ("style_set", G_TYPE_FROM_CLASS (object_class), G_SIGNAL_RUN_FIRST, @@ -249,8 +259,6 @@ e_minicard_init (EMinicard *minicard) minicard->list_icon_pixbuf = e_icon_factory_get_icon (LIST_ICON_NAME, E_ICON_SIZE_MENU); minicard->list_icon_size = gdk_pixbuf_get_height (minicard->list_icon_pixbuf); - minicard->editor = NULL; - minicard->changed = FALSE; e_canvas_item_set_reflow_callback(GNOME_CANVAS_ITEM(minicard), e_minicard_reflow); @@ -528,50 +536,12 @@ e_minicard_unrealize (GnomeCanvasItem *item) (* GNOME_CANVAS_ITEM_CLASS(parent_class)->unrealize) (item); } -/* Callback used when the contact editor is closed */ -static void -editor_closed_cb (GtkObject *editor, gpointer data) -{ - EMinicard *minicard = data; - g_object_unref (editor); - minicard->editor = NULL; -} - -gboolean -e_minicard_activate_editor(EMinicard *minicard) +void +e_minicard_activate_editor (EMinicard *minicard) { - GnomeCanvasItem *item = (GnomeCanvasItem *)minicard; - - if (minicard->editor) { - eab_editor_raise (minicard->editor); - } - else { - EBook *book = NULL; - if (E_IS_MINICARD_VIEW(item->parent)) { - g_object_get(item->parent, "book", &book, NULL); - } - - if (book != NULL) { - if (e_contact_get (minicard->contact, E_CONTACT_IS_LIST)) { - EContactListEditor *editor = eab_show_contact_list_editor (book, minicard->contact, - FALSE, e_book_is_writable (book)); - minicard->editor = EAB_EDITOR (editor); - } - else { - EContactEditor *editor = eab_show_contact_editor (book, minicard->contact, - FALSE, e_book_is_writable (book)); - minicard->editor = EAB_EDITOR (editor); - } - - g_object_ref (minicard->editor); - g_signal_connect (minicard->editor, "editor_closed", - G_CALLBACK (editor_closed_cb), minicard); - - g_object_unref (book); - } - } + g_return_if_fail (E_IS_MINICARD (minicard)); - return TRUE; + g_signal_emit (minicard, signals[OPEN_CONTACT], 0, minicard->contact); } static gboolean @@ -655,7 +625,8 @@ e_minicard_event (GnomeCanvasItem *item, GdkEvent *event) break; case GDK_2BUTTON_PRESS: if (event->button.button == 1 && E_IS_MINICARD_VIEW (item->parent)) { - return e_minicard_activate_editor (e_minicard); + e_minicard_activate_editor (e_minicard); + return TRUE; } break; case GDK_KEY_PRESS: @@ -725,7 +696,8 @@ e_minicard_event (GnomeCanvasItem *item, GdkEvent *event) } else if (event->key.keyval == GDK_Return || event->key.keyval == GDK_KP_Enter) { - return e_minicard_activate_editor (e_minicard); + e_minicard_activate_editor (e_minicard); + return TRUE; } break; default: @@ -1154,7 +1126,7 @@ e_minicard_drag_begin (EMinicard *minicard, GdkEvent *event) gint ret_val = 0; GnomeCanvasItem *parent; g_signal_emit (minicard, - e_minicard_signals[DRAG_BEGIN], 0, + signals[DRAG_BEGIN], 0, event, &ret_val); parent = GNOME_CANVAS_ITEM (minicard)->parent; diff --git a/addressbook/gui/widgets/e-minicard.h b/addressbook/gui/widgets/e-minicard.h index 71c976745f..98a4629ad9 100644 --- a/addressbook/gui/widgets/e-minicard.h +++ b/addressbook/gui/widgets/e-minicard.h @@ -24,7 +24,6 @@ #define __E_MINICARD_H__ #include <gtk/gtk.h> -#include "addressbook/gui/contact-editor/eab-editor.h" #include <libgnomecanvas/gnome-canvas.h> #include <libebook/e-contact.h> @@ -75,8 +74,6 @@ struct _EMinicard GdkPixbuf *list_icon_pixbuf; double list_icon_size; - EABEditor *editor; - GList *fields; /* Of type EMinicardField */ guint needs_remodeling : 1; @@ -105,6 +102,7 @@ struct _EMinicardClass gint (* selected) (EMinicard *minicard, GdkEvent *event); gint (* drag_begin) (EMinicard *minicard, GdkEvent *event); + void (* open_contact) (EMinicard *minicard, EContact *contact); void (* style_set) (EMinicard *minicard, GtkStyle *previous_style); }; @@ -125,7 +123,7 @@ int e_minicard_compare (EMinicard *minicard1, int e_minicard_selected (EMinicard *minicard, GdkEvent *event); -gboolean e_minicard_activate_editor (EMinicard *minicard); +void e_minicard_activate_editor (EMinicard *minicard); #ifdef __cplusplus } diff --git a/addressbook/gui/widgets/eab-contact-display.c b/addressbook/gui/widgets/eab-contact-display.c index 1cbe322a96..1d22f3ea70 100644 --- a/addressbook/gui/widgets/eab-contact-display.c +++ b/addressbook/gui/widgets/eab-contact-display.c @@ -62,6 +62,11 @@ enum { PROP_MODE }; +enum { + SEND_MESSAGE, + LAST_SIGNAL +}; + static struct { gchar *name; gchar *pretty_name; @@ -101,6 +106,7 @@ static const gchar *ui = "</ui>"; static gpointer parent_class; +static guint signals[LAST_SIGNAL]; static void action_copy_address_cb (GtkAction *action, @@ -169,6 +175,7 @@ static void action_send_message_cb (GtkAction *action, EABContactDisplay *display) { + EDestination *destination; EContact *contact; const gchar *uri; gint row; @@ -177,8 +184,11 @@ action_send_message_cb (GtkAction *action, row = atoi (uri + strlen ("internal-mailto:")); g_return_if_fail (row >= 0); + destination = e_destination_new (); contact = eab_contact_display_get_contact (display); - eab_send_contact (contact, row, EAB_DISPOSITION_AS_TO); + e_destination_set_contact (destination, contact, row); + g_signal_emit (display, signals[SEND_MESSAGE], 0, destination); + g_object_unref (destination); } static GtkActionEntry email_entries[] = { @@ -283,12 +293,19 @@ contact_display_on_link_clicked (GtkHTML *html, #ifdef HANDLE_MAILTO_INTERNALLY if (!strncmp (url, "internal-mailto:", strlen ("internal-mailto:"))) { - int mail_num = atoi (url + strlen ("internal-mailto:")); + EDestination *destination; + EContact *contact; + gint email_num; - if (mail_num == -1) + email_num = atoi (url + strlen ("internal-mailto:")); + if (email_num == -1) return; - eab_send_contact (display->priv->contact, mail_num, EAB_DISPOSITION_AS_TO); + destination = e_destination_new (); + contact = eab_contact_display_get_contact (display); + e_destination_set_contact (destination, contact, email_num); + g_signal_emit (display, signals[SEND_MESSAGE], 0, destination); + g_object_unref (destination); return; } @@ -1067,6 +1084,16 @@ eab_contact_display_class_init (EABContactDisplayClass *class) EAB_CONTACT_DISPLAY_RENDER_COMPACT, EAB_CONTACT_DISPLAY_RENDER_NORMAL, G_PARAM_READWRITE)); + + signals[SEND_MESSAGE] = g_signal_new ( + "send-message", + G_OBJECT_CLASS_TYPE (class), + G_SIGNAL_RUN_FIRST, + G_STRUCT_OFFSET (EABContactDisplayClass, send_message), + NULL, NULL, + g_cclosure_marshal_VOID__OBJECT, + G_TYPE_NONE, 1, + E_TYPE_DESTINATION); } static void diff --git a/addressbook/gui/widgets/eab-contact-display.h b/addressbook/gui/widgets/eab-contact-display.h index 803a23d79f..096a910f2f 100644 --- a/addressbook/gui/widgets/eab-contact-display.h +++ b/addressbook/gui/widgets/eab-contact-display.h @@ -25,6 +25,7 @@ #include <gtkhtml/gtkhtml.h> #include <libebook/e-contact.h> +#include <libebook/e-destination.h> /* Standard GObject macros */ #define EAB_TYPE_CONTACT_DISPLAY \ @@ -63,6 +64,10 @@ struct _EABContactDisplay { struct _EABContactDisplayClass { GtkHTMLClass parent_class; + + /* Signals */ + void (*send_message) (EABContactDisplay *display, + EDestination *destination); }; GType eab_contact_display_get_type (void); diff --git a/addressbook/gui/widgets/eab-gui-util.c b/addressbook/gui/widgets/eab-gui-util.c index 3ba848ecc8..d3c0910827 100644 --- a/addressbook/gui/widgets/eab-gui-util.c +++ b/addressbook/gui/widgets/eab-gui-util.c @@ -40,16 +40,11 @@ #include "misc/e-image-chooser.h" #include <e-util/e-icon-factory.h> #include "eab-contact-merging.h" -#include <composer/e-msg-composer.h> -#include <mail/em-composer-utils.h> /* we link to camel for decoding quoted printable email addresses */ #include <camel/camel-mime-utils.h> -#include "addressbook/gui/contact-editor/eab-editor.h" -#include "addressbook/gui/contact-editor/e-contact-editor.h" -#include "addressbook/gui/contact-list-editor/e-contact-list-editor.h" -#include "addressbook/gui/component/addressbook.h" +#include "addressbook/util/addressbook.h" /* the NULL's in this table correspond to the status codes that should *never* be generated by a backend */ @@ -201,140 +196,6 @@ eab_prompt_save_dialog (GtkWindow *parent) return e_error_run (parent, "addressbook:prompt-save", NULL); } -static void -added_cb (EBook* book, EBookStatus status, EContact *contact, - gpointer data) -{ - gboolean is_list = GPOINTER_TO_INT (data); - - if (status != E_BOOK_ERROR_OK && status != E_BOOK_ERROR_CANCELLED) { - eab_error_dialog (is_list ? _("Error adding list") : _("Error adding contact"), status); - } -} - -static void -modified_cb (EBook* book, EBookStatus status, EContact *contact, - gpointer data) -{ - gboolean is_list = GPOINTER_TO_INT (data); - - if (status != E_BOOK_ERROR_OK && status != E_BOOK_ERROR_CANCELLED) { - eab_error_dialog (is_list ? _("Error modifying list") : _("Error modifying contact"), - status); - } -} - -static void -deleted_cb (EBook* book, EBookStatus status, EContact *contact, - gpointer data) -{ - gboolean is_list = GPOINTER_TO_INT (data); - - if (status != E_BOOK_ERROR_OK) { - eab_error_dialog (is_list ? _("Error removing list") : _("Error removing contact"), - status); - } -} - -static void -editor_closed_cb (GtkObject *editor, gpointer data) -{ - g_object_unref (editor); -} - -EContactEditor * -eab_show_contact_editor (EBook *book, EContact *contact, - gboolean is_new_contact, - gboolean editable) -{ - EContactEditor *ce; - - ce = e_contact_editor_new (book, contact, is_new_contact, editable); - - g_signal_connect (ce, "contact_added", - G_CALLBACK (added_cb), GINT_TO_POINTER (FALSE)); - g_signal_connect (ce, "contact_modified", - G_CALLBACK (modified_cb), GINT_TO_POINTER (FALSE)); - g_signal_connect (ce, "contact_deleted", - G_CALLBACK (deleted_cb), GINT_TO_POINTER (FALSE)); - g_signal_connect (ce, "editor_closed", - G_CALLBACK (editor_closed_cb), NULL); - - return ce; -} - -EContactListEditor * -eab_show_contact_list_editor (EBook *book, EContact *contact, - gboolean is_new_contact, - gboolean editable) -{ - EContactListEditor *ce; - - ce = e_contact_list_editor_new (book, contact, is_new_contact, editable); - - g_signal_connect (ce, "contact_added", - G_CALLBACK (added_cb), GINT_TO_POINTER (TRUE)); - g_signal_connect (ce, "contact_modified", - G_CALLBACK (modified_cb), GINT_TO_POINTER (TRUE)); - g_signal_connect (ce, "contact_deleted", - G_CALLBACK (deleted_cb), GINT_TO_POINTER (TRUE)); - g_signal_connect (ce, "editor_closed", - G_CALLBACK (editor_closed_cb), GINT_TO_POINTER (TRUE)); - - eab_editor_show (EAB_EDITOR (ce)); - - return ce; -} - -static void -view_contacts (EBook *book, GList *list, gboolean editable) -{ - for (; list; list = list->next) { - EContact *contact = list->data; - if (e_contact_get (contact, E_CONTACT_IS_LIST)) - eab_show_contact_list_editor (book, contact, FALSE, editable); - else - eab_show_contact_editor (book, contact, FALSE, editable); - } -} - -void -eab_show_multiple_contacts (EBook *book, - GList *list, - gboolean editable) -{ - if (list) { - int length = g_list_length (list); - if (length > 5) { - GtkWidget *dialog; - gint response; - - dialog = gtk_message_dialog_new (NULL, - 0, - GTK_MESSAGE_QUESTION, - GTK_BUTTONS_NONE, - ngettext("Opening %d contact will open %d new window as well.\n" - "Do you really want to display this contact?", - "Opening %d contacts will open %d new windows as well.\n" - "Do you really want to display all of these contacts?", - length), - length, - length); - gtk_dialog_add_buttons (GTK_DIALOG (dialog), - _("_Don't Display"), GTK_RESPONSE_NO, - _("Display _All Contacts"), GTK_RESPONSE_YES, - NULL); - response = gtk_dialog_run (GTK_DIALOG (dialog)); - gtk_widget_destroy (dialog); - if (response == GTK_RESPONSE_YES) - view_contacts (book, list, editable); - } else { - view_contacts (book, list, editable); - } - } -} - - static gint file_exists(GtkWindow *window, const char *filename) { @@ -773,232 +634,6 @@ eab_transfer_contacts (EBook *source, GList *contacts /* adopted */, gboolean de addressbook_load (dest, got_book_cb, process); } -typedef struct { - EContact *contact; - int email_num; /* if the contact is a person (not a list), the email address to use */ -} ContactAndEmailNum; - -static void -eab_send_to_contact_and_email_num_list (GList *contact_list) -{ - EMsgComposer *composer; - EComposerHeaderTable *table; - GPtrArray *to_array; - GPtrArray *bcc_array; - - union { - gpointer *pdata; - EDestination **destinations; - } convert; - - if (contact_list == NULL) - return; - - composer = e_msg_composer_new (); - table = e_msg_composer_get_header_table (composer); - em_composer_utils_setup_default_callbacks (composer); - - to_array = g_ptr_array_new (); - bcc_array = g_ptr_array_new (); - - /* Sort contacts into "To" and "Bcc" destinations. */ - while (contact_list != NULL) { - ContactAndEmailNum *ce = contact_list->data; - EContact *contact = ce->contact; - EDestination *destination; - - destination = e_destination_new (); - e_destination_set_contact (destination, contact, 0); - - if (e_destination_is_evolution_list (destination)) { - if (e_destination_list_show_addresses (destination)) - g_ptr_array_add (to_array, destination); - else - g_ptr_array_add (bcc_array, destination); - } else - g_ptr_array_add (to_array, destination); - - contact_list = g_list_next (contact_list); - } - - /* Add sentinels to each array. */ - g_ptr_array_add (to_array, NULL); - g_ptr_array_add (bcc_array, NULL); - - /* XXX Acrobatics like this make me question whether NULL-terminated - * arrays are really the best argument type for passing a list of - * destinations to the header table. */ - - /* Add "To" destinations. */ - convert.pdata = to_array->pdata; - e_composer_header_table_set_destinations_to ( - table, convert.destinations); - g_ptr_array_free (to_array, FALSE); - e_destination_freev (convert.destinations); - - /* Add "Bcc" destinations. */ - convert.pdata = bcc_array->pdata; - e_composer_header_table_set_destinations_bcc ( - table, convert.destinations); - g_ptr_array_free (bcc_array, FALSE); - e_destination_freev (convert.destinations); - - gtk_widget_show (GTK_WIDGET (composer)); -} - -static const char * -get_email (EContact *contact, EContactField field_id, gchar **to_free) -{ - char *name = NULL, *mail = NULL; - const char *value = e_contact_get_const (contact, field_id); - - *to_free = NULL; - - if (eab_parse_qp_email (value, &name, &mail)) { - *to_free = g_strdup_printf ("%s <%s>", name, mail); - value = *to_free; - } - - g_free (name); - g_free (mail); - - return value; -} - -static void -eab_send_contact_list_as_attachment (GList *contacts) -{ - EMsgComposer *composer; - EComposerHeaderTable *table; - CamelMimePart *attachment; - gchar *data; - - if (contacts == NULL) - return; - - composer = e_msg_composer_new (); - table = e_msg_composer_get_header_table (composer); - em_composer_utils_setup_default_callbacks (composer); - - attachment = camel_mime_part_new (); - data = eab_contact_list_to_string (contacts); - - camel_mime_part_set_content ( - attachment, data, strlen (data), "text/x-vcard"); - - if (contacts->next != NULL) - camel_mime_part_set_description ( - attachment, _("Multiple vCards")); - else { - EContact *contact = contacts->data; - const gchar *file_as; - gchar *description; - - file_as = e_contact_get_const (contact, E_CONTACT_FILE_AS); - description = g_strdup_printf (_("vCard for %s"), file_as); - camel_mime_part_set_description (attachment, description); - g_free (description); - } - - camel_mime_part_set_disposition (attachment, "attachment"); - - e_msg_composer_attach (composer, attachment); - camel_object_unref (attachment); - - if (contacts->next != NULL) - e_composer_header_table_set_subject ( - table, _("Contact information")); - else { - EContact *contact = contacts->data; - gchar *tempstr; - const gchar *tempstr2; - gchar *tempfree = NULL; - - tempstr2 = e_contact_get_const (contact, E_CONTACT_FILE_AS); - if (!tempstr2 || !*tempstr2) - tempstr2 = e_contact_get_const (contact, E_CONTACT_FULL_NAME); - if (!tempstr2 || !*tempstr2) - tempstr2 = e_contact_get_const (contact, E_CONTACT_ORG); - if (!tempstr2 || !*tempstr2) { - g_free (tempfree); - tempstr2 = get_email (contact, E_CONTACT_EMAIL_1, &tempfree); - } - if (!tempstr2 || !*tempstr2) { - g_free (tempfree); - tempstr2 = get_email (contact, E_CONTACT_EMAIL_2, &tempfree); - } - if (!tempstr2 || !*tempstr2) { - g_free (tempfree); - tempstr2 = get_email (contact, E_CONTACT_EMAIL_3, &tempfree); - } - - if (!tempstr2 || !*tempstr2) - tempstr = g_strdup_printf (_("Contact information")); - else - tempstr = g_strdup_printf (_("Contact information for %s"), tempstr2); - - e_composer_header_table_set_subject (table, tempstr); - - g_free (tempstr); - g_free (tempfree); - } - - gtk_widget_show (GTK_WIDGET (composer)); -} - -void -eab_send_contact_list (GList *contacts, EABDisposition disposition) -{ - switch (disposition) { - case EAB_DISPOSITION_AS_TO: { - GList *list = NULL, *l; - - for (l = contacts; l; l = l->next) { - ContactAndEmailNum *ce = g_new (ContactAndEmailNum, 1); - ce->contact = l->data; - ce->email_num = 0; /* hardcode this */ - - list = g_list_append (list, ce); - } - - eab_send_to_contact_and_email_num_list (list); - - g_list_foreach (list, (GFunc)g_free, NULL); - g_list_free (list); - break; - } - case EAB_DISPOSITION_AS_ATTACHMENT: - eab_send_contact_list_as_attachment (contacts); - break; - } -} - -void -eab_send_contact (EContact *contact, int email_num, EABDisposition disposition) -{ - GList *list = NULL; - - switch (disposition) { - case EAB_DISPOSITION_AS_TO: { - ContactAndEmailNum ce; - - ce.contact = contact; - ce.email_num = email_num; - - list = g_list_prepend (NULL, &ce); - eab_send_to_contact_and_email_num_list (list); - break; - } - case EAB_DISPOSITION_AS_ATTACHMENT: { - list = g_list_prepend (NULL, contact); - eab_send_contact_list_as_attachment (list); - break; - } - } - - g_list_free (list); -} - GtkWidget * eab_create_image_chooser_widget(gchar *name, gchar *string1, gchar *string2, diff --git a/addressbook/gui/widgets/eab-gui-util.h b/addressbook/gui/widgets/eab-gui-util.h index 79dbe5493a..8d878cff14 100644 --- a/addressbook/gui/widgets/eab-gui-util.h +++ b/addressbook/gui/widgets/eab-gui-util.h @@ -26,8 +26,6 @@ #include <gtk/gtk.h> #include <libebook/e-book.h> -#include "addressbook/gui/contact-editor/e-contact-editor.h" -#include "addressbook/gui/contact-list-editor/e-contact-list-editor.h" G_BEGIN_DECLS @@ -40,17 +38,6 @@ void eab_search_result_dialog (GtkWidget *parent, EBookViewStatus status); gint eab_prompt_save_dialog (GtkWindow *parent); -EContactEditor *eab_show_contact_editor (EBook *book, - EContact *contact, - gboolean is_new_contact, - gboolean editable); -EContactListEditor *eab_show_contact_list_editor (EBook *book, - EContact *contact, - gboolean is_new_contact, - gboolean editable); -void eab_show_multiple_contacts (EBook *book, - GList *list, - gboolean editable); void eab_transfer_contacts (EBook *source, GList *contacts, /* adopted */ gboolean delete_from_source, @@ -64,26 +51,17 @@ void eab_contact_list_save (char *title, GList *list, GtkWindow *parent_window); -typedef enum { - EAB_DISPOSITION_AS_ATTACHMENT, - EAB_DISPOSITION_AS_TO, -} EABDisposition; - -void eab_send_contact (EContact *contact, - int email_num, - EABDisposition disposition); -void eab_send_contact_list (GList *contacts, - EABDisposition disposition); - GtkWidget *eab_create_image_chooser_widget (gchar *name, gchar *string1, gchar *string2, gint int1, gint int2); ESource *eab_select_source (const gchar *title, const gchar *message, const gchar *select_uid, GtkWindow *parent); -/* To parse quoted printable address & return email & name fields */ -gboolean eab_parse_qp_email (const gchar *string, gchar **name, gchar **email); -char *eab_parse_qp_email_to_html (const gchar *string); +/* To parse quoted printable address & return email & name fields */ +gboolean eab_parse_qp_email (const gchar *string, + gchar **name, + gchar **email); +gchar * eab_parse_qp_email_to_html (const gchar *string); G_END_DECLS |