diff options
-rw-r--r-- | ChangeLog | 4 | ||||
-rw-r--r-- | addressbook/gui/component/autocompletion-config.c | 1 | ||||
-rw-r--r-- | configure.in | 3 | ||||
-rw-r--r-- | plugins/bbdb/.cvsignore | 3 | ||||
-rw-r--r-- | plugins/bbdb/ChangeLog | 4 | ||||
-rw-r--r-- | plugins/bbdb/Makefile.am | 12 | ||||
-rw-r--r-- | plugins/bbdb/bbdb.c | 328 | ||||
-rw-r--r-- | plugins/bbdb/org-gnome-evolution-bbdb.eplug.in | 20 |
8 files changed, 374 insertions, 1 deletions
@@ -1,3 +1,7 @@ +2004-10-22 Nat Friedman <nat@novell.com> + + * configure.in: Added the bbdb plugin. + 2004-10-21 Rodrigo Moya <rodrigo@novell.com> * configure.in: added save-calendar plugin. diff --git a/addressbook/gui/component/autocompletion-config.c b/addressbook/gui/component/autocompletion-config.c index 8161c71166..0324ad838e 100644 --- a/addressbook/gui/component/autocompletion-config.c +++ b/addressbook/gui/component/autocompletion-config.c @@ -124,6 +124,7 @@ autocompletion_config_control_new (void) /* g_signal_connect (ac->source_list, "changed", G_CALLBACK (source_list_changed), ac); */ scrolledwin = gtk_scrolled_window_new (NULL, NULL); + gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolledwin), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC); diff --git a/configure.in b/configure.in index c6576f70f1..134eb9f9aa 100644 --- a/configure.in +++ b/configure.in @@ -1341,7 +1341,7 @@ AC_SUBST_FILE(EVO_PLUGIN_RULE) AC_ARG_ENABLE(plugins, [ --enable-plugins=[no/all/list] Enable plugins.],enable_plugins="$enableval",enable_plugins=no) dnl Add any new plugins here -plugins_all="subject-thread save-attachments prefer-plain save-calendar select-one-source copy-tool mail-to-task" +plugins_all="subject-thread save-attachments prefer-plain save-calendar select-one-source copy-tool mail-to-task bbdb" if test x"$enable_plugins" = "xno"; then plugins_enabled="" @@ -1539,6 +1539,7 @@ plugins/save-attachments/Makefile plugins/save-calendar/Makefile plugins/select-one-source/Makefile plugins/prefer-plain/Makefile +plugins/bbdb/Makefile plugins/copy-tool/Makefile smime/Makefile smime/lib/Makefile diff --git a/plugins/bbdb/.cvsignore b/plugins/bbdb/.cvsignore new file mode 100644 index 0000000000..0c59e48770 --- /dev/null +++ b/plugins/bbdb/.cvsignore @@ -0,0 +1,3 @@ +Makefile.in +Makefile +org-gnome-evolution-bbdb.eplug diff --git a/plugins/bbdb/ChangeLog b/plugins/bbdb/ChangeLog new file mode 100644 index 0000000000..4f0f84b82d --- /dev/null +++ b/plugins/bbdb/ChangeLog @@ -0,0 +1,4 @@ +2004-10-22 Nat Friedman <nat@novell.com> + + * Initial checkin. + diff --git a/plugins/bbdb/Makefile.am b/plugins/bbdb/Makefile.am new file mode 100644 index 0000000000..140cc9e2fc --- /dev/null +++ b/plugins/bbdb/Makefile.am @@ -0,0 +1,12 @@ +INCLUDES = \ + -I$(top_srcdir) \ + $(EVOLUTION_MAIL_CFLAGS) \ + $(EVOLUTION_ADDRESSBOOK_CFLAGS) + +@EVO_PLUGIN_RULE@ + +plugin_DATA = org-gnome-evolution-bbdb.eplug +plugin_LTLIBRARIES = liborg-gnome-evolution-bbdb.la + +liborg_gnome_evolution_bbdb_la_SOURCES = bbdb.c +liborg_gnome_evolution_bbdb_la_LDFLAGS = -module -avoid-version diff --git a/plugins/bbdb/bbdb.c b/plugins/bbdb/bbdb.c new file mode 100644 index 0000000000..87d728c231 --- /dev/null +++ b/plugins/bbdb/bbdb.c @@ -0,0 +1,328 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- + * + * An Evolution EPlugin that automatically populates your addressbook + * as you reply to messages. Inspired by an Emacs contact management + * tool called The Insidious Big Brother Database, a jwz joint. + * + * Nat Friedman + * 22 October 2004 + * Boston + * + * Copyright (C) 2004 Novell, Inc. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include <gtk/gtk.h> +#include <libgnome/gnome-i18n.h> +#include <string.h> + +#include <libebook/e-book.h> +#include <libedataserverui/e-source-option-menu.h> + +#include <e-util/e-config.h> +#include <mail/em-config.h> +#include <mail/em-event.h> +#include <camel/camel-mime-message.h> + +/* Where to store the config values */ +#define GCONF_KEY_ENABLE "/apps/evolution/mail/autopopulate_addressbook" +#define GCONF_KEY_WHICH_ADDRESSBOOK "/apps/evolution/mail/autopopulate_source" + +/* Plugin hooks */ +void bbdb_handle_reply (EPlugin *ep, EMEventTargetMessage *target); +GtkWidget *bbdb_page_factory (EPlugin *ep, EConfigHookItemFactoryData *hook_data); +GtkWidget *bbdb_page_factory (EPlugin *ep, EConfigHookItemFactoryData *hook_data); + +/* For internal use */ +struct bbdb_stuff { + EMConfigTargetPrefs *target; + ESourceList *source_list; + + GtkWidget *option_menu; + GtkWidget *check; +}; + +/* Static forward declarations */ +static void bbdb_do_it (EBook *book, const char *name, const char *email); +static void add_email_to_contact (EContact *contact, const char *email); +static void enable_toggled_cb (GtkWidget *widget, gpointer data); +static void source_changed_cb (GtkWidget *widget, ESource *source, gpointer data); +static GtkWidget *create_addressbook_option_menu (struct bbdb_stuff *stuff); +static void cleanup_cb (GObject *o, gpointer data); + + + +/* Code to populate addressbook when you reply to a mail follows */ + +void +bbdb_handle_reply (EPlugin *ep, EMEventTargetMessage *target) +{ + const CamelInternetAddress *cia; + const char *name; + const char *email; + char *uri; + EBook *book = NULL; + int i; + GConfClient *gconf; + + gboolean status; + GError *error; + + gconf = gconf_client_get_default (); + uri = gconf_client_get_string (gconf, GCONF_KEY_WHICH_ADDRESSBOOK, NULL); + g_object_unref (G_OBJECT (gconf)); + if (uri == NULL) + book = e_book_new_system_addressbook (&error); + else + book = e_book_new_from_uri (uri, &error); + if (book == NULL) { + g_warning ("bbdb: failed to open addressbook: %s\n", error->message); + return; + } + + status = e_book_open (book, FALSE, NULL); + + if (status == FALSE) { + g_warning ("bbdb: failed to open local addressbook\n"); + return; + } + + + cia = camel_mime_message_get_from (target->message); + for (i = 0; i < camel_address_length CAMEL_ADDRESS (cia); i ++) { + camel_internet_address_get (cia, i, &name, &email); + bbdb_do_it (book, name, email); + } + + if (((EEventTarget *) target)->mask & EM_EVENT_MESSAGE_REPLY_ALL) { + g_object_unref (G_OBJECT (book)); + return; + } + + cia = camel_mime_message_get_recipients (target->message, CAMEL_RECIPIENT_TYPE_TO); + for (i = 0; i < camel_address_length CAMEL_ADDRESS (cia); i ++) { + camel_internet_address_get (cia, i, &name, &email); + bbdb_do_it (book, name, email); + } + + cia = camel_mime_message_get_recipients (target->message, CAMEL_RECIPIENT_TYPE_CC); + for (i = 0; i < camel_address_length CAMEL_ADDRESS (cia); i ++) { + camel_internet_address_get (cia, i, &name, &email); + bbdb_do_it (book, name, email); + } + + g_object_unref (G_OBJECT (book)); +} + +static void +bbdb_do_it (EBook *book, const char *name, const char *email) +{ + char *query_string; + EBookQuery *query; + GList *contacts; + EContact *contact; + + gboolean status; + GError *error = NULL; + + g_return_if_fail (name != NULL); + g_return_if_fail (email != NULL); + g_return_if_fail (book != NULL); + g_return_if_fail (strcmp (name, "")); + g_return_if_fail (strcmp (email, "")); + g_return_if_fail (strchr (email, '@') != NULL); + + /* If any contacts exists with this email address, don't do anything */ + query_string = g_strdup_printf ("(contains \"email\" \"%s\")", email); + query = e_book_query_from_string (query_string); + g_free (query_string); + + status = e_book_get_contacts (book, query, &contacts, NULL); + if (contacts != NULL) { + g_warning ("bbdb: contact exists, bailing\n"); + return; + } + + /* If a contact exists with this name, add the email address to it. */ + query_string = g_strdup_printf ("(is \"full_name\" \"%s\")", name); + query = e_book_query_from_string (query_string); + g_free (query_string); + + status = e_book_get_contacts (book, query, &contacts, NULL); + if (contacts != NULL) { + contact = (EContact *) contacts->data; + add_email_to_contact (contact, email); + if (! e_book_commit_contact (book, contact, &error)) + g_warning ("bbdb: Could not modify contact: %s\n", error->message); + return; + } + + /* Otherwise, create a new contact. */ + contact = e_contact_new (); + e_contact_set (contact, E_CONTACT_FULL_NAME, (gpointer) name); + add_email_to_contact (contact, email); + + if (! e_book_add_contact (book, contact, &error)) { + g_warning ("bbdb: Failed to add new contact: %s\n", error->message); + return; + } +} + +static void +add_email_to_contact (EContact *contact, const char *email) +{ + GList *emails; + + emails = e_contact_get (contact, E_CONTACT_EMAIL); + emails = g_list_append (emails, (gpointer) email); + e_contact_set (contact, E_CONTACT_EMAIL, (gpointer) emails); +} + + + +/* Code to implement the configuration user interface follows */ + +static void +enable_toggled_cb (GtkWidget *widget, gpointer data) +{ + struct bbdb_stuff *stuff = (struct bbdb_stuff *) data; + gboolean active; + + active = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (widget)); + + /* Save the new setting to gconf */ + gconf_client_set_bool (stuff->target->gconf, GCONF_KEY_ENABLE, active, NULL); + + gtk_widget_set_sensitive (stuff->option_menu, active); +} + +static void +source_changed_cb (GtkWidget *widget, ESource *source, gpointer data) +{ + struct bbdb_stuff *stuff = (struct bbdb_stuff *) data; + + gconf_client_set_string (stuff->target->gconf, GCONF_KEY_WHICH_ADDRESSBOOK, e_source_get_uri (source), NULL); +} + +static GtkWidget * +create_addressbook_option_menu (struct bbdb_stuff *stuff) +{ + GtkWidget *menu; + ESourceList *source_list; + char *selected_source_uri; + ESource *selected_source; + + GConfClient *gconf = stuff->target->gconf; + + source_list = e_source_list_new_for_gconf (gconf, "/apps/evolution/addressbook/sources"); + menu = e_source_option_menu_new (source_list); + + selected_source_uri = gconf_client_get_string (gconf, GCONF_KEY_WHICH_ADDRESSBOOK, NULL); + if (selected_source_uri != NULL) { + selected_source = e_source_new_with_absolute_uri ("", selected_source_uri); + e_source_option_menu_select (E_SOURCE_OPTION_MENU (menu), selected_source); + } + + gtk_widget_show (menu); + + stuff->source_list = source_list; + + return menu; +} + +GtkWidget * +bbdb_page_factory (EPlugin *ep, EConfigHookItemFactoryData *hook_data) +{ + struct bbdb_stuff *stuff; + EMConfigTargetPrefs *target = (EMConfigTargetPrefs *) hook_data->config->target; + GtkWidget *page; + GtkWidget *tab_label; + GtkWidget *frame; + GtkWidget *frame_label; + GtkWidget *padding_label; + GtkWidget *hbox; + GtkWidget *inner_vbox; + GtkWidget *check; + GtkWidget *option; + + /* A structure to pass some stuff around */ + stuff = g_new0 (struct bbdb_stuff, 1); + stuff->target = target; + + /* Create a new notebook page */ + page = gtk_vbox_new (FALSE, 0); + GTK_CONTAINER (page)->border_width = 12; + tab_label = gtk_label_new (_("Automatic Contacts")); + gtk_notebook_append_page (GTK_NOTEBOOK (hook_data->parent), page, tab_label); + + /* Frame */ + frame = gtk_vbox_new (FALSE, 6); + gtk_box_pack_start (GTK_BOX (page), frame, TRUE, TRUE, 0); + + /* Label */ + frame_label = gtk_label_new (""); + gtk_label_set_markup (GTK_LABEL (frame_label), _("<span weight=\"bold\">Automatic Contacts</span>")); + GTK_MISC (frame_label)->xalign = 0.0; + gtk_box_pack_start (GTK_BOX (frame), frame_label, FALSE, FALSE, 0); + + /* Indent/padding */ + hbox = gtk_hbox_new (FALSE, 12); + gtk_box_pack_start (GTK_BOX (frame), hbox, FALSE, TRUE, 0); + padding_label = gtk_label_new (""); + gtk_box_pack_start (GTK_BOX (hbox), padding_label, FALSE, FALSE, 0); + inner_vbox = gtk_vbox_new (FALSE, 6); + gtk_box_pack_start (GTK_BOX (hbox), inner_vbox, FALSE, FALSE, 0); + + /* Enable BBDB checkbox */ + check = gtk_check_button_new_with_mnemonic (_("_Automatically create entries in the addressbook when responding to mail")); + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (check), gconf_client_get_bool (target->gconf, GCONF_KEY_ENABLE, NULL)); + g_signal_connect (GTK_TOGGLE_BUTTON (check), "toggled", G_CALLBACK (enable_toggled_cb), stuff); + gtk_box_pack_start (GTK_BOX (inner_vbox), check, FALSE, FALSE, 0); + stuff->check = check; + + /* Source selection open menu */ + option = create_addressbook_option_menu (stuff); + g_signal_connect (option, "source_selected", G_CALLBACK (source_changed_cb), stuff); + gtk_widget_set_sensitive (option, gconf_client_get_bool (target->gconf, GCONF_KEY_ENABLE, NULL)); + gtk_box_pack_start (GTK_BOX (inner_vbox), option, FALSE, FALSE, 0); + stuff->option_menu = option; + + /* Clean up */ + g_signal_connect (page, "destroy", G_CALLBACK (cleanup_cb), stuff); + + gtk_widget_show_all (page); + + return page; +} + +static void +cleanup_cb (GObject *o, gpointer data) +{ + struct bbdb_stuff *stuff = data; + + g_object_unref (stuff->source_list); + g_free (stuff); +} diff --git a/plugins/bbdb/org-gnome-evolution-bbdb.eplug.in b/plugins/bbdb/org-gnome-evolution-bbdb.eplug.in new file mode 100644 index 0000000000..b2b0b1cb63 --- /dev/null +++ b/plugins/bbdb/org-gnome-evolution-bbdb.eplug.in @@ -0,0 +1,20 @@ +<e-plugin-list> + <e-plugin id="org.gnome.evolution.bbdb" type="shlib" name="BBDB Functionality for Evolution" description="Automatically tracks contacts" + location="@PLUGINDIR@/liborg-gnome-evolution-bbdb.so"> + + <hook class="org.gnome.evolution.mail.events:1.0"> + <event + id="message.replying" + handle="bbdb_handle_reply" + target="message" + /> + </hook> + + <hook class="org.gnome.evolution.mail.config:1.0"> + <group target="prefs"> + <item type="page" path="80.bbdb" label="BBDB" factory="bbdb_page_factory"/> + </group> + </hook> + + </e-plugin> +</e-plugin-list>
\ No newline at end of file |