aboutsummaryrefslogtreecommitdiffstats
path: root/plugins/bbdb/bbdb.c
diff options
context:
space:
mode:
authorNat Friedman <nat@novell.com>2004-10-22 12:37:29 +0800
committerNat Friedman <nat@src.gnome.org>2004-10-22 12:37:29 +0800
commit31f3035ad5b3da9c6b4baf512e457f946a99477c (patch)
treecb7f128b1bce04eeb44aac0688abcde4db6b6de3 /plugins/bbdb/bbdb.c
parent9045f9fddba2e3d7b20894b0675d0cf8eeb9a9a5 (diff)
downloadgsoc2013-evolution-31f3035ad5b3da9c6b4baf512e457f946a99477c.tar
gsoc2013-evolution-31f3035ad5b3da9c6b4baf512e457f946a99477c.tar.gz
gsoc2013-evolution-31f3035ad5b3da9c6b4baf512e457f946a99477c.tar.bz2
gsoc2013-evolution-31f3035ad5b3da9c6b4baf512e457f946a99477c.tar.lz
gsoc2013-evolution-31f3035ad5b3da9c6b4baf512e457f946a99477c.tar.xz
gsoc2013-evolution-31f3035ad5b3da9c6b4baf512e457f946a99477c.tar.zst
gsoc2013-evolution-31f3035ad5b3da9c6b4baf512e457f946a99477c.zip
Added the bbdb plugin.
2004-10-22 Nat Friedman <nat@novell.com> * configure.in: Added the bbdb plugin. Man, hacking is fun. svn path=/trunk/; revision=27690
Diffstat (limited to 'plugins/bbdb/bbdb.c')
-rw-r--r--plugins/bbdb/bbdb.c328
1 files changed, 328 insertions, 0 deletions
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);
+}