qulogic/pidgin

Parents 88f86f065f99
Children d7d2b78a6bcf
disapproval of revision '88f86f065f99effaf1315dafbae8c9763ca5750d'
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/pidgin/plugins/gevolution/Makefile.am Thu Sep 20 12:01:33 2007 +0000
@@ -0,0 +1,29 @@
+plugindir = $(libdir)/pidgin
+
+gevolution_la_LDFLAGS = -module -avoid-version
+
+if PLUGINS
+
+plugin_LTLIBRARIES = gevolution.la
+
+gevolution_la_SOURCES = \
+ add_buddy_dialog.c \
+ assoc-buddy.c \
+ gevolution.c \
+ gevolution.h \
+ gevo-util.c \
+ new_person_dialog.c \
+ eds-utils.c
+
+gevolution_la_LIBADD = $(EVOLUTION_ADDRESSBOOK_LIBS) $(GTK_LIBS)
+
+endif
+
+AM_CPPFLAGS = \
+ -DDATADIR=\"$(datadir)\" \
+ -I$(top_srcdir)/libpurple \
+ -I$(top_builddir)/libpurple \
+ -I$(top_srcdir)/pidgin \
+ $(EVOLUTION_ADDRESSBOOK_CFLAGS) \
+ $(DEBUG_CFLAGS) \
+ $(GTK_CFLAGS)
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/pidgin/plugins/gevolution/add_buddy_dialog.c Thu Sep 20 12:01:33 2007 +0000
@@ -0,0 +1,631 @@
+/*
+ * Evolution integration plugin for Purple
+ *
+ * Copyright (C) 2003 Christian Hammond.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02111-1301, USA.
+ */
+#include "internal.h"
+#include "gtkblist.h"
+#include "pidgin.h"
+#include "gtkutils.h"
+
+#include "debug.h"
+
+#include "gevolution.h"
+
+#include <stdlib.h>
+
+enum
+{
+ COLUMN_NAME,
+ COLUMN_PRPL_ICON,
+ COLUMN_USERNAME,
+ COLUMN_DATA,
+ NUM_COLUMNS
+};
+
+static gint
+delete_win_cb(GtkWidget *w, GdkEvent *event, GevoAddBuddyDialog *dialog)
+{
+ gtk_widget_destroy(dialog->win);
+
+ if (dialog->contacts != NULL)
+ {
+ g_list_foreach(dialog->contacts, (GFunc)g_object_unref, NULL);
+ g_list_free(dialog->contacts);
+ }
+
+ if (dialog->book != NULL)
+ g_object_unref(dialog->book);
+
+ gevo_addrbooks_model_unref(dialog->addrbooks);
+
+ if (dialog->username != NULL)
+ g_free(dialog->username);
+
+ g_free(dialog);
+
+ return 0;
+}
+
+static void
+new_person_cb(GtkWidget *w, GevoAddBuddyDialog *dialog)
+{
+ const char *group_name;
+
+ group_name =
+ pidgin_text_combo_box_entry_get_text(dialog->group_combo);
+
+ gevo_new_person_dialog_show(dialog->book, NULL, dialog->account, dialog->username,
+ (*group_name ? group_name : NULL),
+ NULL, FALSE);
+
+ delete_win_cb(NULL, NULL, dialog);
+}
+
+static void
+cancel_cb(GtkWidget *w, GevoAddBuddyDialog *dialog)
+{
+ delete_win_cb(NULL, NULL, dialog);
+}
+
+static void
+select_buddy_cb(GtkWidget *w, GevoAddBuddyDialog *dialog)
+{
+ GtkTreeSelection *selection;
+ GtkTreeIter iter;
+ const char *group_name;
+ const char *fullname;
+ const char *username;
+ EContact *contact;
+
+ selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(dialog->treeview));
+
+ if (!gtk_tree_selection_get_selected(selection, NULL, &iter))
+ return;
+
+ gtk_tree_model_get(GTK_TREE_MODEL(dialog->model), &iter,
+ COLUMN_NAME, &fullname,
+ COLUMN_USERNAME, &username,
+ COLUMN_DATA, &contact,
+ -1);
+
+ group_name =
+ pidgin_text_combo_box_entry_get_text(dialog->group_combo);
+
+ if (username == NULL || *username == '\0')
+ {
+ gevo_new_person_dialog_show(dialog->book, NULL, dialog->account, dialog->username,
+ (*group_name ? group_name : NULL),
+ NULL, FALSE);
+ }
+ else
+ {
+ gevo_add_buddy(dialog->account, group_name, username, fullname);
+ }
+
+ delete_win_cb(NULL, NULL, dialog);
+}
+
+static void
+add_columns(GevoAddBuddyDialog *dialog)
+{
+ GtkCellRenderer *renderer;
+ GtkTreeViewColumn *column;
+
+ /* Name column */
+ column = gtk_tree_view_column_new();
+ gtk_tree_view_column_set_title(column, _("Name"));
+ gtk_tree_view_insert_column(GTK_TREE_VIEW(dialog->treeview), column, -1);
+ gtk_tree_view_column_set_sort_column_id(column, COLUMN_NAME);
+
+ renderer = gtk_cell_renderer_text_new();
+ gtk_tree_view_column_pack_start(column, renderer, TRUE);
+ gtk_tree_view_column_add_attribute(column, renderer,
+ "text", COLUMN_NAME);
+
+ /* Account column */
+ column = gtk_tree_view_column_new();
+ gtk_tree_view_column_set_title(column, _("Instant Messaging"));
+ gtk_tree_view_insert_column(GTK_TREE_VIEW(dialog->treeview), column, -1);
+ gtk_tree_view_column_set_sort_column_id(column, COLUMN_USERNAME);
+
+ /* Protocol icon */
+ renderer = gtk_cell_renderer_pixbuf_new();
+ gtk_tree_view_column_pack_start(column, renderer, FALSE);
+ gtk_tree_view_column_add_attribute(column, renderer,
+ "pixbuf", COLUMN_PRPL_ICON);
+
+ /* Account name */
+ renderer = gtk_cell_renderer_text_new();
+ gtk_tree_view_column_pack_start(column, renderer, TRUE);
+ gtk_tree_view_column_add_attribute(column, renderer,
+ "text", COLUMN_USERNAME);
+}
+
+static void
+add_ims(GevoAddBuddyDialog *dialog, EContact *contact, const char *name,
+ GList *list, const char *id)
+{
+ PurpleAccount *account = NULL;
+ GList *l;
+ GtkTreeIter iter;
+ GdkPixbuf *pixbuf;
+
+ if (list == NULL)
+ return;
+
+ for (l = purple_connections_get_all(); l != NULL; l = l->next)
+ {
+ PurpleConnection *gc = (PurpleConnection *)l->data;
+
+ account = purple_connection_get_account(gc);
+
+ if (!strcmp(purple_account_get_protocol_id(account), id))
+ break;
+
+ account = NULL;
+ }
+
+ if (account == NULL)
+ return;
+
+ pixbuf = pidgin_create_prpl_icon(account, 0.5);
+
+ for (l = list; l != NULL; l = l->next)
+ {
+ char *account_name = (char *)l->data;
+
+ if (account_name == NULL)
+ continue;
+
+ if (purple_find_buddy(dialog->account, account_name) != NULL)
+ continue;
+
+ gtk_list_store_append(dialog->model, &iter);
+
+ gtk_list_store_set(dialog->model, &iter,
+ COLUMN_NAME, name,
+ COLUMN_PRPL_ICON, pixbuf,
+ COLUMN_USERNAME, account_name,
+ COLUMN_DATA, contact,
+ -1);
+
+ if (!strcmp(purple_account_get_protocol_id(account),
+ purple_account_get_protocol_id(dialog->account)) &&
+ dialog->username != NULL &&
+ !strcmp(account_name, dialog->username))
+ {
+ GtkTreeSelection *selection;
+
+ /* This is it. Select it. */
+ selection = gtk_tree_view_get_selection(
+ GTK_TREE_VIEW(dialog->treeview));
+
+ gtk_tree_selection_select_iter(selection, &iter);
+ }
+ }
+
+ if (pixbuf != NULL)
+ g_object_unref(G_OBJECT(pixbuf));
+
+ g_list_foreach(list, (GFunc)g_free, NULL);
+ g_list_free(list);
+}
+
+static void
+populate_treeview(GevoAddBuddyDialog *dialog, const gchar *uri)
+{
+ EBookQuery *query;
+ EBook *book;
+ gboolean status;
+ GList *cards, *c;
+
+ if (dialog->book != NULL)
+ {
+ g_object_unref(dialog->book);
+ dialog->book = NULL;
+ }
+
+ if (dialog->contacts != NULL)
+ {
+ g_list_foreach(dialog->contacts, (GFunc)g_object_unref, NULL);
+ g_list_free(dialog->contacts);
+ dialog->contacts = NULL;
+ }
+
+ gtk_list_store_clear(dialog->model);
+
+ if (!gevo_load_addressbook(uri, &book, NULL))
+ {
+ purple_debug_error("evolution",
+ "Error retrieving default addressbook\n");
+
+ return;
+ }
+
+ query = e_book_query_field_exists(E_CONTACT_FULL_NAME);
+
+ if (query == NULL)
+ {
+ purple_debug_error("evolution", "Error in creating query\n");
+
+ g_object_unref(book);
+
+ return;
+ }
+
+ status = e_book_get_contacts(book, query, &cards, NULL);
+
+ e_book_query_unref(query);
+
+ if (!status)
+ {
+ purple_debug_error("evolution", "Error %d in getting card list\n",
+ status);
+
+ g_object_unref(book);
+
+ return;
+ }
+
+ for (c = cards; c != NULL; c = c->next)
+ {
+ EContact *contact = E_CONTACT(c->data);
+ const char *name;
+ GList *aims, *jabbers, *yahoos, *msns, *icqs, *novells;
+
+ name = e_contact_get_const(contact, E_CONTACT_FULL_NAME);
+
+ aims = e_contact_get(contact, E_CONTACT_IM_AIM);
+ jabbers = e_contact_get(contact, E_CONTACT_IM_JABBER);
+ yahoos = e_contact_get(contact, E_CONTACT_IM_YAHOO);
+ msns = e_contact_get(contact, E_CONTACT_IM_MSN);
+ icqs = e_contact_get(contact, E_CONTACT_IM_ICQ);
+ novells = e_contact_get(contact, E_CONTACT_IM_GROUPWISE);
+
+ if (aims == NULL && jabbers == NULL && yahoos == NULL &&
+ msns == NULL && icqs == NULL && novells == NULL)
+ {
+ GtkTreeIter iter;
+
+ gtk_list_store_append(dialog->model, &iter);
+
+ gtk_list_store_set(dialog->model, &iter,
+ COLUMN_NAME, name,
+ COLUMN_DATA, contact,
+ -1);
+ }
+ else
+ {
+ add_ims(dialog, contact, name, aims, "prpl-oscar");
+ add_ims(dialog, contact, name, jabbers, "prpl-jabber");
+ add_ims(dialog, contact, name, yahoos, "prpl-yahoo");
+ add_ims(dialog, contact, name, msns, "prpl-msn");
+ add_ims(dialog, contact, name, icqs, "prpl-oscar");
+ add_ims(dialog, contact, name, novells, "prpl-novell");
+ }
+ }
+
+ dialog->contacts = cards;
+ dialog->book = book;
+}
+
+static void
+addrbook_change_cb(GtkComboBox *combo, GevoAddBuddyDialog *dialog)
+{
+ GtkTreeIter iter;
+ const char *esource_uri;
+
+ if (!gtk_combo_box_get_active_iter(combo, &iter))
+ return;
+
+ gtk_tree_model_get(GTK_TREE_MODEL(dialog->addrbooks), &iter,
+ ADDRBOOK_COLUMN_URI, &esource_uri,
+ -1);
+
+ populate_treeview(dialog, esource_uri);
+}
+
+static void
+selected_cb(GtkTreeSelection *sel, GevoAddBuddyDialog *dialog)
+{
+ GtkTreeSelection *selection;
+
+ selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(dialog->treeview));
+ gtk_widget_set_sensitive(dialog->select_button,
+ gtk_tree_selection_get_selected(selection, NULL, NULL));
+}
+
+static void
+search_changed_cb(GtkEntry *entry, GevoAddBuddyDialog *dialog)
+{
+ const char *text = gtk_entry_get_text(entry);
+ GList *l;
+
+ gtk_list_store_clear(dialog->model);
+
+ for (l = dialog->contacts; l != NULL; l = l->next)
+ {
+ EContact *contact = E_CONTACT(l->data);
+ const char *name;
+ GList *aims, *jabbers, *yahoos, *msns, *icqs, *novells;
+
+ name = e_contact_get_const(contact, E_CONTACT_FULL_NAME);
+
+ if (text != NULL && *text != '\0' && name != NULL &&
+ g_ascii_strncasecmp(name, text, strlen(text)))
+ {
+ continue;
+ }
+
+ aims = e_contact_get(contact, E_CONTACT_IM_AIM);
+ jabbers = e_contact_get(contact, E_CONTACT_IM_JABBER);
+ yahoos = e_contact_get(contact, E_CONTACT_IM_YAHOO);
+ msns = e_contact_get(contact, E_CONTACT_IM_MSN);
+ icqs = e_contact_get(contact, E_CONTACT_IM_ICQ);
+ novells = e_contact_get(contact, E_CONTACT_IM_GROUPWISE);
+
+ if (aims == NULL && jabbers == NULL && yahoos == NULL &&
+ msns == NULL && icqs == NULL && novells == NULL)
+ {
+ GtkTreeIter iter;
+
+ gtk_list_store_append(dialog->model, &iter);
+
+ gtk_list_store_set(dialog->model, &iter,
+ COLUMN_NAME, name,
+ COLUMN_DATA, contact,
+ -1);
+ }
+ else
+ {
+ add_ims(dialog, contact, name, aims, "prpl-oscar");
+ add_ims(dialog, contact, name, jabbers, "prpl-jabber");
+ add_ims(dialog, contact, name, yahoos, "prpl-yahoo");
+ add_ims(dialog, contact, name, msns, "prpl-msn");
+ add_ims(dialog, contact, name, icqs, "prpl-oscar");
+ add_ims(dialog, contact, name, novells, "prpl-novell");
+ }
+ }
+}
+
+static void
+clear_cb(GtkWidget *w, GevoAddBuddyDialog *dialog)
+{
+ static gboolean lock = FALSE;
+
+ if (lock)
+ return;
+
+ lock = TRUE;
+ gtk_entry_set_text(GTK_ENTRY(dialog->search_field), "");
+ lock = FALSE;
+}
+
+void
+gevo_add_buddy_dialog_show(PurpleAccount *account, const char *username,
+ const char *group, const char *alias)
+{
+ GevoAddBuddyDialog *dialog;
+ GtkWidget *button;
+ GtkWidget *sw;
+ GtkWidget *label;
+ GtkWidget *vbox;
+ GtkWidget *hbox;
+ GtkWidget *bbox;
+ GtkWidget *sep;
+ GtkTreeSelection *selection;
+ GtkCellRenderer *cell;
+
+ dialog = g_new0(GevoAddBuddyDialog, 1);
+
+ dialog->account =
+ (account != NULL
+ ? account
+ : purple_connection_get_account(purple_connections_get_all()->data));
+
+ if (username != NULL)
+ dialog->username = g_strdup(username);
+
+ dialog->win = pidgin_create_window(_("Add Buddy"), PIDGIN_HIG_BORDER, "add_buddy", TRUE);
+ gtk_widget_set_size_request(dialog->win, -1, 400);
+
+ g_signal_connect(G_OBJECT(dialog->win), "delete_event",
+ G_CALLBACK(delete_win_cb), dialog);
+
+ /* Setup the vbox */
+ vbox = gtk_vbox_new(FALSE, 12);
+ gtk_container_add(GTK_CONTAINER(dialog->win), vbox);
+ gtk_widget_show(vbox);
+
+ /* Add the label. */
+ label = gtk_label_new(_("Select a person from your address book below, "
+ "or add a new person."));
+ gtk_label_set_line_wrap(GTK_LABEL(label), TRUE);
+ gtk_misc_set_alignment(GTK_MISC(label), 0, 0);
+ gtk_box_pack_start(GTK_BOX(vbox), label, FALSE, TRUE, 0);
+ gtk_widget_show(label);
+
+ /* Add the search hbox */
+ hbox = gtk_hbox_new(FALSE, 6);
+ gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, TRUE, 0);
+ gtk_widget_show(hbox);
+
+ /* "Search" */
+ label = gtk_label_new(_("Search"));
+ gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0);
+ gtk_widget_show(label);
+
+ /* Addressbooks */
+ dialog->addrbooks = gevo_addrbooks_model_new();
+
+ dialog->addrbooks_combo = gtk_combo_box_new_with_model(
+ dialog->addrbooks);
+ cell = gtk_cell_renderer_text_new();
+ gtk_cell_layout_pack_start(GTK_CELL_LAYOUT(dialog->addrbooks_combo),
+ cell, TRUE);
+ gtk_cell_layout_set_attributes(GTK_CELL_LAYOUT(dialog->addrbooks_combo),
+ cell,
+ "text", ADDRBOOK_COLUMN_NAME,
+ NULL);
+ gtk_box_pack_start(GTK_BOX(hbox), dialog->addrbooks_combo, FALSE,
+ FALSE, 0);
+ gtk_widget_show(dialog->addrbooks_combo);
+
+ /* Search field */
+ dialog->search_field = gtk_entry_new();
+ gtk_box_pack_start(GTK_BOX(hbox), dialog->search_field, TRUE, TRUE, 0);
+ gtk_widget_show(dialog->search_field);
+
+ g_signal_connect(G_OBJECT(dialog->search_field), "changed",
+ G_CALLBACK(search_changed_cb), dialog);
+
+ /* Clear button */
+ button = gtk_button_new_from_stock(GTK_STOCK_CLEAR);
+ gtk_box_pack_start(GTK_BOX(hbox), button, FALSE, FALSE, 0);
+ gtk_widget_show(button);
+
+ g_signal_connect(G_OBJECT(button), "clicked",
+ G_CALLBACK(clear_cb), dialog);
+
+ /* Scrolled Window */
+ sw = gtk_scrolled_window_new(0, 0);
+ gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(sw),
+ GTK_POLICY_AUTOMATIC,
+ GTK_POLICY_ALWAYS);
+ gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(sw),
+ GTK_SHADOW_IN);
+ gtk_box_pack_start(GTK_BOX(vbox), sw, TRUE, TRUE, 0);
+ gtk_widget_show(sw);
+
+ /* Create the list model for the treeview. */
+ dialog->model = gtk_list_store_new(NUM_COLUMNS,
+ G_TYPE_STRING, GDK_TYPE_PIXBUF,
+ G_TYPE_STRING, G_TYPE_POINTER);
+
+ /* Now for the treeview */
+ dialog->treeview =
+ gtk_tree_view_new_with_model(GTK_TREE_MODEL(dialog->model));
+ gtk_tree_view_set_rules_hint(GTK_TREE_VIEW(dialog->treeview), TRUE);
+ gtk_container_add(GTK_CONTAINER(sw), dialog->treeview);
+ gtk_widget_show(dialog->treeview);
+
+ selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(dialog->treeview));
+
+ gtk_tree_selection_set_mode(selection, GTK_SELECTION_SINGLE);
+
+ g_signal_connect(G_OBJECT(selection), "changed",
+ G_CALLBACK(selected_cb), dialog);
+
+ add_columns(dialog);
+
+ /*
+ * Catch addressbook selection and populate treeview with the first
+ * addressbook
+ */
+ gevo_addrbooks_model_populate(dialog->addrbooks);
+ g_signal_connect(G_OBJECT(dialog->addrbooks_combo), "changed",
+ G_CALLBACK(addrbook_change_cb), dialog);
+ gtk_combo_box_set_active(GTK_COMBO_BOX(dialog->addrbooks_combo), 0);
+
+ /* Group box */
+ hbox = gtk_hbox_new(FALSE, 6);
+ gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 0);
+ gtk_widget_show(hbox);
+
+ label = gtk_label_new(_("Group:"));
+ gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5);
+ gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0);
+ gtk_widget_show(label);
+
+ dialog->group_combo =
+ pidgin_text_combo_box_entry_new(NULL, gevo_get_groups());
+ gtk_box_pack_start(GTK_BOX(hbox), dialog->group_combo, TRUE, TRUE, 0);
+ gtk_widget_show(dialog->group_combo);
+
+ /* Cool. Now we only have a little left... */
+
+ /* Separator. */
+ sep = gtk_hseparator_new();
+ gtk_box_pack_start(GTK_BOX(vbox), sep, FALSE, FALSE, 0);
+ gtk_widget_show(sep);
+
+ /* Button box */
+ bbox = gtk_hbutton_box_new();
+ gtk_box_set_spacing(GTK_BOX(bbox), 6);
+ gtk_button_box_set_layout(GTK_BUTTON_BOX(bbox), GTK_BUTTONBOX_END);
+ gtk_box_pack_end(GTK_BOX(vbox), bbox, FALSE, TRUE, 0);
+ gtk_widget_show(bbox);
+
+ /* "New Person" button */
+ button = pidgin_pixbuf_button_from_stock(_("New Person"), GTK_STOCK_NEW,
+ PIDGIN_BUTTON_HORIZONTAL);
+ gtk_box_pack_start(GTK_BOX(bbox), button, FALSE, FALSE, 0);
+ gtk_widget_show(button);
+
+ g_signal_connect(G_OBJECT(button), "clicked",
+ G_CALLBACK(new_person_cb), dialog);
+
+ /* "Cancel" button */
+ button = gtk_button_new_from_stock(GTK_STOCK_CANCEL);
+ gtk_box_pack_start(GTK_BOX(bbox), button, FALSE, FALSE, 0);
+ gtk_widget_show(button);
+
+ g_signal_connect(G_OBJECT(button), "clicked",
+ G_CALLBACK(cancel_cb), dialog);
+
+ /* "Select Buddy" button */
+ button = pidgin_pixbuf_button_from_stock(_("Select Buddy"), GTK_STOCK_APPLY,
+ PIDGIN_BUTTON_HORIZONTAL);
+ dialog->select_button = button;
+ gtk_box_pack_start(GTK_BOX(bbox), button, FALSE, FALSE, 0);
+ gtk_widget_set_sensitive(button, FALSE);
+ gtk_widget_show(button);
+
+ g_signal_connect(G_OBJECT(button), "clicked",
+ G_CALLBACK(select_buddy_cb), dialog);
+
+ /* Show it. */
+ gtk_widget_show(dialog->win);
+}
+
+void
+gevo_add_buddy_dialog_add_person(GevoAddBuddyDialog *dialog,
+ EContact *contact, const char *name,
+ PurpleAccount *account, const char *screenname)
+{
+ GdkPixbuf *pixbuf;
+ GtkTreeIter iter;
+
+ pixbuf = pidgin_create_prpl_icon(account, 0.5);
+
+ gtk_list_store_append(dialog->model, &iter);
+
+ gtk_list_store_set(dialog->model, &iter,
+ COLUMN_NAME, name,
+ COLUMN_PRPL_ICON, pixbuf,
+ COLUMN_DATA, contact,
+ COLUMN_USERNAME, screenname,
+ -1);
+
+ if (contact != NULL)
+ dialog->contacts = g_list_append(dialog->contacts, contact);
+
+ if (pixbuf != NULL)
+ g_object_unref(G_OBJECT(pixbuf));
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/pidgin/plugins/gevolution/assoc-buddy.c Thu Sep 20 12:01:33 2007 +0000
@@ -0,0 +1,499 @@
+/*
+ * Evolution integration plugin for Purple
+ *
+ * Copyright (C) 2003 Christian Hammond.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02111-1301, USA.
+ */
+#include "internal.h"
+#include "gtkblist.h"
+#include "gtkexpander.h"
+#include "pidgin.h"
+#include "gtkutils.h"
+#include "gtkimhtml.h"
+
+#include "debug.h"
+
+#include "gevolution.h"
+
+#include <stdlib.h>
+#include <gtk/gtk.h>
+
+enum
+{
+ COLUMN_NAME,
+ COLUMN_DATA,
+ NUM_COLUMNS
+};
+
+static gint
+delete_win_cb(GtkWidget *w, GdkEvent *event, GevoAssociateBuddyDialog *dialog)
+{
+ gtk_widget_destroy(dialog->win);
+
+ if (dialog->contacts != NULL)
+ {
+ g_list_foreach(dialog->contacts, (GFunc)g_object_unref, NULL);
+ g_list_free(dialog->contacts);
+ }
+
+ g_object_unref(dialog->book);
+ gevo_addrbooks_model_unref(dialog->addrbooks);
+
+ g_free(dialog);
+
+ return 0;
+}
+
+static void
+search_changed_cb(GtkEntry *entry, GevoAssociateBuddyDialog *dialog)
+{
+ const char *text = gtk_entry_get_text(entry);
+ GList *l;
+
+ gtk_list_store_clear(dialog->model);
+
+ for (l = dialog->contacts; l != NULL; l = l->next)
+ {
+ EContact *contact = E_CONTACT(l->data);
+ const char *name;
+ GtkTreeIter iter;
+
+ name = e_contact_get_const(contact, E_CONTACT_FULL_NAME);
+
+ if (text != NULL && *text != '\0' && name != NULL &&
+ g_ascii_strncasecmp(name, text, strlen(text)))
+ {
+ continue;
+ }
+
+ gtk_list_store_append(dialog->model, &iter);
+
+ gtk_list_store_set(dialog->model, &iter,
+ COLUMN_NAME, name,
+ COLUMN_DATA, contact,
+ -1);
+ }
+}
+
+static void
+clear_cb(GtkWidget *w, GevoAssociateBuddyDialog *dialog)
+{
+ static gboolean lock = FALSE;
+
+ if (lock)
+ return;
+
+ lock = TRUE;
+ gtk_entry_set_text(GTK_ENTRY(dialog->search_field), "");
+ lock = FALSE;
+}
+
+static void
+selected_cb(GtkTreeSelection *sel, GevoAssociateBuddyDialog *dialog)
+{
+ GtkTreeSelection *selection;
+
+ selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(dialog->treeview));
+ gtk_widget_set_sensitive(dialog->assoc_button,
+ gtk_tree_selection_get_selected(selection, NULL, NULL));
+}
+
+static void
+add_columns(GevoAssociateBuddyDialog *dialog)
+{
+ GtkCellRenderer *renderer;
+ GtkTreeViewColumn *column;
+
+ /* Name column */
+ column = gtk_tree_view_column_new();
+ gtk_tree_view_column_set_title(column, _("Name"));
+ gtk_tree_view_insert_column(GTK_TREE_VIEW(dialog->treeview), column, -1);
+ gtk_tree_view_column_set_sort_column_id(column, COLUMN_NAME);
+
+ renderer = gtk_cell_renderer_text_new();
+ gtk_tree_view_column_pack_start(column, renderer, TRUE);
+ gtk_tree_view_column_add_attribute(column, renderer,
+ "text", COLUMN_NAME);
+}
+
+static void
+populate_treeview(GevoAssociateBuddyDialog *dialog, const gchar *uri)
+{
+ EBook *book;
+ EBookQuery *query;
+ const char *prpl_id;
+ gboolean status;
+ GList *cards, *c;
+
+ if (dialog->book != NULL)
+ {
+ g_object_unref(dialog->book);
+ dialog->book = NULL;
+ }
+
+ if (dialog->contacts != NULL)
+ {
+ g_list_foreach(dialog->contacts, (GFunc) g_object_unref, NULL);
+ g_list_free(dialog->contacts);
+ dialog->contacts = NULL;
+ }
+
+ gtk_list_store_clear(dialog->model);
+
+ if (!gevo_load_addressbook(uri, &book, NULL))
+ {
+ purple_debug_error("evolution",
+ "Error retrieving addressbook\n");
+
+ return;
+ }
+
+ query = e_book_query_field_exists(E_CONTACT_FULL_NAME);
+
+ if (query == NULL)
+ {
+ purple_debug_error("evolution", "Error in creating query\n");
+
+ g_object_unref(book);
+
+ return;
+ }
+
+ status = e_book_get_contacts(book, query, &cards, NULL);
+
+ e_book_query_unref(query);
+
+ if (!status)
+ {
+ purple_debug_error("evolution", "Error %d in getting card list\n",
+ status);
+
+ g_object_unref(book);
+
+ return;
+ }
+
+ prpl_id = purple_account_get_protocol_id(dialog->buddy->account);
+
+ for (c = cards; c != NULL; c = c->next)
+ {
+ EContact *contact = E_CONTACT(c->data);
+ const char *name;
+ GtkTreeIter iter;
+ EContactField protocol_field = 0;
+
+ name = e_contact_get_const(contact, E_CONTACT_FULL_NAME);
+
+ gtk_list_store_append(dialog->model, &iter);
+
+ gtk_list_store_set(dialog->model, &iter,
+ COLUMN_NAME, name,
+ COLUMN_DATA, contact,
+ -1);
+
+ /* See if this user has the buddy in its list. */
+ protocol_field = gevo_prpl_get_field(dialog->buddy->account,
+ dialog->buddy);
+
+ if (protocol_field > 0)
+ {
+ GList *ims, *l;
+
+ ims = e_contact_get(contact, protocol_field);
+
+ for (l = ims; l != NULL; l = l->next)
+ {
+ if (!strcmp(l->data, dialog->buddy->name))
+ {
+ GtkTreeSelection *selection;
+
+ /* This is it. Select it. */
+ selection = gtk_tree_view_get_selection(
+ GTK_TREE_VIEW(dialog->treeview));
+
+ gtk_tree_selection_select_iter(selection, &iter);
+ break;
+ }
+ }
+ }
+ }
+
+ dialog->contacts = cards;
+ dialog->book = book;
+}
+
+static void
+addrbook_change_cb(GtkComboBox *combo, GevoAssociateBuddyDialog *dialog)
+{
+ GtkTreeIter iter;
+ const char *esource_uri;
+
+ if (!gtk_combo_box_get_active_iter(combo, &iter))
+ return;
+
+ gtk_tree_model_get(GTK_TREE_MODEL(dialog->addrbooks), &iter,
+ ADDRBOOK_COLUMN_URI, &esource_uri,
+ -1);
+
+ populate_treeview(dialog, esource_uri);
+}
+
+static void
+new_person_cb(GtkWidget *w, GevoAssociateBuddyDialog *dialog)
+{
+ gevo_new_person_dialog_show(dialog->book, NULL, dialog->buddy->account,
+ dialog->buddy->name, NULL, dialog->buddy,
+ TRUE);
+
+ delete_win_cb(NULL, NULL, dialog);
+}
+
+static void
+cancel_cb(GtkWidget *w, GevoAssociateBuddyDialog *dialog)
+{
+ delete_win_cb(NULL, NULL, dialog);
+}
+
+static void
+assoc_buddy_cb(GtkWidget *w, GevoAssociateBuddyDialog *dialog)
+{
+ GtkTreeSelection *selection;
+ GtkTreeIter iter;
+ GList *list;
+ const char *fullname;
+ EContactField protocol_field;
+ EContact *contact;
+
+ selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(dialog->treeview));
+
+ if (!gtk_tree_selection_get_selected(selection, NULL, &iter))
+ return;
+
+ gtk_tree_model_get(GTK_TREE_MODEL(dialog->model), &iter,
+ COLUMN_NAME, &fullname,
+ COLUMN_DATA, &contact,
+ -1);
+
+ protocol_field = gevo_prpl_get_field(dialog->buddy->account, dialog->buddy);
+
+ if (protocol_field == 0)
+ return; /* XXX */
+
+ list = e_contact_get(contact, protocol_field);
+ list = g_list_append(list, g_strdup(dialog->buddy->name));
+
+ e_contact_set(contact, protocol_field, list);
+
+ if (!e_book_commit_contact(dialog->book, contact, NULL))
+ purple_debug_error("evolution", "Error adding contact to book\n");
+
+ /* Free the list. */
+ g_list_foreach(list, (GFunc)g_free, NULL);
+ g_list_free(list);
+
+ delete_win_cb(NULL, NULL, dialog);
+}
+
+GevoAssociateBuddyDialog *
+gevo_associate_buddy_dialog_new(PurpleBuddy *buddy)
+{
+ GevoAssociateBuddyDialog *dialog;
+ GtkWidget *button;
+ GtkWidget *sw;
+ GtkWidget *label;
+ GtkWidget *vbox;
+ GtkWidget *hbox;
+ GtkWidget *bbox;
+ GtkWidget *sep;
+ GtkWidget *expander;
+ GtkTreeSelection *selection;
+ GtkCellRenderer *cell;
+
+ g_return_val_if_fail(buddy != NULL, NULL);
+
+ dialog = g_new0(GevoAssociateBuddyDialog, 1);
+
+ dialog->buddy = buddy;
+
+ dialog->win = pidgin_create_window(NULL, PIDGIN_HIG_BORDER, "assoc_buddy", TRUE);
+
+ g_signal_connect(G_OBJECT(dialog->win), "delete_event",
+ G_CALLBACK(delete_win_cb), dialog);
+
+ /* Setup the vbox */
+ vbox = gtk_vbox_new(FALSE, 12);
+ gtk_container_add(GTK_CONTAINER(dialog->win), vbox);
+ gtk_widget_show(vbox);
+
+ /* Add the label. */
+ label = gtk_label_new(_("Select a person from your address book to "
+ "add this buddy to, or create a new person."));
+ gtk_label_set_line_wrap(GTK_LABEL(label), TRUE);
+ gtk_misc_set_alignment(GTK_MISC(label), 0, 0);
+ gtk_box_pack_start(GTK_BOX(vbox), label, FALSE, TRUE, 0);
+ gtk_widget_show(label);
+
+ /* Add the search hbox */
+ hbox = gtk_hbox_new(FALSE, 6);
+ gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, TRUE, 0);
+ gtk_widget_show(hbox);
+
+ /* "Search" */
+ label = gtk_label_new(_("Search"));
+ gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0);
+ gtk_widget_show(label);
+
+ /* Addressbooks */
+ dialog->addrbooks = gevo_addrbooks_model_new();
+
+ dialog->addrbooks_combo = gtk_combo_box_new_with_model(dialog->addrbooks);
+ cell = gtk_cell_renderer_text_new();
+ gtk_cell_layout_pack_start(GTK_CELL_LAYOUT(dialog->addrbooks_combo),
+ cell, TRUE);
+ gtk_cell_layout_set_attributes(GTK_CELL_LAYOUT(dialog->addrbooks_combo),
+ cell,
+ "text", ADDRBOOK_COLUMN_NAME,
+ NULL);
+ gtk_box_pack_start(GTK_BOX(hbox), dialog->addrbooks_combo, FALSE, FALSE, 0);
+ gtk_widget_show(dialog->addrbooks_combo);
+
+
+ /* Search field */
+ dialog->search_field = gtk_entry_new();
+ gtk_box_pack_start(GTK_BOX(hbox), dialog->search_field, TRUE, TRUE, 0);
+ gtk_widget_show(dialog->search_field);
+
+ g_signal_connect(G_OBJECT(dialog->search_field), "changed",
+ G_CALLBACK(search_changed_cb), dialog);
+
+ /* Clear button */
+ button = gtk_button_new_from_stock(GTK_STOCK_CLEAR);
+ gtk_box_pack_start(GTK_BOX(hbox), button, FALSE, FALSE, 0);
+ gtk_widget_show(button);
+
+ g_signal_connect(G_OBJECT(button), "clicked",
+ G_CALLBACK(clear_cb), dialog);
+
+ /* Scrolled Window */
+ sw = gtk_scrolled_window_new(0, 0);
+ gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(sw),
+ GTK_POLICY_AUTOMATIC,
+ GTK_POLICY_ALWAYS);
+ gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(sw),
+ GTK_SHADOW_IN);
+ gtk_box_pack_start(GTK_BOX(vbox), sw, TRUE, TRUE, 0);
+ gtk_widget_show(sw);
+
+ /* Create the list model for the treeview. */
+ dialog->model = gtk_list_store_new(NUM_COLUMNS,
+ G_TYPE_STRING, G_TYPE_POINTER);
+
+ /* Now for the treeview */
+ dialog->treeview = gtk_tree_view_new_with_model(
+ GTK_TREE_MODEL(dialog->model));
+ gtk_tree_view_set_rules_hint(GTK_TREE_VIEW(dialog->treeview), TRUE);
+ gtk_container_add(GTK_CONTAINER(sw), dialog->treeview);
+ gtk_widget_show(dialog->treeview);
+
+ selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(dialog->treeview));
+
+ gtk_tree_selection_set_mode(selection, GTK_SELECTION_SINGLE);
+
+ g_signal_connect(G_OBJECT(selection), "changed",
+ G_CALLBACK(selected_cb), dialog);
+
+ add_columns(dialog);
+
+ /*
+ * Catch addressbook selection and populate treeview with the first
+ * addressbook
+ */
+ gevo_addrbooks_model_populate( dialog->addrbooks );
+ g_signal_connect(G_OBJECT(dialog->addrbooks_combo), "changed",
+ G_CALLBACK(addrbook_change_cb), dialog);
+ gtk_combo_box_set_active(GTK_COMBO_BOX(dialog->addrbooks_combo), 0);
+
+ /* Add the expander */
+ expander = gtk_expander_new_with_mnemonic(_("User _details"));
+ gtk_box_pack_start(GTK_BOX(vbox), expander, FALSE, FALSE, 0);
+ gtk_widget_show(expander);
+
+ /*
+ * User details
+ */
+
+ /* Scrolled Window */
+ sw = gtk_scrolled_window_new(0, 0);
+ gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(sw),
+ GTK_POLICY_NEVER,
+ GTK_POLICY_ALWAYS);
+ gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(sw),
+ GTK_SHADOW_IN);
+ gtk_container_add(GTK_CONTAINER(expander), sw);
+ gtk_widget_show(sw);
+
+ /* Textview */
+ dialog->imhtml = gtk_imhtml_new(NULL, NULL);
+ gtk_container_add(GTK_CONTAINER(sw), dialog->imhtml);
+ gtk_widget_show(dialog->imhtml);
+
+ /* Separator. */
+ sep = gtk_hseparator_new();
+ gtk_box_pack_start(GTK_BOX(vbox), sep, FALSE, FALSE, 0);
+ gtk_widget_show(sep);
+
+ /* Button box */
+ bbox = gtk_hbutton_box_new();
+ gtk_box_set_spacing(GTK_BOX(bbox), 6);
+ gtk_button_box_set_layout(GTK_BUTTON_BOX(bbox), GTK_BUTTONBOX_END);
+ gtk_box_pack_end(GTK_BOX(vbox), bbox, FALSE, TRUE, 0);
+ gtk_widget_show(bbox);
+
+ /* "New Person" button */
+ button = pidgin_pixbuf_button_from_stock(_("New Person"), GTK_STOCK_NEW,
+ PIDGIN_BUTTON_HORIZONTAL);
+ gtk_box_pack_start(GTK_BOX(bbox), button, FALSE, FALSE, 0);
+ gtk_widget_show(button);
+
+ g_signal_connect(G_OBJECT(button), "clicked",
+ G_CALLBACK(new_person_cb), dialog);
+
+ /* "Cancel" button */
+ button = gtk_button_new_from_stock(GTK_STOCK_CANCEL);
+ gtk_box_pack_start(GTK_BOX(bbox), button, FALSE, FALSE, 0);
+ gtk_widget_show(button);
+
+ g_signal_connect(G_OBJECT(button), "clicked",
+ G_CALLBACK(cancel_cb), dialog);
+
+ /* "Associate Buddy" button */
+ button = pidgin_pixbuf_button_from_stock(_("_Associate Buddy"),
+ GTK_STOCK_APPLY,
+ PIDGIN_BUTTON_HORIZONTAL);
+ dialog->assoc_button = button;
+ gtk_box_pack_start(GTK_BOX(bbox), button, FALSE, FALSE, 0);
+ gtk_widget_set_sensitive(button, FALSE);
+ gtk_widget_show(button);
+
+ g_signal_connect(G_OBJECT(button), "clicked",
+ G_CALLBACK(assoc_buddy_cb), dialog);
+
+ /* Show it. */
+ gtk_widget_show(dialog->win);
+
+ return dialog;
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/pidgin/plugins/gevolution/eds-utils.c Thu Sep 20 12:01:33 2007 +0000
@@ -0,0 +1,244 @@
+/*
+ * Evolution integration plugin for Purple
+ *
+ * Copyright (C) 2004 Henry Jen.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02111-1301, USA.
+ */
+
+#include "internal.h"
+#include "gtkblist.h"
+#include "pidgin.h"
+#include "gtkutils.h"
+#include "gtkimhtml.h"
+
+#include "debug.h"
+#include "gevolution.h"
+
+GtkTreeModel *
+gevo_addrbooks_model_new()
+{
+ return GTK_TREE_MODEL(gtk_list_store_new(NUM_ADDRBOOK_COLUMNS,
+ G_TYPE_STRING, G_TYPE_STRING));
+}
+
+void
+gevo_addrbooks_model_unref(GtkTreeModel *model)
+{
+ GtkTreeIter iter;
+
+ g_return_if_fail(model != NULL);
+ g_return_if_fail(GTK_IS_LIST_STORE(model));
+
+ if (!gtk_tree_model_get_iter_first(model, &iter))
+ return;
+
+ g_object_unref(model);
+}
+
+void
+gevo_addrbooks_model_populate(GtkTreeModel *model)
+{
+ ESourceList *addressbooks;
+ GError *err;
+ GSList *groups, *g;
+ GtkTreeIter iter;
+ GtkListStore *list;
+
+ g_return_if_fail(model != NULL);
+ g_return_if_fail(GTK_IS_LIST_STORE(model));
+
+ list = GTK_LIST_STORE(model);
+
+ if (!e_book_get_addressbooks(&addressbooks, &err))
+ {
+ purple_debug_error("evolution",
+ "Unable to fetch list of address books.\n");
+
+ gtk_list_store_append(list, &iter);
+ gtk_list_store_set(list, &iter,
+ ADDRBOOK_COLUMN_NAME, _("None"),
+ ADDRBOOK_COLUMN_URI, NULL,
+ -1);
+
+ return;
+ }
+
+ groups = e_source_list_peek_groups(addressbooks);
+
+ if (groups == NULL)
+ {
+ gtk_list_store_append(list, &iter);
+ gtk_list_store_set(list, &iter,
+ ADDRBOOK_COLUMN_NAME, _("None"),
+ ADDRBOOK_COLUMN_URI, NULL,
+ -1);
+
+ return;
+ }
+
+ for (g = groups; g != NULL; g = g->next)
+ {
+ GSList *sources, *s;
+
+ sources = e_source_group_peek_sources(g->data);
+
+ for (s = sources; s != NULL; s = s->next)
+ {
+ ESource *source = E_SOURCE(s->data);
+
+ g_object_ref(source);
+
+ gtk_list_store_append(list, &iter);
+ gtk_list_store_set(list, &iter,
+ ADDRBOOK_COLUMN_NAME, e_source_peek_name(source),
+ ADDRBOOK_COLUMN_URI, e_source_get_uri(source),
+ -1);
+ }
+ }
+
+ g_object_unref(addressbooks);
+}
+
+static EContact *
+gevo_run_query_in_uri(const gchar *uri, EBookQuery *query)
+{
+ EBook *book;
+ gboolean status;
+ GList *cards;
+
+ if (!gevo_load_addressbook(uri, &book, NULL))
+ {
+ purple_debug_error("evolution",
+ "Error retrieving addressbook\n");
+ return NULL;
+ }
+
+ status = e_book_get_contacts(book, query, &cards, NULL);
+ if (!status)
+ {
+ purple_debug_error("evolution", "Error %d in getting card list\n",
+ status);
+ g_object_unref(book);
+ return NULL;
+ }
+ g_object_unref(book);
+
+ if (cards != NULL)
+ {
+ EContact *contact = E_CONTACT(cards->data);
+ GList *cards2 = cards->next;
+
+ if (cards2 != NULL)
+ {
+ /* Break off the first contact and free the rest. */
+ cards->next = NULL;
+ cards2->prev = NULL;
+ g_list_foreach(cards2, (GFunc)g_object_unref, NULL);
+ }
+
+ /* Free the whole list. */
+ g_list_free(cards);
+
+ return contact;
+ }
+
+ return NULL;
+}
+
+/*
+ * Search for a buddy in the Evolution contacts.
+ *
+ * @param buddy The buddy to search for.
+ * @param query An optional query. This function takes ownership of @a query,
+ * so callers must e_book_query_ref() it in advance (to obtain a
+ * second reference) if they want to reuse @a query.
+ */
+EContact *
+gevo_search_buddy_in_contacts(PurpleBuddy *buddy, EBookQuery *query)
+{
+ ESourceList *addressbooks;
+ GError *err;
+ EBookQuery *full_query;
+ GSList *groups, *g;
+ EContact *result;
+ EContactField protocol_field = gevo_prpl_get_field(buddy->account, buddy);
+
+ if (protocol_field == 0)
+ return NULL;
+
+ if (query != NULL)
+ {
+ EBookQuery *queries[2];
+
+ queries[0] = query;
+ queries[1] = e_book_query_field_test(protocol_field, E_BOOK_QUERY_IS, buddy->name);
+ if (queries[1] == NULL)
+ {
+ purple_debug_error("evolution", "Error in creating protocol query\n");
+ e_book_query_unref(query);
+ return NULL;
+ }
+
+ full_query = e_book_query_and(2, queries, TRUE);
+ }
+ else
+ {
+ full_query = e_book_query_field_test(protocol_field, E_BOOK_QUERY_IS, buddy->name);
+ if (full_query == NULL)
+ {
+ purple_debug_error("evolution", "Error in creating protocol query\n");
+ return NULL;
+ }
+ }
+
+ if (!e_book_get_addressbooks(&addressbooks, &err))
+ {
+ purple_debug_error("evolution",
+ "Unable to fetch list of address books.\n");
+ e_book_query_unref(full_query);
+ if (err != NULL)
+ g_error_free(err);
+ return NULL;
+ }
+
+ groups = e_source_list_peek_groups(addressbooks);
+ if (groups == NULL)
+ {
+ g_object_unref(addressbooks);
+ e_book_query_unref(full_query);
+ return NULL;
+ }
+
+ for (g = groups; g != NULL; g = g->next)
+ {
+ GSList *sources, *s;
+ sources = e_source_group_peek_sources(g->data);
+ for (s = sources; s != NULL; s = s->next)
+ {
+ result = gevo_run_query_in_uri(e_source_get_uri(E_SOURCE(s->data)), full_query);
+ if (result != NULL) {
+ g_object_unref(addressbooks);
+ e_book_query_unref(full_query);
+ return result;
+ }
+ }
+ }
+
+ g_object_unref(addressbooks);
+ e_book_query_unref(full_query);
+ return NULL;
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/pidgin/plugins/gevolution/gevo-util.c Thu Sep 20 12:01:33 2007 +0000
@@ -0,0 +1,186 @@
+/*
+ * Evolution integration plugin for Purple
+ *
+ * Copyright (C) 2003 Christian Hammond.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02111-1301, USA.
+ */
+#include "internal.h"
+#include "gtkblist.h"
+#include "pidgin.h"
+#include "gtkutils.h"
+
+#include "gevolution.h"
+
+void
+gevo_add_buddy(PurpleAccount *account, const char *group_name,
+ const char *screenname, const char *alias)
+{
+ PurpleConversation *conv = NULL;
+ PurpleBuddy *buddy;
+ PurpleGroup *group;
+
+ conv = purple_find_conversation_with_account(PURPLE_CONV_TYPE_IM, screenname, account);
+
+ if ((group = purple_find_group(group_name)) == NULL)
+ {
+ group = purple_group_new(group_name);
+ purple_blist_add_group(group, NULL);
+ }
+
+ buddy = purple_buddy_new(account, screenname, alias);
+ purple_blist_add_buddy(buddy, NULL, group, NULL);
+ purple_account_add_buddy(account, buddy);
+
+ if (conv != NULL)
+ {
+ purple_buddy_icon_update(purple_conv_im_get_icon(PURPLE_CONV_IM(conv)));
+ purple_conversation_update(conv, PURPLE_CONV_UPDATE_ADD);
+ }
+}
+
+GList *
+gevo_get_groups(void)
+{
+ static GList *list = NULL;
+ PurpleGroup *g;
+ PurpleBlistNode *gnode;
+
+ g_list_free(list);
+ list = NULL;
+
+ if (purple_get_blist()->root == NULL)
+ {
+ list = g_list_append(list, (gpointer)_("Buddies"));
+ }
+ else
+ {
+ for (gnode = purple_get_blist()->root;
+ gnode != NULL;
+ gnode = gnode->next)
+ {
+ if (PURPLE_BLIST_NODE_IS_GROUP(gnode))
+ {
+ g = (PurpleGroup *)gnode;
+ list = g_list_append(list, g->name);
+ }
+ }
+ }
+
+ return list;
+}
+
+EContactField
+gevo_prpl_get_field(PurpleAccount *account, PurpleBuddy *buddy)
+{
+ EContactField protocol_field = 0;
+ const char *protocol_id;
+
+ g_return_val_if_fail(account != NULL, 0);
+
+ protocol_id = purple_account_get_protocol_id(account);
+
+ if (!strcmp(protocol_id, "prpl-oscar"))
+ {
+ PurpleConnection *gc;
+ PurplePluginProtocolInfo *prpl_info;
+
+ gc = purple_account_get_connection(account);
+
+ prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(gc->prpl);
+
+ if (!strcmp("aim", prpl_info->list_icon(account, buddy)))
+ {
+ protocol_field = E_CONTACT_IM_AIM;
+ }
+ else
+ protocol_field = E_CONTACT_IM_ICQ;
+ }
+ else if (!strcmp(protocol_id, "prpl-msn"))
+ protocol_field = E_CONTACT_IM_MSN;
+ else if (!strcmp(protocol_id, "prpl-yahoo"))
+ protocol_field = E_CONTACT_IM_YAHOO;
+ else if (!strcmp(protocol_id, "prpl-jabber"))
+ protocol_field = E_CONTACT_IM_JABBER;
+ else if (!strcmp(protocol_id, "prpl-novell"))
+ protocol_field = E_CONTACT_IM_GROUPWISE;
+
+ return protocol_field;
+}
+
+gboolean
+gevo_prpl_is_supported(PurpleAccount *account, PurpleBuddy *buddy)
+{
+ return (gevo_prpl_get_field(account, buddy) != 0);
+}
+
+gboolean
+gevo_load_addressbook(const gchar* uri, EBook **book, GError **error)
+{
+ gboolean result = FALSE;
+
+ g_return_val_if_fail(book != NULL, FALSE);
+
+ if (uri == NULL)
+ *book = e_book_new_system_addressbook(NULL);
+ else
+ *book = e_book_new_from_uri(uri, error);
+
+ result = e_book_open(*book, FALSE, NULL);
+
+ if (!result && *book != NULL)
+ {
+ g_object_unref(*book);
+ *book = NULL;
+ }
+
+ return result;
+}
+
+char *
+gevo_get_email_for_buddy(PurpleBuddy *buddy)
+{
+ EContact *contact;
+ char *mail = NULL;
+
+ contact = gevo_search_buddy_in_contacts(buddy, NULL);
+
+ if (contact != NULL)
+ {
+ mail = g_strdup(e_contact_get(contact, E_CONTACT_EMAIL_1));
+ g_object_unref(contact);
+ }
+
+ if (mail == NULL)
+ {
+ PurpleAccount *account = purple_buddy_get_account(buddy);
+ const char *prpl_id = purple_account_get_protocol_id(account);
+
+ if (!strcmp(prpl_id, "prpl-msn"))
+ {
+ mail = g_strdup(purple_normalize(account,
+ purple_buddy_get_name(buddy)));
+ }
+ else if (!strcmp(prpl_id, "prpl-yahoo"))
+ {
+ mail = g_strdup_printf("%s@yahoo.com",
+ purple_normalize(account,
+ purple_buddy_get_name(buddy)));
+ }
+ }
+
+ return mail;
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/pidgin/plugins/gevolution/gevolution.c Thu Sep 20 12:01:33 2007 +0000
@@ -0,0 +1,581 @@
+/*
+ * Evolution integration plugin for Purple
+ *
+ * Copyright (C) 2003 Christian Hammond.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02111-1301, USA.
+ */
+#include "internal.h"
+#include "pidgin.h"
+
+#include "connection.h"
+#include "debug.h"
+#include "prefs.h"
+#include "notify.h"
+#include "signals.h"
+#include "util.h"
+#include "version.h"
+
+#include "gtkblist.h"
+#include "gtkconv.h"
+#include "gtkplugin.h"
+#include "gtkutils.h"
+
+#include "gevolution.h"
+
+#include <libedata-book/Evolution-DataServer-Addressbook.h>
+
+#include <libedata-book/e-data-book-factory.h>
+#include <bonobo/bonobo-main.h>
+
+#include <glib.h>
+
+#define GEVOLUTION_PLUGIN_ID "gtk-x11-gevolution"
+
+#define E_DATA_BOOK_FACTORY_OAF_ID \
+ "OAFIID:GNOME_Evolution_DataServer_BookFactory"
+
+enum
+{
+ COLUMN_AUTOADD,
+ COLUMN_ICON,
+ COLUMN_SCREENNAME,
+ COLUMN_DATA,
+ NUM_COLUMNS
+};
+
+static PurpleBlistUiOps *backup_blist_ui_ops = NULL;
+static PurpleBlistUiOps *blist_ui_ops = NULL;
+static EBook *book = NULL;
+static gulong timer = 0;
+static gulong book_view_tag = 0;
+static EBookView *book_view = NULL;
+
+static void
+update_ims_from_contact(EContact *contact, const char *name,
+ const char *prpl_id, EContactField field)
+{
+ GList *ims = e_contact_get(contact, field);
+ GList *l, *l2;
+
+ if (ims == NULL)
+ return;
+
+ for (l = purple_connections_get_all(); l != NULL; l = l->next)
+ {
+ PurpleConnection *gc = (PurpleConnection *)l->data;
+ PurpleAccount *account = purple_connection_get_account(gc);
+ char *me;
+
+ if (strcmp(purple_account_get_protocol_id(account), prpl_id))
+ continue;
+
+ if (!purple_account_get_bool(account, "gevo-autoadd", FALSE))
+ continue;
+
+ me = g_strdup(purple_normalize(account, purple_account_get_username(account)));
+ for (l2 = ims; l2 != NULL; l2 = l2->next)
+ {
+ if (purple_find_buddy(account, l2->data) != NULL ||
+ !strcmp(me, purple_normalize(account, l2->data)))
+ continue;
+
+ gevo_add_buddy(account, _("Buddies"), l2->data, name);
+ }
+ g_free(me);
+ }
+
+ g_list_foreach(ims, (GFunc)g_free, NULL);
+ g_list_free(ims);
+}
+
+static void
+update_buddies_from_contact(EContact *contact)
+{
+ const char *name;
+
+ name = e_contact_get_const(contact, E_CONTACT_FULL_NAME);
+
+ update_ims_from_contact(contact, name, "prpl-oscar", E_CONTACT_IM_AIM);
+ update_ims_from_contact(contact, name, "prpl-jabber", E_CONTACT_IM_JABBER);
+ update_ims_from_contact(contact, name, "prpl-yahoo", E_CONTACT_IM_YAHOO);
+ update_ims_from_contact(contact, name, "prpl-msn", E_CONTACT_IM_MSN);
+ update_ims_from_contact(contact, name, "prpl-oscar", E_CONTACT_IM_ICQ);
+ update_ims_from_contact(contact, name, "prpl-novell", E_CONTACT_IM_GROUPWISE);
+}
+
+static void
+contacts_changed_cb(EBookView *book_view, GList *contacts)
+{
+ GList *l;
+
+ if (purple_connections_get_all() == NULL)
+ return;
+
+ for (l = contacts; l != NULL; l = l->next)
+ {
+ EContact *contact = (EContact *)l->data;
+
+ update_buddies_from_contact(contact);
+ }
+}
+
+static void
+request_add_buddy(PurpleAccount *account, const char *username,
+ const char *group, const char *alias)
+{
+ if (book == NULL)
+ {
+ backup_blist_ui_ops->request_add_buddy(account, username, group,
+ alias);
+ }
+ else
+ {
+ gevo_add_buddy_dialog_show(account, username, group, alias);
+ }
+}
+
+static void
+got_book_view_cb(EBook *book, EBookStatus status, EBookView *view,
+ gpointer user_data)
+{
+ book_view_tag = 0;
+
+ if (status != E_BOOK_ERROR_OK)
+ {
+ purple_debug_error("evolution", "Unable to retrieve book view! :(\n");
+
+ return;
+ }
+
+ book_view = view;
+
+ g_object_ref(book_view);
+
+ g_signal_connect(G_OBJECT(book_view), "contacts_changed",
+ G_CALLBACK(contacts_changed_cb), book);
+
+ g_signal_connect(G_OBJECT(book_view), "contacts_added",
+ G_CALLBACK(contacts_changed_cb), book);
+
+ e_book_view_start(view);
+}
+
+static void
+signed_on_cb(PurpleConnection *gc)
+{
+ EBookQuery *query;
+ gboolean status;
+ GList *contacts;
+ GList *l;
+
+ if (book == NULL)
+ return;
+
+ query = e_book_query_any_field_contains("");
+
+ status = e_book_get_contacts(book, query, &contacts, NULL);
+
+ e_book_query_unref(query);
+
+ if (!status)
+ return;
+
+ for (l = contacts; l != NULL; l = l->next)
+ {
+ EContact *contact = E_CONTACT(l->data);
+
+ update_buddies_from_contact(contact);
+
+ g_object_unref(contact);
+ }
+
+ g_list_free(contacts);
+}
+
+static void
+menu_item_activate_cb(PurpleBlistNode *node, gpointer user_data)
+{
+ PurpleBuddy *buddy = (PurpleBuddy *)node;
+ gevo_associate_buddy_dialog_new(buddy);
+}
+
+static void
+menu_item_send_mail_activate_cb(PurpleBlistNode *node, gpointer user_data)
+{
+ PurpleBuddy *buddy = (PurpleBuddy *)node;
+ char *mail = NULL;
+
+ mail = gevo_get_email_for_buddy(buddy);
+
+ if (mail != NULL)
+ {
+ char *app = g_find_program_in_path("evolution");
+ if (app != NULL)
+ {
+ char *command_line = g_strdup_printf("%s mailto:%s", app, mail);
+ char *quoted = g_shell_quote(command_line);
+ g_free(app);
+ g_free(mail);
+
+ g_spawn_command_line_async(quoted, NULL);
+ g_free(command_line);
+ g_free(quoted);
+ }
+ else
+ {
+ purple_notify_error(NULL, NULL, _("Unable to send e-mail"),
+ _("The evolution executable was not found in the PATH."));
+ }
+ }
+ else
+ {
+ purple_notify_error(NULL, NULL, _("Unable to send e-mail"),
+ _("An e-mail address was not found for this buddy."));
+ }
+}
+
+static void
+blist_node_extended_menu_cb(PurpleBlistNode *node, GList **menu)
+{
+ PurpleMenuAction *act;
+ PurpleBuddy *buddy;
+ PurpleAccount *account;
+ EContact *contact;
+ char *mail;
+
+ if (!PURPLE_BLIST_NODE_IS_BUDDY(node))
+ return;
+
+ buddy = (PurpleBuddy *)node;
+ account = purple_buddy_get_account(buddy);
+
+ if (!gevo_prpl_is_supported(account, buddy))
+ return;
+
+ contact = gevo_search_buddy_in_contacts(buddy, NULL);
+
+ if (contact == NULL)
+ {
+ act = purple_menu_action_new(_("Add to Address Book"),
+ PURPLE_CALLBACK(menu_item_activate_cb),
+ NULL, NULL);
+ *menu = g_list_append(*menu, act);
+ }
+ else
+ g_object_unref(contact);
+
+ mail = gevo_get_email_for_buddy(buddy);
+
+ if (mail != NULL)
+ {
+ act = purple_menu_action_new(_("Send E-Mail"),
+ PURPLE_CALLBACK(menu_item_send_mail_activate_cb), NULL, NULL);
+ *menu = g_list_append(*menu, act);
+ g_free(mail);
+ }
+}
+
+/* TODO: Something in here leaks 1 reference to a bonobo object! */
+static gboolean
+load_timeout(gpointer data)
+{
+ PurplePlugin *plugin = (PurplePlugin *)data;
+ EBookQuery *query;
+
+ timer = 0;
+
+ /* Maybe this is it? */
+ if (!gevo_load_addressbook(NULL, &book, NULL))
+ return FALSE;
+
+ query = e_book_query_any_field_contains("");
+
+ /* Is it this? */
+ book_view_tag = e_book_async_get_book_view(book, query, NULL, -1,
+ got_book_view_cb, NULL);
+
+ e_book_query_unref(query);
+
+ purple_signal_connect(purple_blist_get_handle(), "blist-node-extended-menu",
+ plugin, PURPLE_CALLBACK(blist_node_extended_menu_cb), NULL);
+
+ return FALSE;
+}
+
+static gboolean
+plugin_load(PurplePlugin *plugin)
+{
+ bonobo_activate();
+
+ backup_blist_ui_ops = purple_blist_get_ui_ops();
+
+ blist_ui_ops = g_memdup(backup_blist_ui_ops, sizeof(PurpleBlistUiOps));
+ blist_ui_ops->request_add_buddy = request_add_buddy;
+
+ purple_blist_set_ui_ops(blist_ui_ops);
+
+ purple_signal_connect(purple_connections_get_handle(), "signed-on",
+ plugin, PURPLE_CALLBACK(signed_on_cb), NULL);
+
+ timer = g_timeout_add(1, load_timeout, plugin);
+
+ return TRUE;
+}
+
+static gboolean
+plugin_unload(PurplePlugin *plugin)
+{
+ purple_blist_set_ui_ops(backup_blist_ui_ops);
+
+ g_free(blist_ui_ops);
+
+ backup_blist_ui_ops = NULL;
+ blist_ui_ops = NULL;
+
+ if (book_view != NULL)
+ {
+ e_book_view_stop(book_view);
+ g_object_unref(book_view);
+ book_view = NULL;
+ }
+
+ if (book != NULL)
+ {
+ g_object_unref(book);
+ book = NULL;
+ }
+
+ return TRUE;
+}
+
+static void
+plugin_destroy(PurplePlugin *plugin)
+{
+ bonobo_debug_shutdown();
+}
+
+static void
+autoadd_toggled_cb(GtkCellRendererToggle *renderer, gchar *path_str,
+ gpointer data)
+{
+ PurpleAccount *account;
+ GtkTreeModel *model = (GtkTreeModel *)data;
+ GtkTreeIter iter;
+ gboolean autoadd;
+
+ gtk_tree_model_get_iter_from_string(model, &iter, path_str);
+ gtk_tree_model_get(model, &iter,
+ COLUMN_DATA, &account,
+ COLUMN_AUTOADD, &autoadd,
+ -1);
+
+ purple_account_set_bool(account, "gevo-autoadd", !autoadd);
+
+ gtk_list_store_set(GTK_LIST_STORE(model), &iter,
+ COLUMN_AUTOADD, !autoadd,
+ -1);
+}
+
+static GtkWidget *
+get_config_frame(PurplePlugin *plugin)
+{
+ GtkWidget *ret;
+ GtkWidget *vbox;
+ GtkWidget *label;
+ GtkWidget *sw;
+ GtkWidget *treeview;
+ GtkTreeViewColumn *column;
+ GtkCellRenderer *renderer;
+ GdkPixbuf *pixbuf;
+ GtkListStore *model;
+ GList *l;
+
+ /* Outside container */
+ ret = gtk_vbox_new(FALSE, 18);
+ gtk_container_set_border_width(GTK_CONTAINER(ret), 12);
+
+ /* Configuration frame */
+ vbox = pidgin_make_frame(ret, _("Evolution Integration Configuration"));
+
+ /* Label */
+ label = gtk_label_new(_("Select all accounts that buddies should be "
+ "auto-added to."));
+ gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5);
+ gtk_box_pack_start(GTK_BOX(vbox), label, FALSE, FALSE, 0);
+ gtk_widget_show(label);
+
+ /* Scrolled window */
+ sw = gtk_scrolled_window_new(0, 0);
+ gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(sw),
+ GTK_POLICY_AUTOMATIC,
+ GTK_POLICY_ALWAYS);
+ gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(sw),
+ GTK_SHADOW_IN);
+ gtk_box_pack_start(GTK_BOX(vbox), sw, TRUE, TRUE, 0);
+ gtk_widget_set_size_request(sw, 300, 300);
+ gtk_widget_show(sw);
+
+ /* Create the list model for the treeview. */
+ model = gtk_list_store_new(NUM_COLUMNS,
+ G_TYPE_BOOLEAN, GDK_TYPE_PIXBUF,
+ G_TYPE_STRING, G_TYPE_POINTER);
+
+ /* Setup the treeview */
+ treeview = gtk_tree_view_new_with_model(GTK_TREE_MODEL(model));
+ gtk_tree_view_set_rules_hint(GTK_TREE_VIEW(treeview), TRUE);
+ gtk_container_add(GTK_CONTAINER(sw), treeview);
+ gtk_widget_show(treeview);
+
+ /* Setup the column */
+ column = gtk_tree_view_column_new();
+ gtk_tree_view_column_set_title(column, _("Account"));
+ gtk_tree_view_insert_column(GTK_TREE_VIEW(treeview), column, -1);
+
+ /* Checkbox */
+ renderer = gtk_cell_renderer_toggle_new();
+
+ g_signal_connect(G_OBJECT(renderer), "toggled",
+ G_CALLBACK(autoadd_toggled_cb), model);
+
+ gtk_tree_view_column_pack_start(column, renderer, FALSE);
+ gtk_tree_view_column_add_attribute(column, renderer,
+ "active", COLUMN_AUTOADD);
+
+ /* Icon */
+ renderer = gtk_cell_renderer_pixbuf_new();
+ gtk_tree_view_column_pack_start(column, renderer, FALSE);
+ gtk_tree_view_column_add_attribute(column, renderer,
+ "pixbuf", COLUMN_ICON);
+
+ /* Screenname */
+ renderer = gtk_cell_renderer_text_new();
+ gtk_tree_view_column_pack_start(column, renderer, TRUE);
+ gtk_tree_view_column_add_attribute(column, renderer,
+ "text", COLUMN_SCREENNAME);
+
+
+ /* Populate */
+ for (l = purple_accounts_get_all(); l != NULL; l = l->next)
+ {
+ PurpleAccount *account = (PurpleAccount *)l->data;
+ GtkTreeIter iter;
+
+ purple_debug_info("evolution", "Adding account\n");
+
+ gtk_list_store_append(model, &iter);
+
+ pixbuf = pidgin_create_prpl_icon(account, 0.5);
+ if ((pixbuf != NULL) && (!purple_account_is_connected(account)))
+ gdk_pixbuf_saturate_and_pixelate(pixbuf, pixbuf, 0.0, FALSE);
+
+ gtk_list_store_set(model, &iter,
+ COLUMN_AUTOADD,
+ purple_account_get_bool(account, "gevo-autoadd",
+ FALSE),
+ COLUMN_ICON, pixbuf,
+ COLUMN_SCREENNAME,
+ purple_account_get_username(account),
+ COLUMN_DATA, account,
+ -1);
+
+ if (pixbuf != NULL)
+ g_object_unref(G_OBJECT(pixbuf));
+ }
+
+ gtk_widget_show_all(ret);
+
+ return ret;
+}
+
+static PidginPluginUiInfo ui_info =
+{
+ get_config_frame, /**< get_config_frame */
+ 0, /**< page_num */
+ /* Padding */
+ NULL,
+ NULL,
+ NULL,
+ NULL
+};
+
+static PurplePluginInfo info =
+{
+ PURPLE_PLUGIN_MAGIC,
+ PURPLE_MAJOR_VERSION,
+ PURPLE_MINOR_VERSION,
+ PURPLE_PLUGIN_STANDARD, /**< type */
+ PIDGIN_PLUGIN_TYPE, /**< ui_requirement */
+ 0, /**< flags */
+ NULL, /**< dependencies */
+ PURPLE_PRIORITY_DEFAULT, /**< priority */
+
+ GEVOLUTION_PLUGIN_ID, /**< id */
+ N_("Evolution Integration"), /**< name */
+ VERSION, /**< version */
+ /** summary */
+ N_("Provides integration with Evolution."),
+ /** description */
+ N_("Provides integration with Evolution."),
+ "Christian Hammond <chipx86@chipx86.com>", /**< author */
+ PURPLE_WEBSITE, /**< homepage */
+
+ plugin_load, /**< load */
+ plugin_unload, /**< unload */
+ plugin_destroy, /**< destroy */
+
+ &ui_info, /**< ui_info */
+ NULL, /**< extra_info */
+ NULL,
+ NULL,
+
+ /* Padding */
+ NULL,
+ NULL,
+ NULL,
+ NULL
+};
+
+static void
+init_plugin(PurplePlugin *plugin)
+{
+ /* TODO: Change to core-remote when possible. */
+ /* info.dependencies = g_list_append(info.dependencies, "gtk-remote"); */
+
+ /*
+ * I'm going to rant a little bit here...
+ *
+ * For some reason, when we init bonobo from inside a plugin, it will
+ * segfault when destroyed. The backtraces are within gmodule somewhere.
+ * There's not much I can do, and I'm not sure where the bug lies.
+ * However, plugins are only destroyed when Purple is shutting down. After
+ * destroying the plugins, purple ends, and anything else is of course
+ * freed. That includes this, if we make the module resident, which
+ * prevents us from being able to actually unload it.
+ *
+ * So, in conclusion, this is an evil hack, but it doesn't harm anything
+ * and it works.
+ */
+ g_module_make_resident(plugin->handle);
+
+ if (!bonobo_init_full(NULL, NULL, bonobo_activation_orb_get(),
+ CORBA_OBJECT_NIL, CORBA_OBJECT_NIL))
+ {
+ purple_debug_error("evolution", "Unable to initialize bonobo.\n");
+ }
+}
+
+PURPLE_INIT_PLUGIN(gevolution, init_plugin, info)
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/pidgin/plugins/gevolution/gevolution.h Thu Sep 20 12:01:33 2007 +0000
@@ -0,0 +1,136 @@
+/*
+ * Evolution integration plugin for Purple
+ *
+ * Copyright (C) 2003 Christian Hammond.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02111-1301, USA.
+ */
+#ifndef _GEVOLUTION_H_
+#define _GEVOLUTION_H_
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <libebook/e-book.h>
+
+enum
+{
+ ADDRBOOK_COLUMN_NAME,
+ ADDRBOOK_COLUMN_URI,
+ NUM_ADDRBOOK_COLUMNS
+};
+
+typedef struct
+{
+ GtkListStore *sources;
+ EBook *active_book;
+ GList *contacts;
+
+} GevoAddrbooksSelector;
+
+typedef struct
+{
+ PurpleAccount *account;
+ char *username;
+
+ EBook *book;
+
+ GtkWidget *win;
+ GtkWidget *treeview;
+ GtkWidget *addrbooks_combo;
+ GtkWidget *search_field;
+ GtkWidget *group_combo;
+ GtkWidget *select_button;
+ GtkWidget *account_optmenu;
+ GtkListStore *model;
+
+ GtkTreeModel *addrbooks;
+ GList *contacts;
+
+} GevoAddBuddyDialog;
+
+typedef struct
+{
+ gboolean person_only;
+
+ PurpleAccount *account;
+ PurpleBuddy *buddy;
+
+ EBook *book;
+ EContact *contact;
+
+ GtkWidget *win;
+ GtkWidget *accounts_menu;
+ GtkWidget *screenname;
+ GtkWidget *firstname;
+ GtkWidget *lastname;
+ GtkWidget *email;
+ GtkWidget *group_combo;
+ GtkWidget *add_button;
+
+ char *buddy_icon;
+
+} GevoNewPersonDialog;
+
+typedef struct
+{
+ PurpleBuddy *buddy;
+
+ EBook *book;
+
+ GtkWidget *win;
+ GtkWidget *treeview;
+ GtkWidget *addrbooks_combo;
+ GtkWidget *search_field;
+ GtkWidget *assoc_button;
+ GtkWidget *imhtml;
+ GtkListStore *model;
+
+ GtkTreeModel *addrbooks;
+ GList *contacts;
+
+} GevoAssociateBuddyDialog;
+
+void gevo_add_buddy_dialog_show(PurpleAccount *account, const char *username,
+ const char *group, const char *alias);
+void gevo_add_buddy_dialog_add_person(GevoAddBuddyDialog *dialog,
+ EContact *contact,
+ const char *name, PurpleAccount *account,
+ const char *screenname);
+
+void gevo_new_person_dialog_show(EBook *book, EContact *contact,
+ PurpleAccount *account, const char *username,
+ const char *group, PurpleBuddy *buddy,
+ gboolean person_only);
+
+void gevo_add_buddy(PurpleAccount *account, const char *group_name,
+ const char *screenname, const char *alias);
+GList *gevo_get_groups(void);
+
+EContactField gevo_prpl_get_field(PurpleAccount *account, PurpleBuddy *buddy);
+gboolean gevo_prpl_is_supported(PurpleAccount *account, PurpleBuddy *buddy);
+gboolean gevo_load_addressbook(const gchar *uri, EBook **book, GError **error);
+char *gevo_get_email_for_buddy(PurpleBuddy *buddy);
+
+GevoAssociateBuddyDialog *gevo_associate_buddy_dialog_new(PurpleBuddy *buddy);
+
+GtkTreeModel *gevo_addrbooks_model_new(void);
+void gevo_addrbooks_model_unref(GtkTreeModel *model);
+void gevo_addrbooks_model_populate(GtkTreeModel *model);
+EContact *gevo_search_buddy_in_contacts(PurpleBuddy *buddy, EBookQuery *query);
+
+#endif /* _GEVOLUTION_H_ */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/pidgin/plugins/gevolution/new_person_dialog.c Thu Sep 20 12:01:33 2007 +0000
@@ -0,0 +1,419 @@
+/*
+ * Evolution integration plugin for Purple
+ *
+ * Copyright (C) 2003 Christian Hammond.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02111-1301, USA.
+ */
+#include "internal.h"
+#include "pidgin.h"
+#include "gtkutils.h"
+
+#include "debug.h"
+
+#include "gevolution.h"
+
+static GtkWidget *
+add_pref_box(GtkSizeGroup *sg, GtkWidget *parent, const char *text,
+ GtkWidget *widget)
+{
+ GtkWidget *hbox;
+ GtkWidget *label;
+
+ hbox = gtk_hbox_new(FALSE, 6);
+ gtk_box_pack_start(GTK_BOX(parent), hbox, FALSE, FALSE, 0);
+ gtk_widget_show(hbox);
+
+ label = gtk_label_new_with_mnemonic(text);
+ gtk_size_group_add_widget(sg, label);
+ gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5);
+ gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0);
+ gtk_widget_show(label);
+
+ gtk_box_pack_start(GTK_BOX(hbox), widget, TRUE, TRUE, 0);
+ gtk_widget_show(widget);
+
+ return hbox;
+}
+
+static gint
+delete_win_cb(GtkWidget *w, GdkEvent *event, GevoNewPersonDialog *dialog)
+{
+ gtk_widget_destroy(dialog->win);
+
+ g_object_unref(dialog->book);
+ g_free(dialog);
+
+ return 0;
+}
+
+static void
+cancel_cb(GtkWidget *w, GevoNewPersonDialog *dialog)
+{
+ delete_win_cb(NULL, NULL, dialog);
+}
+
+static void
+screenname_changed_cb(GtkEntry *entry, GevoNewPersonDialog *dialog)
+{
+ gtk_widget_set_sensitive(dialog->add_button,
+ *gtk_entry_get_text(entry) != '\0');
+}
+
+static void
+person_info_changed_cb(GtkEntry *entry, GevoNewPersonDialog *dialog)
+{
+ gtk_widget_set_sensitive(dialog->add_button,
+ (*gtk_entry_get_text(GTK_ENTRY(dialog->firstname)) != '\0' ||
+ *gtk_entry_get_text(GTK_ENTRY(dialog->lastname)) != '\0'));
+}
+
+static void
+add_cb(GtkWidget *w, GevoNewPersonDialog *dialog)
+{
+ EContact *contact = NULL;
+ const char *screenname;
+ const char *firstname;
+ const char *lastname;
+ const char *email;
+ const char *im_service;
+ gboolean new_contact = FALSE;
+ EContactField field = 0;
+ EContactName *name = NULL;
+ char *full_name = NULL;
+
+ if (dialog->person_only)
+ screenname = dialog->buddy->name;
+ else
+ screenname = gtk_entry_get_text(GTK_ENTRY(dialog->screenname));
+
+ firstname = gtk_entry_get_text(GTK_ENTRY(dialog->firstname));
+ lastname = gtk_entry_get_text(GTK_ENTRY(dialog->lastname));
+ email = gtk_entry_get_text(GTK_ENTRY(dialog->email));
+
+ if (*firstname || *lastname)
+ {
+ if (dialog->contact == NULL)
+ {
+ char *file_as;
+
+ dialog->contact = e_contact_new();
+
+ if (*lastname && *firstname)
+ file_as = g_strdup_printf("%s, %s", lastname, firstname);
+ else if (*lastname)
+ file_as = g_strdup(lastname);
+ else
+ file_as = g_strdup(firstname);
+
+ e_contact_set(dialog->contact, E_CONTACT_FILE_AS, file_as);
+
+ g_free(file_as);
+
+ new_contact = TRUE;
+ }
+
+ contact = dialog->contact;
+
+ name = e_contact_name_new();
+
+ name->given = g_strdup(firstname);
+ name->family = g_strdup(lastname);
+
+ full_name = e_contact_name_to_string(name);
+ e_contact_set(contact, E_CONTACT_FULL_NAME, full_name);
+
+ im_service = purple_account_get_protocol_id(dialog->account);
+
+ if (*email)
+ e_contact_set(contact, E_CONTACT_EMAIL_1, (gpointer)email);
+
+ if (!strcmp(im_service, "prpl-oscar"))
+ {
+ if (isdigit(*screenname))
+ field = E_CONTACT_IM_ICQ;
+ else
+ field = E_CONTACT_IM_AIM;
+ }
+ else if (!strcmp(im_service, "prpl-yahoo"))
+ field = E_CONTACT_IM_YAHOO;
+ else if (!strcmp(im_service, "prpl-jabber"))
+ field = E_CONTACT_IM_JABBER;
+ else if (!strcmp(im_service, "prpl-msn"))
+ field = E_CONTACT_IM_MSN;
+ else if (!strcmp(im_service, "prpl-novell"))
+ field = E_CONTACT_IM_GROUPWISE;
+
+ if (field > 0)
+ {
+ GList *list = g_list_append(NULL, g_strdup(screenname));
+
+ e_contact_set(contact, field, list);
+
+ g_free(list->data);
+ g_list_free(list);
+ }
+
+ if (new_contact)
+ {
+ if (!e_book_add_contact(dialog->book, contact, NULL))
+ {
+ purple_debug_error("evolution", "Error adding contact to book\n");
+
+ g_object_unref(contact);
+ delete_win_cb(NULL, NULL, dialog);
+ return;
+ }
+ }
+ else
+ {
+ if (!e_book_commit_contact(dialog->book, contact, NULL))
+ {
+ purple_debug_error("evolution", "Error adding contact to book\n");
+
+ g_object_unref(contact);
+ delete_win_cb(NULL, NULL, dialog);
+ return;
+ }
+ }
+
+ g_object_unref(contact);
+ }
+
+ if (!dialog->person_only)
+ {
+ const char *group_name;
+
+ group_name = pidgin_text_combo_box_entry_get_text(dialog->group_combo);
+
+ gevo_add_buddy(dialog->account, group_name, screenname, full_name);
+ }
+
+ if (name != NULL)
+ e_contact_name_free(name);
+
+ if (full_name != NULL)
+ g_free(full_name);
+
+ delete_win_cb(NULL, NULL, dialog);
+}
+
+static void
+select_account_cb(GObject *w, PurpleAccount *account,
+ GevoNewPersonDialog *dialog)
+{
+ dialog->account = account;
+}
+
+void
+gevo_new_person_dialog_show(EBook *book, EContact *contact,
+ PurpleAccount *account, const char *username,
+ const char *group, PurpleBuddy *buddy,
+ gboolean person_only)
+{
+ GevoNewPersonDialog *dialog;
+ GtkWidget *vbox, *vbox2;
+ GtkWidget *hbox;
+ GtkWidget *bbox;
+ GtkWidget *label;
+ GtkWidget *button;
+ GtkWidget *sep;
+ GtkSizeGroup *sg, *sg2;
+ const char *str;
+
+ g_return_if_fail(book);
+ g_return_if_fail(!person_only || (person_only && buddy));
+
+ dialog = g_new0(GevoNewPersonDialog, 1);
+
+ dialog->account = account;
+ dialog->person_only = person_only;
+ dialog->buddy = buddy;
+ dialog->book = book;
+ g_object_ref(book);
+
+ dialog->win = pidgin_create_window(_("New Person"), PIDGIN_HIG_BORDER, "new_person", FALSE);
+
+ g_signal_connect(G_OBJECT(dialog->win), "delete_event",
+ G_CALLBACK(delete_win_cb), dialog);
+
+ /* Setup the vbox */
+ vbox = gtk_vbox_new(FALSE, 12);
+ gtk_container_add(GTK_CONTAINER(dialog->win), vbox);
+ gtk_widget_show(vbox);
+
+ /* Label */
+ if (person_only)
+ {
+ label = gtk_label_new(
+ _("Please enter the person's information below."));
+ }
+ else
+ {
+ label = gtk_label_new(_("Please enter the buddy's screen name and "
+ "account type below."));
+ }
+
+ gtk_label_set_line_wrap(GTK_LABEL(label), TRUE);
+ gtk_misc_set_alignment(GTK_MISC(label), 0, 0);
+ gtk_box_pack_start(GTK_BOX(vbox), label, FALSE, TRUE, 0);
+ gtk_widget_show(label);
+
+ /* Setup the size groups */
+ sg = gtk_size_group_new(GTK_SIZE_GROUP_HORIZONTAL);
+ sg2 = gtk_size_group_new(GTK_SIZE_GROUP_HORIZONTAL);
+
+ if (!person_only)
+ {
+ /* Add the account type stuff. */
+ dialog->accounts_menu =
+ pidgin_account_option_menu_new(account, FALSE,
+ G_CALLBACK(select_account_cb),
+ NULL, dialog);
+ add_pref_box(sg, vbox, _("Account type:"), dialog->accounts_menu);
+
+ /* Screen Name */
+ dialog->screenname = gtk_entry_new();
+ add_pref_box(sg, vbox, _("Screen name:"), dialog->screenname);
+
+ if (username != NULL)
+ gtk_entry_set_text(GTK_ENTRY(dialog->screenname), username);
+
+ g_signal_connect(G_OBJECT(dialog->screenname), "changed",
+ G_CALLBACK(screenname_changed_cb), dialog);
+
+ /* Group */
+ dialog->group_combo = pidgin_text_combo_box_entry_new(NULL,
+ gevo_get_groups());
+ add_pref_box(sg, vbox, _("Group:"), dialog->group_combo);
+
+ /* Separator */
+ sep = gtk_hseparator_new();
+ gtk_box_pack_start(GTK_BOX(vbox), sep, FALSE, FALSE, 0);
+ gtk_widget_show(sep);
+
+ /* Optional Information section */
+ label = gtk_label_new(_("Optional information:"));
+ gtk_misc_set_alignment(GTK_MISC(label), 0, 0);
+ gtk_box_pack_start(GTK_BOX(vbox), label, FALSE, FALSE, 0);
+ gtk_widget_show(label);
+ }
+
+ /* Create the parent hbox for this whole thing. */
+ hbox = gtk_hbox_new(FALSE, 12);
+ gtk_box_pack_start(GTK_BOX(vbox), hbox, TRUE, TRUE, 0);
+ gtk_widget_show(hbox);
+
+#if 0
+ /* Now the left side of the hbox */
+ vbox2 = gtk_vbox_new(FALSE, 12);
+ gtk_box_pack_start(GTK_BOX(hbox), vbox2, FALSE, FALSE, 0);
+ gtk_widget_show(vbox2);
+
+ /* Buddy icon button */
+ button = gtk_button_new_from_stock(GTK_STOCK_OPEN);
+ gtk_box_pack_start(GTK_BOX(vbox2), button, FALSE, FALSE, 0);
+ gtk_widget_show(button);
+
+ /* Label */
+ label = gtk_label_new(_("Buddy Icon"));
+ gtk_box_pack_start(GTK_BOX(vbox2), label, FALSE, FALSE, 0);
+ gtk_widget_show(label);
+#endif
+
+ /* Now the right side. */
+ vbox2 = gtk_vbox_new(FALSE, 12);
+ gtk_box_pack_start(GTK_BOX(hbox), vbox2, TRUE, TRUE, 0);
+ gtk_widget_show(vbox2);
+
+ /* First Name field */
+ dialog->firstname = gtk_entry_new();
+ add_pref_box(sg2, vbox2, _("First name:"), dialog->firstname);
+
+ if (contact != NULL)
+ {
+ str = e_contact_get_const(contact, E_CONTACT_GIVEN_NAME);
+
+ if (str != NULL)
+ gtk_entry_set_text(GTK_ENTRY(dialog->firstname), str);
+ }
+
+ /* Last Name field */
+ dialog->lastname = gtk_entry_new();
+ add_pref_box(sg2, vbox2, _("Last name:"), dialog->lastname);
+
+ if (contact != NULL)
+ {
+ str = e_contact_get_const(contact, E_CONTACT_FAMILY_NAME);
+
+ if (str != NULL)
+ gtk_entry_set_text(GTK_ENTRY(dialog->lastname), str);
+ }
+
+ if (person_only)
+ {
+ g_signal_connect(G_OBJECT(dialog->firstname), "changed",
+ G_CALLBACK(person_info_changed_cb), dialog);
+ g_signal_connect(G_OBJECT(dialog->lastname), "changed",
+ G_CALLBACK(person_info_changed_cb), dialog);
+ }
+
+ /* E-Mail address field */
+ dialog->email = gtk_entry_new();
+ add_pref_box(sg2, vbox2, _("E-mail:"), dialog->email);
+
+ if (contact != NULL)
+ {
+ str = e_contact_get_const(contact, E_CONTACT_EMAIL_1);
+
+ if (str != NULL)
+ gtk_entry_set_text(GTK_ENTRY(dialog->email), str);
+ }
+
+ /* Separator */
+ sep = gtk_hseparator_new();
+ gtk_box_pack_start(GTK_BOX(vbox), sep, FALSE, FALSE, 0);
+ gtk_widget_show(sep);
+
+ /* Button box */
+ bbox = gtk_hbutton_box_new();
+ gtk_box_set_spacing(GTK_BOX(bbox), 6);
+ gtk_button_box_set_layout(GTK_BUTTON_BOX(bbox), GTK_BUTTONBOX_END);
+ gtk_box_pack_end(GTK_BOX(vbox), bbox, FALSE, TRUE, 0);
+ gtk_widget_show(bbox);
+
+ /* Cancel button */
+ button = gtk_button_new_from_stock(GTK_STOCK_CANCEL);
+ gtk_box_pack_start(GTK_BOX(bbox), button, FALSE, FALSE, 0);
+ gtk_widget_show(button);
+
+ g_signal_connect(G_OBJECT(button), "clicked",
+ G_CALLBACK(cancel_cb), dialog);
+
+ /* Add button */
+ button = gtk_button_new_from_stock(GTK_STOCK_ADD);
+ dialog->add_button = button;
+ if (username == NULL || *username == '\0')
+ gtk_widget_set_sensitive(button, FALSE);
+ gtk_box_pack_start(GTK_BOX(bbox), button, FALSE, FALSE, 0);
+ gtk_widget_show(button);
+
+ g_signal_connect(G_OBJECT(button), "clicked",
+ G_CALLBACK(add_cb), dialog);
+
+ /* Show it. */
+ gtk_widget_show(dialog->win);
+}