aboutsummaryrefslogtreecommitdiffstats
path: root/addressbook/gui/widgets/e-addressbook-model.c
diff options
context:
space:
mode:
Diffstat (limited to 'addressbook/gui/widgets/e-addressbook-model.c')
-rw-r--r--addressbook/gui/widgets/e-addressbook-model.c1306
1 files changed, 829 insertions, 477 deletions
diff --git a/addressbook/gui/widgets/e-addressbook-model.c b/addressbook/gui/widgets/e-addressbook-model.c
index 9244df8a38..683eed3499 100644
--- a/addressbook/gui/widgets/e-addressbook-model.c
+++ b/addressbook/gui/widgets/e-addressbook-model.c
@@ -1,641 +1,993 @@
-/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) version 3.
*
- * Author:
- * Christopher James Lahey <clahey@ximian.com>
+ * 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with the program; if not, see <http://www.gnu.org/licenses/>
+ *
+ *
+ * Authors:
+ * Christopher James Lahey <clahey@ximian.com>
+ *
+ * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
*
- * (C) 1999 Ximian, Inc.
*/
+#ifdef HAVE_CONFIG_H
#include <config.h>
-#include "e-addressbook-model.h"
-#include <gnome-xml/tree.h>
-#include <gnome-xml/parser.h>
-#include <gnome-xml/xmlmemory.h>
-#include <gnome.h>
-#include <gal/widgets/e-gui-utils.h>
-#include "e-addressbook-util.h"
-
-#define PARENT_TYPE gtk_object_get_type()
-GtkObjectClass *parent_class;
-
-/*
- * EAddressbookModel callbacks
- * These are the callbacks that define the behavior of our custom model.
- */
-static void e_addressbook_model_set_arg (GtkObject *o, GtkArg *arg, guint arg_id);
-static void e_addressbook_model_get_arg (GtkObject *object, GtkArg *arg, guint arg_id);
+#endif
+#include <string.h>
+#include <glib/gi18n.h>
+#include "e-addressbook-model.h"
+#include <e-util/e-marshal.h>
+#include <e-util/e-util.h>
+#include "eab-gui-util.h"
+
+#define E_ADDRESSBOOK_MODEL_GET_PRIVATE(obj) \
+ (G_TYPE_INSTANCE_GET_PRIVATE \
+ ((obj), E_TYPE_ADDRESSBOOK_MODEL, EAddressbookModelPrivate))
+
+struct _EAddressbookModelPrivate {
+ EClientCache *client_cache;
+ gulong client_notify_readonly_handler_id;
+
+ EBookClient *book_client;
+ gchar *query_str;
+ EBookClientView *client_view;
+ guint client_view_idle_id;
+
+ /* Query Results */
+ GPtrArray *contacts;
+
+ /* Signal Handler IDs */
+ gulong create_contact_id;
+ gulong remove_contact_id;
+ gulong modify_contact_id;
+ gulong status_message_id;
+ gulong view_complete_id;
+ guint remove_status_id;
+
+ guint search_in_progress : 1;
+ guint editable : 1;
+ guint first_get_view : 1;
+};
enum {
- ARG_0,
- ARG_BOOK,
- ARG_QUERY,
- ARG_EDITABLE,
+ PROP_0,
+ PROP_CLIENT,
+ PROP_CLIENT_CACHE,
+ PROP_EDITABLE,
+ PROP_QUERY
};
enum {
WRITABLE_STATUS,
STATUS_MESSAGE,
+ SEARCH_STARTED,
SEARCH_RESULT,
FOLDER_BAR_MESSAGE,
- CARD_ADDED,
- CARD_REMOVED,
- CARD_CHANGED,
+ CONTACT_ADDED,
+ CONTACTS_REMOVED,
+ CONTACT_CHANGED,
MODEL_CHANGED,
STOP_STATE_CHANGED,
- BACKEND_DIED,
LAST_SIGNAL
};
-#define COLS (E_CARD_SIMPLE_FIELD_LAST)
+static guint signals[LAST_SIGNAL];
-static guint e_addressbook_model_signals [LAST_SIGNAL] = {0, };
+G_DEFINE_TYPE (EAddressbookModel, e_addressbook_model, G_TYPE_OBJECT)
static void
free_data (EAddressbookModel *model)
{
- int i;
-
- for ( i = 0; i < model->data_count; i++ ) {
- gtk_object_unref(GTK_OBJECT(model->data[i]));
- }
+ GPtrArray *array;
- g_free(model->data);
- model->data = NULL;
- model->data_count = 0;
- model->allocated_count = 0;
+ array = model->priv->contacts;
+ g_ptr_array_foreach (array, (GFunc) g_object_unref, NULL);
+ g_ptr_array_set_size (array, 0);
}
static void
-remove_book_view(EAddressbookModel *model)
-{
- if (model->book_view && model->create_card_id)
- gtk_signal_disconnect(GTK_OBJECT (model->book_view),
- model->create_card_id);
- if (model->book_view && model->remove_card_id)
- gtk_signal_disconnect(GTK_OBJECT (model->book_view),
- model->remove_card_id);
- if (model->book_view && model->modify_card_id)
- gtk_signal_disconnect(GTK_OBJECT (model->book_view),
- model->modify_card_id);
- if (model->book_view && model->status_message_id)
- gtk_signal_disconnect(GTK_OBJECT (model->book_view),
- model->status_message_id);
- if (model->book_view && model->sequence_complete_id)
- gtk_signal_disconnect(GTK_OBJECT (model->book_view),
- model->sequence_complete_id);
-
- model->create_card_id = 0;
- model->remove_card_id = 0;
- model->modify_card_id = 0;
- model->status_message_id = 0;
- model->sequence_complete_id = 0;
-
- model->search_in_progress = FALSE;
-
- if (model->book_view) {
- e_book_view_stop (model->book_view);
- gtk_object_unref(GTK_OBJECT(model->book_view));
- }
-
- model->book_view = NULL;
-}
-
-static void
-addressbook_destroy(GtkObject *object)
+remove_book_view (EAddressbookModel *model)
{
- EAddressbookModel *model = E_ADDRESSBOOK_MODEL(object);
-
- if (model->get_view_idle) {
- g_source_remove(model->get_view_idle);
- model->get_view_idle = 0;
- }
-
- remove_book_view(model);
- free_data (model);
-
- if (model->book) {
- if (model->writable_status_id)
- gtk_signal_disconnect(GTK_OBJECT (model->book),
- model->writable_status_id);
+ if (model->priv->client_view && model->priv->create_contact_id)
+ g_signal_handler_disconnect (
+ model->priv->client_view,
+ model->priv->create_contact_id);
+ if (model->priv->client_view && model->priv->remove_contact_id)
+ g_signal_handler_disconnect (
+ model->priv->client_view,
+ model->priv->remove_contact_id);
+ if (model->priv->client_view && model->priv->modify_contact_id)
+ g_signal_handler_disconnect (
+ model->priv->client_view,
+ model->priv->modify_contact_id);
+ if (model->priv->client_view && model->priv->status_message_id)
+ g_signal_handler_disconnect (
+ model->priv->client_view,
+ model->priv->status_message_id);
+ if (model->priv->client_view && model->priv->view_complete_id)
+ g_signal_handler_disconnect (
+ model->priv->client_view,
+ model->priv->view_complete_id);
+ if (model->priv->remove_status_id)
+ g_source_remove (model->priv->remove_status_id);
+
+ model->priv->create_contact_id = 0;
+ model->priv->remove_contact_id = 0;
+ model->priv->modify_contact_id = 0;
+ model->priv->status_message_id = 0;
+ model->priv->view_complete_id = 0;
+ model->priv->remove_status_id = 0;
+
+ model->priv->search_in_progress = FALSE;
+
+ if (model->priv->client_view) {
+ GError *error = NULL;
+
+ e_book_client_view_stop (model->priv->client_view, &error);
+
+ if (error != NULL) {
+ g_warning (
+ "%s: Failed to stop client view: %s",
+ G_STRFUNC, error->message);
+ g_error_free (error);
+ }
- model->writable_status_id = 0;
+ g_object_unref (model->priv->client_view);
+ model->priv->client_view = NULL;
- gtk_object_unref(GTK_OBJECT(model->book));
- model->book = NULL;
+ g_signal_emit (model, signals[STATUS_MESSAGE], 0, NULL, -1);
}
-
- g_free (model->query);
}
static void
update_folder_bar_message (EAddressbookModel *model)
{
- int count;
- char *message;
+ guint count;
+ gchar *message;
- count = model->data_count;
+ count = model->priv->contacts->len;
switch (count) {
case 0:
- message = g_strdup (_("No cards"));
- break;
- case 1:
- message = g_strdup (_("1 card"));
+ message = g_strdup (_("No contacts"));
break;
default:
- message = g_strdup_printf (_("%d cards"), count);
+ message = g_strdup_printf (
+ ngettext ("%d contact", "%d contacts", count), count);
break;
}
- gtk_signal_emit (GTK_OBJECT (model),
- e_addressbook_model_signals [FOLDER_BAR_MESSAGE],
- message);
+ g_signal_emit (model, signals[FOLDER_BAR_MESSAGE], 0, message);
g_free (message);
}
static void
-create_card(EBookView *book_view,
- const GList *cards,
- EAddressbookModel *model)
+view_create_contact_cb (EBookClientView *client_view,
+ const GSList *contact_list,
+ EAddressbookModel *model)
{
- int old_count = model->data_count;
- int length = g_list_length ((GList *)cards);
+ GPtrArray *array;
+ guint count;
+ guint index;
- if (model->data_count + length > model->allocated_count) {
- while (model->data_count + length > model->allocated_count)
- model->allocated_count = model->allocated_count * 2 + 1;
- model->data = g_renew(ECard *, model->data, model->allocated_count);
- }
+ array = model->priv->contacts;
+ index = array->len;
+ count = g_list_length ((GList *) contact_list);
- for ( ; cards; cards = cards->next) {
- model->data[model->data_count++] = cards->data;
- gtk_object_ref (cards->data);
- }
+ while (contact_list != NULL) {
+ EContact *contact = contact_list->data;
- gtk_signal_emit (GTK_OBJECT (model),
- e_addressbook_model_signals [CARD_ADDED],
- old_count, model->data_count - old_count);
+ g_ptr_array_add (array, g_object_ref (contact));
+ contact_list = contact_list->next;
+ }
+ g_signal_emit (model, signals[CONTACT_ADDED], 0, index, count);
update_folder_bar_message (model);
}
-static void
-remove_card(EBookView *book_view,
- const char *id,
- EAddressbookModel *model)
-{
- int i;
-
- for ( i = 0; i < model->data_count; i++) {
- if ( !strcmp(e_card_get_id(model->data[i]), id) ) {
- gtk_object_unref(GTK_OBJECT(model->data[i]));
- memmove(model->data + i, model->data + i + 1, (model->data_count - i - 1) * sizeof (ECard *));
- model->data_count--;
-
- gtk_signal_emit (GTK_OBJECT (model),
- e_addressbook_model_signals [CARD_REMOVED],
- i);
- update_folder_bar_message (model);
- break;
- }
- }
+static gint
+sort_descending (gconstpointer ca,
+ gconstpointer cb)
+{
+ gint a = *((gint *) ca);
+ gint b = *((gint *) cb);
+
+ return (a == b) ? 0 : (a < b) ? 1 : -1;
}
static void
-modify_card(EBookView *book_view,
- const GList *cards,
- EAddressbookModel *model)
-{
- for ( ; cards; cards = cards->next) {
- int i;
- for ( i = 0; i < model->data_count; i++) {
- if ( !strcmp(e_card_get_id(model->data[i]), e_card_get_id(E_CARD(cards->data))) ) {
- gtk_object_unref(GTK_OBJECT(model->data[i]));
- model->data[i] = e_card_duplicate(E_CARD(cards->data));
- gtk_signal_emit (GTK_OBJECT (model),
- e_addressbook_model_signals [CARD_CHANGED],
- i);
+view_remove_contact_cb (EBookClientView *client_view,
+ const GSList *ids,
+ EAddressbookModel *model)
+{
+ /* XXX we should keep a hash around instead of this O(n*m) loop */
+ const GSList *iter;
+ GArray *indices;
+ GPtrArray *array;
+ gint ii;
+
+ array = model->priv->contacts;
+ indices = g_array_new (FALSE, FALSE, sizeof (gint));
+
+ for (iter = ids; iter != NULL; iter = iter->next) {
+ const gchar *target_uid = iter->data;
+
+ for (ii = 0; ii < array->len; ii++) {
+ EContact *contact;
+ const gchar *uid;
+
+ contact = array->pdata[ii];
+ /* check if already removed */
+ if (!contact)
+ continue;
+
+ uid = e_contact_get_const (contact, E_CONTACT_UID);
+ g_return_if_fail (uid != NULL);
+
+ if (strcmp (uid, target_uid) == 0) {
+ g_object_unref (contact);
+ g_array_append_val (indices, ii);
+ array->pdata[ii] = NULL;
break;
}
}
}
-}
-static void
-status_message (EBookView *book_view,
- char* status,
- EAddressbookModel *model)
-{
- gtk_signal_emit (GTK_OBJECT (model),
- e_addressbook_model_signals [STATUS_MESSAGE],
- status);
-}
+ /* Sort the 'indices' array in descending order, since
+ * g_ptr_array_remove_index() shifts subsequent elements
+ * down one position to fill the gap. */
+ g_array_sort (indices, sort_descending);
-static void
-sequence_complete (EBookView *book_view,
- EBookViewStatus status,
- EAddressbookModel *model)
-{
- model->search_in_progress = FALSE;
- status_message (book_view, NULL, model);
- gtk_signal_emit (GTK_OBJECT (model),
- e_addressbook_model_signals [SEARCH_RESULT],
- status);
- gtk_signal_emit (GTK_OBJECT (model),
- e_addressbook_model_signals [STOP_STATE_CHANGED]);
+ for (ii = 0; ii < indices->len; ii++) {
+ gint index;
+
+ index = g_array_index (indices, gint, ii);
+ g_ptr_array_remove_index (array, index);
+ }
+
+ g_signal_emit (model, signals[CONTACTS_REMOVED], 0, indices);
+ g_array_free (indices, FALSE);
+
+ update_folder_bar_message (model);
}
static void
-writable_status (EBook *book,
- gboolean writable,
- EAddressbookModel *model)
+view_modify_contact_cb (EBookClientView *client_view,
+ const GSList *contact_list,
+ EAddressbookModel *model)
{
- if (!model->editable_set) {
- model->editable = writable;
+ GPtrArray *array;
+
+ array = model->priv->contacts;
+
+ while (contact_list != NULL) {
+ EContact *new_contact = contact_list->data;
+ const gchar *target_uid;
+ gint ii;
+
+ target_uid = e_contact_get_const (new_contact, E_CONTACT_UID);
+ g_warn_if_fail (target_uid != NULL);
+
+ /* skip contacts without UID */
+ if (!target_uid) {
+ contact_list = contact_list->next;
+ continue;
+ }
- gtk_signal_emit (GTK_OBJECT (model),
- e_addressbook_model_signals [WRITABLE_STATUS],
- writable);
+ for (ii = 0; ii < array->len; ii++) {
+ EContact *old_contact;
+ const gchar *uid;
+
+ old_contact = array->pdata[ii];
+ g_return_if_fail (old_contact != NULL);
+
+ uid = e_contact_get_const (old_contact, E_CONTACT_UID);
+ g_return_if_fail (uid != NULL);
+
+ if (strcmp (uid, target_uid) != 0)
+ continue;
+
+ g_object_unref (old_contact);
+ array->pdata[ii] = e_contact_duplicate (new_contact);
+
+ g_signal_emit (
+ model, signals[CONTACT_CHANGED], 0, ii);
+ break;
+ }
+
+ contact_list = contact_list->next;
}
}
static void
-backend_died (EBook *book,
- EAddressbookModel *model)
+view_progress_cb (EBookClientView *client_view,
+ guint percent,
+ const gchar *message,
+ EAddressbookModel *model)
{
- gtk_signal_emit (GTK_OBJECT (model),
- e_addressbook_model_signals [BACKEND_DIED]);
+ if (model->priv->remove_status_id)
+ g_source_remove (model->priv->remove_status_id);
+ model->priv->remove_status_id = 0;
+
+ g_signal_emit (model, signals[STATUS_MESSAGE], 0, message, percent);
}
static void
-e_addressbook_model_class_init (GtkObjectClass *object_class)
-{
- parent_class = gtk_type_class (PARENT_TYPE);
-
- object_class->destroy = addressbook_destroy;
- object_class->set_arg = e_addressbook_model_set_arg;
- object_class->get_arg = e_addressbook_model_get_arg;
-
- gtk_object_add_arg_type ("EAddressbookModel::book", GTK_TYPE_OBJECT,
- GTK_ARG_READWRITE, ARG_BOOK);
- gtk_object_add_arg_type ("EAddressbookModel::query", GTK_TYPE_STRING,
- GTK_ARG_READWRITE, ARG_QUERY);
- gtk_object_add_arg_type ("EAddressbookModel::editable", GTK_TYPE_BOOL,
- GTK_ARG_READWRITE, ARG_EDITABLE);
-
- e_addressbook_model_signals [WRITABLE_STATUS] =
- gtk_signal_new ("writable_status",
- GTK_RUN_LAST,
- object_class->type,
- GTK_SIGNAL_OFFSET (EAddressbookModelClass, writable_status),
- gtk_marshal_NONE__BOOL,
- GTK_TYPE_NONE, 1, GTK_TYPE_BOOL);
-
- e_addressbook_model_signals [STATUS_MESSAGE] =
- gtk_signal_new ("status_message",
- GTK_RUN_LAST,
- object_class->type,
- GTK_SIGNAL_OFFSET (EAddressbookModelClass, status_message),
- gtk_marshal_NONE__POINTER,
- GTK_TYPE_NONE, 1, GTK_TYPE_POINTER);
-
- e_addressbook_model_signals [SEARCH_RESULT] =
- gtk_signal_new ("search_result",
- GTK_RUN_LAST,
- object_class->type,
- GTK_SIGNAL_OFFSET (EAddressbookModelClass, search_result),
- gtk_marshal_NONE__ENUM,
- GTK_TYPE_NONE, 1, GTK_TYPE_ENUM);
-
- e_addressbook_model_signals [FOLDER_BAR_MESSAGE] =
- gtk_signal_new ("folder_bar_message",
- GTK_RUN_LAST,
- object_class->type,
- GTK_SIGNAL_OFFSET (EAddressbookModelClass, folder_bar_message),
- gtk_marshal_NONE__POINTER,
- GTK_TYPE_NONE, 1, GTK_TYPE_POINTER);
-
- e_addressbook_model_signals [CARD_ADDED] =
- gtk_signal_new ("card_added",
- GTK_RUN_LAST,
- object_class->type,
- GTK_SIGNAL_OFFSET (EAddressbookModelClass, card_added),
- gtk_marshal_NONE__INT_INT,
- GTK_TYPE_NONE, 2, GTK_TYPE_INT, GTK_TYPE_INT);
-
- e_addressbook_model_signals [CARD_REMOVED] =
- gtk_signal_new ("card_removed",
- GTK_RUN_LAST,
- object_class->type,
- GTK_SIGNAL_OFFSET (EAddressbookModelClass, card_removed),
- gtk_marshal_NONE__INT,
- GTK_TYPE_NONE, 1, GTK_TYPE_INT);
-
- e_addressbook_model_signals [CARD_CHANGED] =
- gtk_signal_new ("card_changed",
- GTK_RUN_LAST,
- object_class->type,
- GTK_SIGNAL_OFFSET (EAddressbookModelClass, card_changed),
- gtk_marshal_NONE__INT,
- GTK_TYPE_NONE, 1, GTK_TYPE_INT);
-
- e_addressbook_model_signals [MODEL_CHANGED] =
- gtk_signal_new ("model_changed",
- GTK_RUN_LAST,
- object_class->type,
- GTK_SIGNAL_OFFSET (EAddressbookModelClass, model_changed),
- gtk_marshal_NONE__NONE,
- GTK_TYPE_NONE, 0);
-
- e_addressbook_model_signals [STOP_STATE_CHANGED] =
- gtk_signal_new ("stop_state_changed",
- GTK_RUN_LAST,
- object_class->type,
- GTK_SIGNAL_OFFSET (EAddressbookModelClass, stop_state_changed),
- gtk_marshal_NONE__NONE,
- GTK_TYPE_NONE, 0);
-
- e_addressbook_model_signals [BACKEND_DIED] =
- gtk_signal_new ("backend_died",
- GTK_RUN_LAST,
- object_class->type,
- GTK_SIGNAL_OFFSET (EAddressbookModelClass, backend_died),
- gtk_marshal_NONE__NONE,
- GTK_TYPE_NONE, 0);
-
- gtk_object_class_add_signals (object_class, e_addressbook_model_signals, LAST_SIGNAL);
+view_complete_cb (EBookClientView *client_view,
+ const GError *error,
+ EAddressbookModel *model)
+{
+ model->priv->search_in_progress = FALSE;
+ view_progress_cb (client_view, -1, NULL, model);
+ g_signal_emit (model, signals[SEARCH_RESULT], 0, error);
+ g_signal_emit (model, signals[STOP_STATE_CHANGED], 0);
}
static void
-e_addressbook_model_init (GtkObject *object)
-{
- EAddressbookModel *model = E_ADDRESSBOOK_MODEL(object);
- model->book = NULL;
- model->query = g_strdup("(contains \"x-evolution-any-field\" \"\")");
- model->book_view = NULL;
- model->get_view_idle = 0;
- model->create_card_id = 0;
- model->remove_card_id = 0;
- model->modify_card_id = 0;
- model->status_message_id = 0;
- model->writable_status_id = 0;
- model->backend_died_id = 0;
- model->sequence_complete_id = 0;
- model->data = NULL;
- model->data_count = 0;
- model->allocated_count = 0;
- model->search_in_progress = FALSE;
- model->editable = FALSE;
- model->editable_set = FALSE;
- model->first_get_view = TRUE;
+addressbook_model_client_notify_readonly_cb (EClientCache *client_cache,
+ EClient *client,
+ GParamSpec *pspec,
+ EAddressbookModel *model)
+{
+ if (!E_IS_BOOK_CLIENT (client))
+ return;
+
+ if (E_BOOK_CLIENT (client) == model->priv->book_client) {
+ gboolean editable = !e_client_is_readonly (client);
+ e_addressbook_model_set_editable (model, editable);
+ }
}
static void
-book_view_loaded (EBook *book, EBookStatus status, EBookView *book_view, gpointer closure)
+client_view_ready_cb (GObject *source_object,
+ GAsyncResult *result,
+ gpointer user_data)
{
- EAddressbookModel *model = closure;
+ EBookClient *book_client = E_BOOK_CLIENT (source_object);
+ EBookClientView *client_view = NULL;
+ EAddressbookModel *model = user_data;
+ GError *error = NULL;
- remove_book_view(model);
+ if (!e_book_client_get_view_finish (book_client, result, &client_view, &error))
+ client_view = NULL;
- if (status != E_BOOK_STATUS_SUCCESS) {
- e_addressbook_error_dialog (_("Error getting book view"), status);
+ if (error) {
+ eab_error_dialog (NULL, NULL, _("Error getting book view"), error);
+ g_error_free (error);
return;
}
- model->book_view = book_view;
- if (model->book_view)
- gtk_object_ref(GTK_OBJECT(model->book_view));
- model->create_card_id = gtk_signal_connect(GTK_OBJECT(model->book_view),
- "card_added",
- GTK_SIGNAL_FUNC(create_card),
- model);
- model->remove_card_id = gtk_signal_connect(GTK_OBJECT(model->book_view),
- "card_removed",
- GTK_SIGNAL_FUNC(remove_card),
- model);
- model->modify_card_id = gtk_signal_connect(GTK_OBJECT(model->book_view),
- "card_changed",
- GTK_SIGNAL_FUNC(modify_card),
- model);
- model->status_message_id = gtk_signal_connect(GTK_OBJECT(model->book_view),
- "status_message",
- GTK_SIGNAL_FUNC(status_message),
- model);
- model->sequence_complete_id = gtk_signal_connect(GTK_OBJECT(model->book_view),
- "sequence_complete",
- GTK_SIGNAL_FUNC(sequence_complete),
- model);
-
+ remove_book_view (model);
free_data (model);
- model->search_in_progress = TRUE;
- gtk_signal_emit (GTK_OBJECT (model),
- e_addressbook_model_signals [MODEL_CHANGED]);
- gtk_signal_emit (GTK_OBJECT (model),
- e_addressbook_model_signals [STOP_STATE_CHANGED]);
+ model->priv->client_view = client_view;
+ if (model->priv->client_view) {
+ model->priv->create_contact_id = g_signal_connect (
+ model->priv->client_view, "objects-added",
+ G_CALLBACK (view_create_contact_cb), model);
+ model->priv->remove_contact_id = g_signal_connect (
+ model->priv->client_view, "objects-removed",
+ G_CALLBACK (view_remove_contact_cb), model);
+ model->priv->modify_contact_id = g_signal_connect (
+ model->priv->client_view, "objects-modified",
+ G_CALLBACK (view_modify_contact_cb), model);
+ model->priv->status_message_id = g_signal_connect (
+ model->priv->client_view, "progress",
+ G_CALLBACK (view_progress_cb), model);
+ model->priv->view_complete_id = g_signal_connect (
+ model->priv->client_view, "complete",
+ G_CALLBACK (view_complete_cb), model);
+
+ model->priv->search_in_progress = TRUE;
+ }
+
+ g_signal_emit (model, signals[MODEL_CHANGED], 0);
+ g_signal_emit (model, signals[SEARCH_STARTED], 0);
+ g_signal_emit (model, signals[STOP_STATE_CHANGED], 0);
+
+ if (model->priv->client_view) {
+ e_book_client_view_start (model->priv->client_view, &error);
+
+ if (error != NULL) {
+ g_warning (
+ "%s: Failed to start client view: %s",
+ G_STRFUNC, error->message);
+ g_error_free (error);
+ }
+ }
}
static gboolean
-get_view (EAddressbookModel *model)
-{
- if (model->book && model->query) {
- if (model->first_get_view) {
- char *capabilities;
- capabilities = e_book_get_static_capabilities (model->book);
- if (capabilities && strstr (capabilities, "do-initial-query")) {
- e_book_get_book_view (model->book, model->query, book_view_loaded, model);
+addressbook_model_idle_cb (EAddressbookModel *model)
+{
+ model->priv->client_view_idle_id = 0;
+
+ if (model->priv->book_client && model->priv->query_str) {
+ remove_book_view (model);
+
+ if (model->priv->first_get_view) {
+ model->priv->first_get_view = FALSE;
+
+ if (e_client_check_capability (E_CLIENT (model->priv->book_client), "do-initial-query")) {
+ e_book_client_get_view (
+ model->priv->book_client, model->priv->query_str,
+ NULL, client_view_ready_cb, model);
} else {
- remove_book_view(model);
free_data (model);
- gtk_signal_emit (GTK_OBJECT (model),
- e_addressbook_model_signals [MODEL_CHANGED]);
- gtk_signal_emit (GTK_OBJECT (model),
- e_addressbook_model_signals [STOP_STATE_CHANGED]);
+
+ g_signal_emit (
+ model, signals[MODEL_CHANGED], 0);
+ g_signal_emit (
+ model, signals[STOP_STATE_CHANGED], 0);
}
- model->first_get_view = FALSE;
- g_free (capabilities);
- }
- else
- e_book_get_book_view (model->book, model->query, book_view_loaded, model);
+ } else
+ e_book_client_get_view (
+ model->priv->book_client, model->priv->query_str,
+ NULL, client_view_ready_cb, model);
+
}
- model->get_view_idle = 0;
+ g_object_unref (model);
+
return FALSE;
}
-ECard *
-e_addressbook_model_get_card(EAddressbookModel *model,
- int row)
+static gboolean
+remove_status_cb (gpointer data)
{
- if (model->data && 0 <= row && row < model->data_count) {
- ECard *card;
- card = e_card_duplicate (model->data[row]);
- return card;
+ EAddressbookModel *model = data;
+
+ g_return_val_if_fail (model != NULL, FALSE);
+ g_return_val_if_fail (E_IS_ADDRESSBOOK_MODEL (model), FALSE);
+
+ g_signal_emit (model, signals[STATUS_MESSAGE], 0, NULL, -1);
+ model->priv->remove_status_id = 0;
+
+ return FALSE;
+}
+
+static void
+addressbook_model_set_client_cache (EAddressbookModel *model,
+ EClientCache *client_cache)
+{
+ g_return_if_fail (E_IS_CLIENT_CACHE (client_cache));
+ g_return_if_fail (model->priv->client_cache == NULL);
+
+ model->priv->client_cache = g_object_ref (client_cache);
+}
+
+static void
+addressbook_model_set_property (GObject *object,
+ guint property_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ switch (property_id) {
+ case PROP_CLIENT:
+ e_addressbook_model_set_client (
+ E_ADDRESSBOOK_MODEL (object),
+ g_value_get_object (value));
+ return;
+
+ case PROP_CLIENT_CACHE:
+ addressbook_model_set_client_cache (
+ E_ADDRESSBOOK_MODEL (object),
+ g_value_get_object (value));
+ return;
+
+ case PROP_EDITABLE:
+ e_addressbook_model_set_editable (
+ E_ADDRESSBOOK_MODEL (object),
+ g_value_get_boolean (value));
+ return;
+
+ case PROP_QUERY:
+ e_addressbook_model_set_query (
+ E_ADDRESSBOOK_MODEL (object),
+ g_value_get_string (value));
+ return;
}
- return NULL;
+
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+
}
-const ECard *
-e_addressbook_model_peek_card(EAddressbookModel *model,
- int row)
+static void
+addressbook_model_get_property (GObject *object,
+ guint property_id,
+ GValue *value,
+ GParamSpec *pspec)
{
- if (model->data && 0 <= row && row < model->data_count) {
- return model->data[row];
+ switch (property_id) {
+ case PROP_CLIENT:
+ g_value_set_object (
+ value, e_addressbook_model_get_client (
+ E_ADDRESSBOOK_MODEL (object)));
+ return;
+
+ case PROP_CLIENT_CACHE:
+ g_value_set_object (
+ value, e_addressbook_model_get_client_cache (
+ E_ADDRESSBOOK_MODEL (object)));
+ return;
+
+ case PROP_EDITABLE:
+ g_value_set_boolean (
+ value, e_addressbook_model_get_editable (
+ E_ADDRESSBOOK_MODEL (object)));
+ return;
+
+ case PROP_QUERY:
+ g_value_set_string (
+ value, e_addressbook_model_get_query (
+ E_ADDRESSBOOK_MODEL (object)));
+ return;
}
- return NULL;
+
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
}
static void
-e_addressbook_model_set_arg (GtkObject *o, GtkArg *arg, guint arg_id)
+addressbook_model_dispose (GObject *object)
{
- EAddressbookModel *model;
+ EAddressbookModel *model = E_ADDRESSBOOK_MODEL (object);
- model = E_ADDRESSBOOK_MODEL (o);
-
- switch (arg_id){
- case ARG_BOOK:
- if (model->book) {
- if (model->writable_status_id)
- gtk_signal_disconnect(GTK_OBJECT (model->book),
- model->writable_status_id);
- model->writable_status_id = 0;
-
- if (model->backend_died_id)
- gtk_signal_disconnect(GTK_OBJECT (model->book),
- model->backend_died_id);
- model->backend_died_id = 0;
-
- gtk_object_unref(GTK_OBJECT(model->book));
- }
- model->book = E_BOOK(GTK_VALUE_OBJECT (*arg));
- if (model->book) {
- model->first_get_view = TRUE;
- gtk_object_ref(GTK_OBJECT(model->book));
- if (model->get_view_idle == 0)
- model->get_view_idle = g_idle_add((GSourceFunc)get_view, model);
- gtk_signal_connect (GTK_OBJECT(model->book),
- "writable_status",
- writable_status, model);
- gtk_signal_connect (GTK_OBJECT(model->book),
- "backend_died",
- backend_died, model);
- }
- break;
- case ARG_QUERY:
- if (model->query)
- g_free(model->query);
- model->query = g_strdup(GTK_VALUE_STRING (*arg));
- if (model->get_view_idle == 0)
- model->get_view_idle = g_idle_add((GSourceFunc)get_view, model);
- break;
- case ARG_EDITABLE:
- model->editable = GTK_VALUE_BOOL (*arg);
- model->editable_set = TRUE;
- break;
+ remove_book_view (model);
+ free_data (model);
+
+ if (model->priv->client_notify_readonly_handler_id > 0) {
+ g_signal_handler_disconnect (
+ model->priv->client_cache,
+ model->priv->client_notify_readonly_handler_id);
+ model->priv->client_notify_readonly_handler_id = 0;
}
+
+ g_clear_object (&model->priv->client_cache);
+ g_clear_object (&model->priv->book_client);
+
+ if (model->priv->query_str) {
+ g_free (model->priv->query_str);
+ model->priv->query_str = NULL;
+ }
+
+ /* Chain up to parent's dispose() method. */
+ G_OBJECT_CLASS (e_addressbook_model_parent_class)->dispose (object);
}
static void
-e_addressbook_model_get_arg (GtkObject *object, GtkArg *arg, guint arg_id)
+addressbook_model_finalize (GObject *object)
{
- EAddressbookModel *e_addressbook_model;
+ EAddressbookModelPrivate *priv;
- e_addressbook_model = E_ADDRESSBOOK_MODEL (object);
+ priv = E_ADDRESSBOOK_MODEL_GET_PRIVATE (object);
- switch (arg_id) {
- case ARG_BOOK:
- GTK_VALUE_OBJECT (*arg) = GTK_OBJECT(e_addressbook_model->book);
- break;
- case ARG_QUERY:
- GTK_VALUE_STRING (*arg) = g_strdup(e_addressbook_model->query);
- break;
- case ARG_EDITABLE:
- GTK_VALUE_BOOL (*arg) = e_addressbook_model->editable;
- break;
- default:
- arg->type = GTK_TYPE_INVALID;
- break;
- }
+ g_ptr_array_free (priv->contacts, TRUE);
+
+ /* Chain up to parent's finalize() method. */
+ G_OBJECT_CLASS (e_addressbook_model_parent_class)->finalize (object);
}
-GtkType
-e_addressbook_model_get_type (void)
+static void
+addressbook_model_constructed (GObject *object)
{
- static GtkType type = 0;
+ EAddressbookModel *model;
+ EClientCache *client_cache;
+ gulong handler_id;
- if (!type){
- GtkTypeInfo info = {
- "EAddressbookModel",
- sizeof (EAddressbookModel),
- sizeof (EAddressbookModelClass),
- (GtkClassInitFunc) e_addressbook_model_class_init,
- (GtkObjectInitFunc) e_addressbook_model_init,
- NULL, /* reserved 1 */
- NULL, /* reserved 2 */
- (GtkClassInitFunc) NULL
- };
+ model = E_ADDRESSBOOK_MODEL (object);
- type = gtk_type_unique (PARENT_TYPE, &info);
- }
+ /* Chain up to parent's constructed() method. */
+ G_OBJECT_CLASS (e_addressbook_model_parent_class)->constructed (object);
- return type;
+ client_cache = e_addressbook_model_get_client_cache (model);
+
+ handler_id = g_signal_connect (
+ client_cache, "client-notify::readonly",
+ G_CALLBACK (addressbook_model_client_notify_readonly_cb),
+ model);
+ model->priv->client_notify_readonly_handler_id = handler_id;
}
-EAddressbookModel*
-e_addressbook_model_new (void)
+static void
+e_addressbook_model_class_init (EAddressbookModelClass *class)
{
- EAddressbookModel *et;
+ GObjectClass *object_class;
+
+ g_type_class_add_private (class, sizeof (EAddressbookModelPrivate));
+
+ object_class = G_OBJECT_CLASS (class);
+ object_class->set_property = addressbook_model_set_property;
+ object_class->get_property = addressbook_model_get_property;
+ object_class->dispose = addressbook_model_dispose;
+ object_class->finalize = addressbook_model_finalize;
+ object_class->constructed = addressbook_model_constructed;
+
+ g_object_class_install_property (
+ object_class,
+ PROP_CLIENT,
+ g_param_spec_object (
+ "client",
+ "EBookClient",
+ NULL,
+ E_TYPE_BOOK_CLIENT,
+ G_PARAM_READWRITE |
+ G_PARAM_STATIC_STRINGS));
+
+ g_object_class_install_property (
+ object_class,
+ PROP_CLIENT_CACHE,
+ g_param_spec_object (
+ "client-cache",
+ "Client Cache",
+ "Shared EClient instances",
+ E_TYPE_CLIENT_CACHE,
+ G_PARAM_READWRITE |
+ G_PARAM_CONSTRUCT_ONLY |
+ G_PARAM_STATIC_STRINGS));
+
+ g_object_class_install_property (
+ object_class,
+ PROP_EDITABLE,
+ g_param_spec_boolean (
+ "editable",
+ "Editable",
+ NULL,
+ FALSE,
+ G_PARAM_READWRITE |
+ G_PARAM_STATIC_STRINGS));
+
+ g_object_class_install_property (
+ object_class,
+ PROP_QUERY,
+ g_param_spec_string (
+ "query",
+ "Query",
+ NULL,
+ NULL,
+ G_PARAM_READWRITE |
+ G_PARAM_CONSTRUCT |
+ G_PARAM_STATIC_STRINGS));
+
+ signals[WRITABLE_STATUS] = g_signal_new (
+ "writable_status",
+ G_OBJECT_CLASS_TYPE (object_class),
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (EAddressbookModelClass, writable_status),
+ NULL, NULL,
+ g_cclosure_marshal_VOID__BOOLEAN,
+ G_TYPE_NONE, 1,
+ G_TYPE_BOOLEAN);
+
+ signals[STATUS_MESSAGE] = g_signal_new (
+ "status_message",
+ G_OBJECT_CLASS_TYPE (object_class),
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (EAddressbookModelClass, status_message),
+ NULL, NULL,
+ e_marshal_VOID__STRING_INT,
+ G_TYPE_NONE, 2,
+ G_TYPE_STRING,
+ G_TYPE_INT);
+
+ signals[SEARCH_STARTED] = g_signal_new (
+ "search_started",
+ G_OBJECT_CLASS_TYPE (object_class),
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (EAddressbookModelClass, search_started),
+ NULL, NULL,
+ g_cclosure_marshal_VOID__VOID,
+ G_TYPE_NONE, 0);
+
+ signals[SEARCH_RESULT] = g_signal_new (
+ "search_result",
+ G_OBJECT_CLASS_TYPE (object_class),
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (EAddressbookModelClass, search_result),
+ NULL, NULL,
+ g_cclosure_marshal_VOID__BOXED,
+ G_TYPE_NONE, 1,
+ G_TYPE_ERROR);
+
+ signals[FOLDER_BAR_MESSAGE] = g_signal_new (
+ "folder_bar_message",
+ G_OBJECT_CLASS_TYPE (object_class),
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (EAddressbookModelClass, folder_bar_message),
+ NULL, NULL,
+ g_cclosure_marshal_VOID__POINTER,
+ G_TYPE_NONE, 1,
+ G_TYPE_POINTER);
+
+ signals[CONTACT_ADDED] = g_signal_new (
+ "contact_added",
+ G_OBJECT_CLASS_TYPE (object_class),
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (EAddressbookModelClass, contact_added),
+ NULL, NULL,
+ e_marshal_NONE__INT_INT,
+ G_TYPE_NONE, 2,
+ G_TYPE_INT,
+ G_TYPE_INT);
+
+ signals[CONTACTS_REMOVED] = g_signal_new (
+ "contacts_removed",
+ G_OBJECT_CLASS_TYPE (object_class),
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (EAddressbookModelClass, contacts_removed),
+ NULL, NULL,
+ g_cclosure_marshal_VOID__POINTER,
+ G_TYPE_NONE, 1,
+ G_TYPE_POINTER);
+
+ signals[CONTACT_CHANGED] = g_signal_new (
+ "contact_changed",
+ G_OBJECT_CLASS_TYPE (object_class),
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (EAddressbookModelClass, contact_changed),
+ NULL, NULL,
+ g_cclosure_marshal_VOID__INT,
+ G_TYPE_NONE, 1,
+ G_TYPE_INT);
+
+ signals[MODEL_CHANGED] = g_signal_new (
+ "model_changed",
+ G_OBJECT_CLASS_TYPE (object_class),
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (EAddressbookModelClass, model_changed),
+ NULL, NULL,
+ g_cclosure_marshal_VOID__VOID,
+ G_TYPE_NONE, 0);
+
+ signals[STOP_STATE_CHANGED] = g_signal_new (
+ "stop_state_changed",
+ G_OBJECT_CLASS_TYPE (object_class),
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (EAddressbookModelClass, stop_state_changed),
+ NULL, NULL,
+ g_cclosure_marshal_VOID__VOID,
+ G_TYPE_NONE, 0);
+}
- et = gtk_type_new (e_addressbook_model_get_type ());
-
- return et;
+static void
+e_addressbook_model_init (EAddressbookModel *model)
+{
+ model->priv = E_ADDRESSBOOK_MODEL_GET_PRIVATE (model);
+ model->priv->contacts = g_ptr_array_new ();
+ model->priv->first_get_view = TRUE;
}
-void e_addressbook_model_stop (EAddressbookModel *model)
+EAddressbookModel *
+e_addressbook_model_new (EClientCache *client_cache)
{
- remove_book_view(model);
- gtk_signal_emit (GTK_OBJECT (model),
- e_addressbook_model_signals [STOP_STATE_CHANGED]);
- gtk_signal_emit (GTK_OBJECT (model),
- e_addressbook_model_signals [STATUS_MESSAGE],
- "Search Interrupted.");
+ g_return_val_if_fail (E_IS_CLIENT_CACHE (client_cache), NULL);
+
+ return g_object_new (
+ E_TYPE_ADDRESSBOOK_MODEL,
+ "client-cache", client_cache, NULL);
+}
+
+EClientCache *
+e_addressbook_model_get_client_cache (EAddressbookModel *model)
+{
+ g_return_val_if_fail (E_IS_ADDRESSBOOK_MODEL (model), NULL);
+
+ return model->priv->client_cache;
+}
+
+EContact *
+e_addressbook_model_get_contact (EAddressbookModel *model,
+ gint row)
+{
+ GPtrArray *array;
+
+ g_return_val_if_fail (E_IS_ADDRESSBOOK_MODEL (model), NULL);
+
+ array = model->priv->contacts;
+
+ if (0 <= row && row < array->len)
+ return e_contact_duplicate (array->pdata[row]);
+
+ return NULL;
+}
+
+void
+e_addressbook_model_stop (EAddressbookModel *model)
+{
+ const gchar *message;
+
+ g_return_if_fail (E_IS_ADDRESSBOOK_MODEL (model));
+
+ remove_book_view (model);
+
+ message = _("Search Interrupted");
+ g_signal_emit (model, signals[STOP_STATE_CHANGED], 0);
+ g_signal_emit (model, signals[STATUS_MESSAGE], 0, message, -1);
+
+ if (!model->priv->remove_status_id)
+ model->priv->remove_status_id =
+ g_timeout_add_seconds (3, remove_status_cb, model);
}
gboolean
e_addressbook_model_can_stop (EAddressbookModel *model)
{
- return model->search_in_progress;
+ g_return_val_if_fail (E_IS_ADDRESSBOOK_MODEL (model), FALSE);
+
+ return model->priv->search_in_progress;
}
void
e_addressbook_model_force_folder_bar_message (EAddressbookModel *model)
{
+ g_return_if_fail (E_IS_ADDRESSBOOK_MODEL (model));
+
update_folder_bar_message (model);
}
-int
-e_addressbook_model_card_count (EAddressbookModel *model)
+gint
+e_addressbook_model_contact_count (EAddressbookModel *model)
+{
+ g_return_val_if_fail (E_IS_ADDRESSBOOK_MODEL (model), 0);
+
+ return model->priv->contacts->len;
+}
+
+EContact *
+e_addressbook_model_contact_at (EAddressbookModel *model,
+ gint index)
+{
+ g_return_val_if_fail (E_IS_ADDRESSBOOK_MODEL (model), NULL);
+
+ return model->priv->contacts->pdata[index];
+}
+
+gint
+e_addressbook_model_find (EAddressbookModel *model,
+ EContact *contact)
+{
+ GPtrArray *array;
+ gint ii;
+
+ /* XXX This searches for a particular EContact instance,
+ * as opposed to an equivalent but possibly different
+ * EContact instance. Might have to revise this in
+ * the future. */
+
+ g_return_val_if_fail (E_IS_ADDRESSBOOK_MODEL (model), -1);
+ g_return_val_if_fail (E_IS_CONTACT (contact), -1);
+
+ array = model->priv->contacts;
+ for (ii = 0; ii < array->len; ii++) {
+ EContact *candidate = array->pdata[ii];
+
+ if (contact == candidate)
+ return ii;
+ }
+
+ return -1;
+}
+
+EBookClient *
+e_addressbook_model_get_client (EAddressbookModel *model)
{
- return model->data_count;
+ g_return_val_if_fail (E_IS_ADDRESSBOOK_MODEL (model), NULL);
+
+ return model->priv->book_client;
}
-ECard *
-e_addressbook_model_card_at (EAddressbookModel *model, int index)
+void
+e_addressbook_model_set_client (EAddressbookModel *model,
+ EBookClient *book_client)
{
- return model->data[index];
+ gboolean editable;
+
+ g_return_if_fail (E_IS_ADDRESSBOOK_MODEL (model));
+ g_return_if_fail (E_IS_BOOK_CLIENT (book_client));
+
+ if (model->priv->book_client == book_client)
+ return;
+
+ if (model->priv->book_client != NULL)
+ g_object_unref (model->priv->book_client);
+
+ model->priv->book_client = g_object_ref (book_client);
+ model->priv->first_get_view = TRUE;
+
+ editable = !e_client_is_readonly (E_CLIENT (book_client));
+ e_addressbook_model_set_editable (model, editable);
+
+ if (model->priv->client_view_idle_id == 0)
+ model->priv->client_view_idle_id = g_idle_add (
+ (GSourceFunc) addressbook_model_idle_cb,
+ g_object_ref (model));
+
+ g_object_notify (G_OBJECT (model), "client");
}
gboolean
-e_addressbook_model_editable (EAddressbookModel *model)
+e_addressbook_model_get_editable (EAddressbookModel *model)
{
- return model->editable;
+ g_return_val_if_fail (E_IS_ADDRESSBOOK_MODEL (model), FALSE);
+
+ return model->priv->editable;
}
-EBook *
-e_addressbook_model_get_ebook (EAddressbookModel *model)
+void
+e_addressbook_model_set_editable (EAddressbookModel *model,
+ gboolean editable)
{
- return model->book;
+ g_return_if_fail (E_IS_ADDRESSBOOK_MODEL (model));
+
+ if (model->priv->editable != editable) {
+ model->priv->editable = editable;
+
+ g_signal_emit (
+ model, signals[WRITABLE_STATUS], 0,
+ model->priv->editable);
+
+ g_object_notify (G_OBJECT (model), "editable");
+ }
+}
+
+gchar *
+e_addressbook_model_get_query (EAddressbookModel *model)
+{
+ g_return_val_if_fail (E_IS_ADDRESSBOOK_MODEL (model), NULL);
+
+ return model->priv->query_str;
+}
+
+void
+e_addressbook_model_set_query (EAddressbookModel *model,
+ const gchar *query)
+{
+ EBookQuery *book_query;
+
+ g_return_if_fail (E_IS_ADDRESSBOOK_MODEL (model));
+
+ if (query == NULL)
+ book_query = e_book_query_any_field_contains ("");
+ else
+ book_query = e_book_query_from_string (query);
+
+ /* also checks whether the query is a valid query string */
+ if (!book_query)
+ return;
+
+ if (model->priv->query_str != NULL) {
+ gchar *new_query;
+
+ new_query = e_book_query_to_string (book_query);
+
+ if (new_query && g_str_equal (model->priv->query_str, new_query)) {
+ g_free (new_query);
+ e_book_query_unref (book_query);
+ return;
+ }
+
+ g_free (new_query);
+ }
+
+ g_free (model->priv->query_str);
+ model->priv->query_str = e_book_query_to_string (book_query);
+ e_book_query_unref (book_query);
+
+ if (model->priv->client_view_idle_id == 0)
+ model->priv->client_view_idle_id = g_idle_add (
+ (GSourceFunc) addressbook_model_idle_cb,
+ g_object_ref (model));
+
+ g_object_notify (G_OBJECT (model), "query");
}