aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--plugins/bbdb/bbdb.c157
-rw-r--r--plugins/bbdb/bbdb.h11
-rw-r--r--plugins/bbdb/gaimbuddies.c143
3 files changed, 138 insertions, 173 deletions
diff --git a/plugins/bbdb/bbdb.c b/plugins/bbdb/bbdb.c
index 0d9bac96e9..3546a75245 100644
--- a/plugins/bbdb/bbdb.c
+++ b/plugins/bbdb/bbdb.c
@@ -43,12 +43,8 @@ GtkWidget *bbdb_page_factory (EPlugin *ep, EConfigHookItemFactoryData *hook_data
/* For internal use */
struct bbdb_stuff {
- EABConfigTargetPrefs *target;
-
GtkWidget *combo_box;
GtkWidget *gaim_combo_box;
- GtkWidget *check;
- GtkWidget *check_gaim;
};
/* Static forward declarations */
@@ -112,8 +108,7 @@ bbdb_timeout (gpointer data)
return data == NULL;
}
-typedef struct
-{
+typedef struct {
gchar *name;
gchar *email;
} todo_struct;
@@ -128,51 +123,55 @@ free_todo_struct (todo_struct *td)
}
}
-static GSList *todo = NULL;
+static GQueue todo = G_QUEUE_INIT;
G_LOCK_DEFINE_STATIC (todo);
-static gpointer
-bbdb_do_in_thread (gpointer data)
+static void
+todo_queue_clear (void)
{
- EBookClient *client = data;
-
- /* Open the addressbook */
- if (client == NULL) {
- G_LOCK (todo);
-
- g_slist_foreach (todo, (GFunc) free_todo_struct, NULL);
- g_slist_free (todo);
- todo = NULL;
+ G_LOCK (todo);
+ while (!g_queue_is_empty (&todo))
+ free_todo_struct (g_queue_pop_head (&todo));
+ G_UNLOCK (todo);
+}
- G_UNLOCK (todo);
- return NULL;
- }
+static todo_struct *
+todo_queue_pop (void)
+{
+ todo_struct *td;
G_LOCK (todo);
- while (todo) {
- todo_struct *td = todo->data;
+ td = g_queue_pop_head (&todo);
+ G_UNLOCK (todo);
- todo = g_slist_remove (todo, td);
+ return td;
+}
+
+static gpointer
+todo_queue_process_thread (gpointer data)
+{
+ EBookClient *client = data;
- G_UNLOCK (todo);
+ if (client != NULL) {
+ todo_struct *td;
- if (td) {
+ while ((td = todo_queue_pop ()) != NULL) {
bbdb_do_it (client, td->name, td->email);
free_todo_struct (td);
}
- G_LOCK (todo);
- }
- G_UNLOCK (todo);
+ g_object_unref (client);
- g_object_unref (client);
+ } else {
+ todo_queue_clear ();
+ }
return NULL;
}
static void
-bbdb_do_thread (const gchar *name,
- const gchar *email)
+todo_queue_process (const gchar *name,
+ const gchar *email)
{
todo_struct *td;
@@ -184,68 +183,44 @@ bbdb_do_thread (const gchar *name,
td->email = g_strdup (email);
G_LOCK (todo);
- if (todo) {
- /* the list isn't empty, which means there is a thread taking
- * care of that, thus just add it to the queue */
- todo = g_slist_append (todo, td);
- } else {
- GThread *thread;
- GError *error = NULL;
- EBookClient *client = bbdb_create_book_client (AUTOMATIC_CONTACTS_ADDRESSBOOK);
- /* list was empty, add item and create a thread */
- todo = g_slist_append (todo, td);
- thread = g_thread_try_new (NULL, bbdb_do_in_thread, client, &error);
+ g_queue_push_tail (&todo, td);
- if (error) {
- g_warning ("%s: Creation of the thread failed with error: %s", G_STRFUNC, error->message);
- g_error_free (error);
+ if (g_queue_get_length (&todo) == 1) {
+ GThread *thread;
+ EBookClient *client;
- G_UNLOCK (todo);
- bbdb_do_in_thread (client);
- G_LOCK (todo);
- } else {
- g_thread_unref (thread);
- }
+ client = bbdb_create_book_client (AUTOMATIC_CONTACTS_ADDRESSBOOK);
+ thread = g_thread_new (NULL, todo_queue_process_thread, client);
+ g_thread_unref (thread);
}
G_UNLOCK (todo);
}
static void
-walk_destinations_and_free (EDestination **dests)
+handle_destination (EDestination *destination)
{
- const gchar *name, *addr;
- gint i;
-
- if (!dests)
- return;
+ g_return_if_fail (destination != NULL);
- for (i = 0; dests[i] != NULL; i++) {
- if (e_destination_is_evolution_list (dests[i])) {
- const GList *members;
+ if (e_destination_is_evolution_list (destination)) {
+ GList *list, *link;
- for (members = e_destination_list_get_dests (dests[i]); members; members = members->next) {
- const EDestination *member = members->data;
+ /* XXX e_destination_list_get_dests() misuses const. */
+ list = (GList *) e_destination_list_get_dests (destination);
- if (!member)
- continue;
+ for (link = list; link != NULL; link = g_list_next (link))
+ handle_destination (E_DESTINATION (link->data));
- name = e_destination_get_name (member);
- addr = e_destination_get_email (member);
+ } else {
+ const gchar *name;
+ const gchar *email;
- if (name || addr)
- bbdb_do_thread (name, addr);
- }
- } else {
- name = e_destination_get_name (dests[i]);
- addr = e_destination_get_email (dests[i]);
+ name = e_destination_get_name (destination);
+ email = e_destination_get_email (destination);
- if (name || addr)
- bbdb_do_thread (name, addr);
- }
+ if (name != NULL || email != NULL)
+ todo_queue_process (name, email);
}
-
- e_destination_freev (dests);
}
void
@@ -253,6 +228,7 @@ bbdb_handle_send (EPlugin *ep,
EMEventTargetComposer *target)
{
EComposerHeaderTable *table;
+ EDestination **destinations;
GSettings *settings;
gboolean enable;
@@ -264,11 +240,26 @@ bbdb_handle_send (EPlugin *ep,
return;
table = e_msg_composer_get_header_table (target->composer);
- g_return_if_fail (table);
/* read information from the composer, not from a generated message */
- walk_destinations_and_free (e_composer_header_table_get_destinations_to (table));
- walk_destinations_and_free (e_composer_header_table_get_destinations_cc (table));
+
+ destinations = e_composer_header_table_get_destinations_to (table);
+ if (destinations != NULL) {
+ gint ii;
+
+ for (ii = 0; destinations[ii] != NULL; ii++)
+ handle_destination (destinations[ii]);
+ e_destination_freev (destinations);
+ }
+
+ destinations = e_composer_header_table_get_destinations_cc (table);
+ if (destinations != NULL) {
+ gint ii;
+
+ for (ii = 0; destinations[ii] != NULL; ii++)
+ handle_destination (destinations[ii]);
+ e_destination_freev (destinations);
+ }
}
static void
@@ -610,7 +601,6 @@ bbdb_page_factory (EPlugin *ep,
EConfigHookItemFactoryData *hook_data)
{
struct bbdb_stuff *stuff;
- EABConfigTargetPrefs *target = (EABConfigTargetPrefs *) hook_data->config->target;
GtkWidget *page;
GtkWidget *tab_label;
GtkWidget *frame;
@@ -630,7 +620,6 @@ bbdb_page_factory (EPlugin *ep,
/* A structure to pass some stuff around */
stuff = g_new0 (struct bbdb_stuff, 1);
- stuff->target = target;
/* Create a new notebook page */
page = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
@@ -665,7 +654,6 @@ bbdb_page_factory (EPlugin *ep,
check, "toggled",
G_CALLBACK (enable_toggled_cb), stuff);
gtk_box_pack_start (GTK_BOX (inner_vbox), check, FALSE, FALSE, 0);
- stuff->check = check;
label = gtk_label_new (_("Select Address book for Automatic Contacts"));
gtk_box_pack_start (GTK_BOX (inner_vbox), label, FALSE, FALSE, 0);
@@ -705,7 +693,6 @@ bbdb_page_factory (EPlugin *ep,
check_gaim, "toggled",
G_CALLBACK (enable_gaim_toggled_cb), stuff);
gtk_box_pack_start (GTK_BOX (inner_vbox), check_gaim, FALSE, FALSE, 0);
- stuff->check_gaim = check_gaim;
gaim_label = gtk_label_new (_("Select Address book for Pidgin buddy list"));
gtk_box_pack_start (GTK_BOX (inner_vbox), gaim_label, FALSE, FALSE, 0);
diff --git a/plugins/bbdb/bbdb.h b/plugins/bbdb/bbdb.h
index 6759921192..045f80c615 100644
--- a/plugins/bbdb/bbdb.h
+++ b/plugins/bbdb/bbdb.h
@@ -40,14 +40,11 @@
#include <libebook/libebook.h>
/* bbdb.c */
-/* creates an EBookClient for a given type (gaim or contacts), but doesn't open it;
- * this function should be called in a main thread. */
-EBookClient *bbdb_create_book_client (gint type);
-
-gboolean bbdb_check_gaim_enabled (void);
+EBookClient * bbdb_create_book_client (gint type);
+gboolean bbdb_check_gaim_enabled (void);
/* gaimbuddies.c */
-void bbdb_sync_buddy_list (void);
-void bbdb_sync_buddy_list_check (void);
+void bbdb_sync_buddy_list (void);
+void bbdb_sync_buddy_list_check (void);
#endif /* __BBDB_H__ */
diff --git a/plugins/bbdb/gaimbuddies.c b/plugins/bbdb/gaimbuddies.c
index 9ef3db263b..7951210996 100644
--- a/plugins/bbdb/gaimbuddies.c
+++ b/plugins/bbdb/gaimbuddies.c
@@ -59,16 +59,27 @@ typedef struct {
static gboolean bbdb_merge_buddy_to_contact (EBookClient *client,
GaimBuddy *buddy,
EContact *contact);
-static GList * bbdb_get_gaim_buddy_list (void);
+static void bbdb_get_gaim_buddy_list (GQueue *out_buddies);
static gchar * get_node_text (xmlNodePtr node);
static gchar * get_buddy_icon_from_setting (xmlNodePtr setting);
-static void free_buddy_list (GList *blist);
static void parse_buddy_group (xmlNodePtr group,
- GList **buddies,
+ GQueue *out_buddies,
GSList *blocked);
static EContactField
proto_to_contact_field (const gchar *proto);
+static void
+free_gaim_body (GaimBuddy *gb)
+{
+ if (gb != NULL) {
+ g_free (gb->icon);
+ g_free (gb->alias);
+ g_free (gb->account_name);
+ g_free (gb->proto);
+ g_free (gb);
+ }
+}
+
static gchar *
get_buddy_filename (void)
{
@@ -185,24 +196,27 @@ store_last_sync_idle_cb (gpointer data)
static gboolean syncing = FALSE;
G_LOCK_DEFINE_STATIC (syncing);
-struct sync_thread_data
-{
- GList *blist;
+struct sync_thread_data {
+ GQueue *buddies;
EBookClient *client;
};
static gpointer
bbdb_sync_buddy_list_in_thread (gpointer data)
{
- GList *l;
struct sync_thread_data *std = data;
+ GList *head, *link;
g_return_val_if_fail (std != NULL, NULL);
printf ("bbdb: Synchronizing buddy list to contacts...\n");
+
/* Walk the buddy list */
- for (l = std->blist; l != NULL; l = l->next) {
- GaimBuddy *b = l->data;
+
+ head = g_queue_peek_head_link (std->buddies);
+
+ for (link = head; link != NULL; link = g_list_next (link)) {
+ GaimBuddy *b = link->data;
EBookQuery *query;
gchar *query_string, *uid;
GSList *contacts = NULL;
@@ -272,7 +286,7 @@ bbdb_sync_buddy_list_in_thread (gpointer data)
if (!e_book_client_add_contact_sync (std->client, c, &uid, NULL, &error)) {
g_warning ("bbdb: Failed to add new contact: %s", error->message);
g_error_free (error);
- goto finish;
+ goto exit;
}
g_object_unref (c);
@@ -281,11 +295,11 @@ bbdb_sync_buddy_list_in_thread (gpointer data)
g_idle_add (store_last_sync_idle_cb, NULL);
- finish:
+exit:
printf ("bbdb: Done syncing buddy list to contacts.\n");
g_object_unref (std->client);
- free_buddy_list (std->blist);
+ g_queue_free_full (std->buddies, (GDestroyNotify) free_gaim_body);
g_free (std);
G_LOCK (syncing);
@@ -298,11 +312,7 @@ bbdb_sync_buddy_list_in_thread (gpointer data)
void
bbdb_sync_buddy_list (void)
{
- GList *blist;
- GThread *thread;
- GError *error = NULL;
- EBookClient *client = NULL;
- struct sync_thread_data *std;
+ GQueue *buddies;
G_LOCK (syncing);
if (syncing) {
@@ -311,39 +321,33 @@ bbdb_sync_buddy_list (void)
return;
}
- /* Get the Gaim buddy list */
- blist = bbdb_get_gaim_buddy_list ();
- if (blist == NULL) {
- G_UNLOCK (syncing);
- return;
- }
-
- /* Open the addressbook */
- client = bbdb_create_book_client (GAIM_ADDRESSBOOK);
- if (client == NULL) {
- free_buddy_list (blist);
- G_UNLOCK (syncing);
- return;
- }
-
- std = g_new0 (struct sync_thread_data, 1);
- std->blist = blist;
- std->client = client;
-
- syncing = TRUE;
+ buddies = g_queue_new ();
+ bbdb_get_gaim_buddy_list (buddies);
- thread = g_thread_try_new (NULL, bbdb_sync_buddy_list_in_thread, std, &error);
- if (error) {
- g_warning (
- "%s: Creation of the thread failed with error: %s",
- G_STRFUNC, error->message);
- g_error_free (error);
-
- G_UNLOCK (syncing);
- bbdb_sync_buddy_list_in_thread (std);
- G_LOCK (syncing);
+ if (g_queue_is_empty (buddies)) {
+ g_queue_free (buddies);
} else {
- g_thread_unref (thread);
+ GThread *thread;
+ EBookClient *client;
+
+ /* Open the addressbook */
+ client = bbdb_create_book_client (GAIM_ADDRESSBOOK);
+ if (client != NULL) {
+ struct sync_thread_data *std;
+
+ std = g_new0 (struct sync_thread_data, 1);
+ std->buddies = buddies;
+ std->client = client;
+
+ syncing = TRUE;
+
+ thread = g_thread_new (
+ NULL, bbdb_sync_buddy_list_in_thread, std);
+ g_thread_unref (thread);
+ } else {
+ g_queue_free_full (
+ buddies, (GDestroyNotify) free_gaim_body);
+ }
}
G_UNLOCK (syncing);
@@ -466,13 +470,12 @@ get_all_blocked (xmlNodePtr node,
}
}
-static GList *
-bbdb_get_gaim_buddy_list (void)
+static void
+bbdb_get_gaim_buddy_list (GQueue *out_buddies)
{
gchar *blist_path;
xmlDocPtr buddy_xml;
xmlNodePtr root, child, blist;
- GList *buddies = NULL;
GSList *blocked = NULL;
blist_path = get_buddy_filename ();
@@ -481,14 +484,14 @@ bbdb_get_gaim_buddy_list (void)
g_free (blist_path);
if (!buddy_xml) {
fprintf (stderr, "bbdb: Could not open Pidgin buddy list.\n");
- return NULL;
+ return;
}
root = xmlDocGetRootElement (buddy_xml);
if (strcmp ((const gchar *) root->name, "purple")) {
fprintf (stderr, "bbdb: Could not parse Pidgin buddy list.\n");
xmlFreeDoc (buddy_xml);
- return NULL;
+ return;
}
for (child = root->children; child != NULL; child = child->next) {
@@ -510,40 +513,18 @@ bbdb_get_gaim_buddy_list (void)
stderr, "bbdb: Could not find 'blist' "
"element in Pidgin buddy list.\n");
xmlFreeDoc (buddy_xml);
- return NULL;
+ return;
}
for (child = blist->children; child != NULL; child = child->next) {
if (!strcmp ((const gchar *) child->name, "group"))
- parse_buddy_group (child, &buddies, blocked);
+ parse_buddy_group (child, out_buddies, blocked);
}
xmlFreeDoc (buddy_xml);
g_slist_foreach (blocked, (GFunc) g_free, NULL);
g_slist_free (blocked);
-
- return buddies;
-}
-
-static void
-free_gaim_body (GaimBuddy *gb)
-{
- if (!gb)
- return;
-
- g_free (gb->icon);
- g_free (gb->alias);
- g_free (gb->account_name);
- g_free (gb->proto);
- g_free (gb);
-}
-
-static void
-free_buddy_list (GList *blist)
-{
- g_list_foreach (blist, (GFunc) free_gaim_body, NULL);
- g_list_free (blist);
}
static gchar *
@@ -575,7 +556,7 @@ get_buddy_icon_from_setting (xmlNodePtr setting)
static void
parse_contact (xmlNodePtr contact,
- GList **buddies,
+ GQueue *out_buddies,
GSList *blocked)
{
xmlNodePtr child;
@@ -625,12 +606,12 @@ parse_contact (xmlNodePtr contact,
if (is_blocked)
free_gaim_body (gb);
else
- *buddies = g_list_prepend (*buddies, gb);
+ g_queue_push_tail (out_buddies, gb);
}
static void
parse_buddy_group (xmlNodePtr group,
- GList **buddies,
+ GQueue *out_buddies,
GSList *blocked)
{
xmlNodePtr child;
@@ -639,6 +620,6 @@ parse_buddy_group (xmlNodePtr group,
if (strcmp ((const gchar *) child->name, "contact"))
continue;
- parse_contact (child, buddies, blocked);
+ parse_contact (child, out_buddies, blocked);
}
}