diff options
-rw-r--r-- | plugins/bbdb/bbdb.c | 157 | ||||
-rw-r--r-- | plugins/bbdb/bbdb.h | 11 | ||||
-rw-r--r-- | plugins/bbdb/gaimbuddies.c | 143 |
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); } } |