#include <libedataserverui/e-book-auth-util.h>
#include "e-name-selector.h"
-#define PRIVATE_SOURCE_BOOKS_KEY "private-source-books"
-
typedef struct {
gchar *name;
ENameSelectorEntry *entry;
}
SourceBook;
+typedef struct _ENameSelectorPrivate ENameSelectorPrivate;
+
+struct _ENameSelectorPrivate {
+ GThread *load_book_thread;
+ gboolean load_cancelled;
+ GArray *source_books;
+};
+
+#define E_NAME_SELECTOR_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), E_TYPE_NAME_SELECTOR, ENameSelectorPrivate))
+
static void e_name_selector_finalize (GObject *object);
/* ------------------ *
G_DEFINE_TYPE (ENameSelector, e_name_selector, G_TYPE_OBJECT)
-static void
-source_books_destroy (GArray *source_books)
-{
- gint i;
-
- for (i = 0; i < source_books->len; i++) {
- SourceBook *source_book = &g_array_index (source_books, SourceBook, i);
-
- g_object_unref (source_book->book);
- }
-
- g_array_free (source_books, TRUE);
-}
-
-static void
-e_name_selector_class_init (ENameSelectorClass *name_selector_class)
-{
- GObjectClass *object_class;
-
- object_class = G_OBJECT_CLASS (name_selector_class);
-
- object_class->finalize = e_name_selector_finalize;
-}
-
-static void
-e_name_selector_init (ENameSelector *name_selector)
+static gpointer
+load_books_thread (gpointer user_data)
{
+ ENameSelector *name_selector = user_data;
+ ENameSelectorPrivate *priv;
ESourceList *source_list;
- GArray *source_books;
GSList *groups;
GSList *l;
- name_selector->sections = g_array_new (FALSE, FALSE, sizeof (Section));
- name_selector->model = e_name_selector_model_new ();
-
- /* Make a list of books */
+ /* XXX This thread is necessary because the e_book_new can block.
+ See gnome's bug #540779 for more information. */
- source_books = g_array_new (FALSE, FALSE, sizeof (SourceBook));
+ g_return_val_if_fail (name_selector != NULL, NULL);
- /* This should be a private field, but we use g_object_set_data() to maintain
- * ABI compatibility in the GNOME 2.10 branch */
- g_object_set_data_full (G_OBJECT (name_selector), PRIVATE_SOURCE_BOOKS_KEY, source_books,
- (GDestroyNotify) source_books_destroy);
+ priv = E_NAME_SELECTOR_GET_PRIVATE (name_selector);
if (!e_book_get_addressbooks (&source_list, NULL)) {
g_warning ("ENameSelector can't find any addressbooks!");
- return;
+ return NULL;
}
groups = e_source_list_peek_groups (source_list);
- for (l = groups; l; l = g_slist_next (l)) {
+ for (l = groups; l && !priv->load_cancelled; l = g_slist_next (l)) {
ESourceGroup *group = l->data;
GSList *sources = e_source_group_peek_sources (group);
GSList *m;
- for (m = sources; m; m = g_slist_next (m)) {
+ for (m = sources; m && !priv->load_cancelled; m = g_slist_next (m)) {
ESource *source = m->data;
const gchar *completion;
SourceBook source_book;
source_book.is_completion_book = TRUE;
- g_array_append_val (source_books, source_book);
+ g_array_append_val (priv->source_books, source_book);
+
+ if (!priv->load_cancelled) {
+ EContactStore *store;
+
+ if (name_selector->model) {
+ store = e_name_selector_model_peek_contact_store (name_selector->model);
+ if (store)
+ e_contact_store_add_book (store, source_book.book);
+ }
+
+ if (name_selector->sections) {
+ gint j;
+
+ for (j = 0; j < name_selector->sections->len && !priv->load_cancelled; j++) {
+ Section *section = &g_array_index (name_selector->sections, Section, j);
+
+ if (section->entry) {
+ store = e_name_selector_entry_peek_contact_store (section->entry);
+ if (store)
+ e_contact_store_add_book (store, source_book.book);
+ }
+ }
+ }
+ }
}
}
g_object_unref (source_list);
+
+ return NULL;
+}
+
+static void
+e_name_selector_class_init (ENameSelectorClass *name_selector_class)
+{
+ GObjectClass *object_class;
+
+ object_class = G_OBJECT_CLASS (name_selector_class);
+
+ object_class->finalize = e_name_selector_finalize;
+
+ g_type_class_add_private (name_selector_class, sizeof (ENameSelectorPrivate));
+}
+
+static void
+e_name_selector_init (ENameSelector *name_selector)
+{
+ ENameSelectorPrivate *priv;
+
+ priv = E_NAME_SELECTOR_GET_PRIVATE (name_selector);
+
+ name_selector->sections = g_array_new (FALSE, FALSE, sizeof (Section));
+ name_selector->model = e_name_selector_model_new ();
+
+ priv->source_books = g_array_new (FALSE, FALSE, sizeof (SourceBook));
+ priv->load_cancelled = FALSE;
+ priv->load_book_thread = g_thread_create (load_books_thread, name_selector, TRUE, NULL);
}
static void
e_name_selector_finalize (GObject *object)
{
+ ENameSelectorPrivate *priv;
+
+ priv = E_NAME_SELECTOR_GET_PRIVATE (object);
+
+ if (priv->load_book_thread) {
+ priv->load_cancelled = TRUE;
+ g_thread_join (priv->load_book_thread);
+ priv->load_book_thread = NULL;
+ }
+
+ if (priv->source_books) {
+ gint i;
+
+ for (i = 0; i < priv->source_books->len; i++) {
+ SourceBook *source_book = &g_array_index (priv->source_books, SourceBook, i);
+
+ if (source_book->book)
+ g_object_unref (source_book->book);
+ }
+
+ g_array_free (priv->source_books, TRUE);
+ priv->source_books = NULL;
+ }
+
if (G_OBJECT_CLASS (e_name_selector_parent_class)->finalize)
G_OBJECT_CLASS (e_name_selector_parent_class)->finalize (object);
}
ENameSelectorEntry *
e_name_selector_peek_section_entry (ENameSelector *name_selector, const gchar *name)
{
+ ENameSelectorPrivate *priv;
EDestinationStore *destination_store;
Section *section;
gint n;
g_return_val_if_fail (E_IS_NAME_SELECTOR (name_selector), NULL);
g_return_val_if_fail (name != NULL, NULL);
+ priv = E_NAME_SELECTOR_GET_PRIVATE (name_selector);
+
if (!e_name_selector_model_peek_section (name_selector->model, name,
NULL, &destination_store))
return NULL;
section = &g_array_index (name_selector->sections, Section, n);
if (!section->entry) {
- GArray *source_books;
EContactStore *contact_store;
gchar *text;
gint i;
/* Create a contact store for the entry and assign our already-open books to it */
contact_store = e_contact_store_new ();
- source_books = g_object_get_data (G_OBJECT (name_selector), PRIVATE_SOURCE_BOOKS_KEY);
- for (i = 0; i < source_books->len; i++) {
- SourceBook *source_book = &g_array_index (source_books, SourceBook, i);
+ for (i = 0; i < priv->source_books->len; i++) {
+ SourceBook *source_book = &g_array_index (priv->source_books, SourceBook, i);
- if (source_book->is_completion_book)
+ if (source_book->is_completion_book && source_book->book)
e_contact_store_add_book (contact_store, source_book->book);
}
ENameSelectorList *
e_name_selector_peek_section_list (ENameSelector *name_selector, const gchar *name)
{
+ ENameSelectorPrivate *priv;
EDestinationStore *destination_store;
Section *section;
gint n;
g_return_val_if_fail (E_IS_NAME_SELECTOR (name_selector), NULL);
g_return_val_if_fail (name != NULL, NULL);
+ priv = E_NAME_SELECTOR_GET_PRIVATE (name_selector);
+
if (!e_name_selector_model_peek_section (name_selector->model, name,
NULL, &destination_store))
return NULL;
section = &g_array_index (name_selector->sections, Section, n);
if (!section->entry) {
- GArray *source_books;
EContactStore *contact_store;
gchar *text;
gint i;
&text, NULL, NULL)) {
atk_object_set_name (gtk_widget_get_accessible (GTK_WIDGET (section->entry)), text);
g_free (text);
- }
+ }
e_name_selector_entry_set_destination_store (section->entry, destination_store);
/* Create a contact store for the entry and assign our already-open books to it */
contact_store = e_contact_store_new ();
- source_books = g_object_get_data (G_OBJECT (name_selector), PRIVATE_SOURCE_BOOKS_KEY);
-
- for (i = 0; i < source_books->len; i++) {
- SourceBook *source_book = &g_array_index (source_books, SourceBook, i);
+ for (i = 0; i < priv->source_books->len; i++) {
+ SourceBook *source_book = &g_array_index (priv->source_books, SourceBook, i);
- if (source_book->is_completion_book)
+ if (source_book->is_completion_book && source_book->book)
e_contact_store_add_book (contact_store, source_book->book);
}