commit 5f83fc43276181409b21688681658d1e9938f83f
Author: Tristan Van Berkom <tristan.van.berkom@gmail.com>
Date:   Sun Jun 26 12:05:54 2011 -0400

    Added E_BOOK_CLIENT_VIEW_DIRECTORY flag to EBookClientViewFlags.
    
    If an EBookClientView is flagged as a 'directory' then only UIDs
    are sent (the idea is that you never have the full contents of
    the contacts when you are only 'browsing the directory').
    
    Patch modifies:
       o addressbook/backends/file/e-book-backend-file.c:
         Send UIDs only vcards when sending initial notifications
    
       o addressbook/libedata-book/e-book-backend.c:
         Strip vCards into shallow UID only vCards when sending
         update notifications.
    
       o addressbook/libebook/e-book-client-view.[ch]:
         Added the new flag and added e_book_client_view_get_flags()
         (The EBookClientView caches a local copy of the flags now
         for the convenience of the caller).

diff --git a/addressbook/backends/file/e-book-backend-file.c b/addressbook/backends/file/e-book-backend-file.c
index 596c829..ac25358 100644
--- a/addressbook/backends/file/e-book-backend-file.c
+++ b/addressbook/backends/file/e-book-backend-file.c
@@ -633,17 +633,45 @@ get_closure (EDataBookView *book_view)
 	return g_object_get_data (G_OBJECT (book_view), "EBookBackendFile.BookView::closure");
 }
 
+static void
+notify_update_vcard (EDataBookView *book_view,
+		     gboolean       uid_only,
+		     gboolean       prefiltered,
+		     const gchar   *id,
+		     const gchar   *vcard)
+{
+	gchar *final_vcard;
+
+	if (uid_only) {
+		/* Create a shallow version of the contacts for views that are
+		 * only interested in the uid. */
+		EContact *shallow = e_contact_new ();
+
+		e_contact_set (shallow, E_CONTACT_UID, id);
+		final_vcard = e_vcard_to_string (E_VCARD (shallow), EVC_FORMAT_VCARD_30);
+		g_object_unref (shallow);
+	} else {
+		final_vcard = g_strdup (vcard);
+	}
+
+	if (prefiltered)
+		e_data_book_view_notify_update_prefiltered_vcard (book_view, id, final_vcard);
+	else
+		e_data_book_view_notify_update_vcard (book_view, final_vcard);
+}
+
 static gpointer
 book_view_thread (gpointer data)
 {
 	EDataBookView *book_view;
 	FileBackendSearchClosure *closure;
 	EBookBackendFile *bf;
+	EBookClientViewFlags flags;
 	const gchar *query;
 	DB  *db;
 	DBT id_dbt, vcard_dbt;
 	gint db_error;
-	gboolean allcontacts;
+	gboolean allcontacts, uid_only;
 
 	g_return_val_if_fail (E_IS_DATA_BOOK_VIEW (data), NULL);
 
@@ -672,6 +700,10 @@ book_view_thread (gpointer data)
 		allcontacts = FALSE;
 	}
 
+	/* If the view is only a directory, avoid digging everything else up */
+	flags = e_data_book_view_get_flags (book_view);
+	uid_only = (flags & E_BOOK_CLIENT_VIEW_DIRECTORY) != 0;
+
 	d(printf ("signalling parent thread\n"));
 	e_flag_set (closure->running);
 
@@ -689,6 +721,11 @@ book_view_thread (gpointer data)
 			if (!e_flag_is_set (closure->running))
 				break;
 
+			if (uid_only) {
+				notify_update_vcard (book_view, uid_only, TRUE, id, NULL);
+				continue;
+			}
+
 			string_to_dbt (id, &id_dbt);
 			memset (&vcard_dbt, 0, sizeof (vcard_dbt));
 			vcard_dbt.flags = DB_DBT_MALLOC;
@@ -696,7 +733,7 @@ book_view_thread (gpointer data)
 			db_error = db->get (db, NULL, &id_dbt, &vcard_dbt, 0);
 
 			if (db_error == 0) {
-				e_data_book_view_notify_update_prefiltered_vcard (book_view, id, vcard_dbt.data);
+				notify_update_vcard (book_view, uid_only, TRUE, id, vcard_dbt.data);
 			}
 			else {
 				g_warning (G_STRLOC ": db->get failed with %s", db_strerror (db_error));
@@ -724,10 +761,8 @@ book_view_thread (gpointer data)
 
 				/* don't include the version in the list of cards */
 				if (strcmp (id_dbt.data, E_BOOK_BACKEND_FILE_VERSION_NAME)) {
-					if (allcontacts)
-						e_data_book_view_notify_update_prefiltered_vcard (book_view, id_dbt.data, vcard_dbt.data);
-					else
-						e_data_book_view_notify_update_vcard (book_view, vcard_dbt.data);
+					notify_update_vcard (book_view, uid_only, allcontacts, 
+							     id_dbt.data, vcard_dbt.data);
 				} else {
 					g_free (vcard_dbt.data);
 				}
diff --git a/addressbook/libebook/e-book-client-view.c b/addressbook/libebook/e-book-client-view.c
index 6c09ccc..a54375d 100644
--- a/addressbook/libebook/e-book-client-view.c
+++ b/addressbook/libebook/e-book-client-view.c
@@ -39,6 +39,7 @@ struct _EBookClientViewPrivate {
 	GDBusProxy *gdbus_bookview;
 	EBookClient *client;
 	gboolean running;
+	EBookClientViewFlags flags;
 };
 
 enum {
@@ -268,19 +269,49 @@ e_book_client_view_set_flags (EBookClientView      *view,
 
 	priv = view->priv;
 
-	if (priv->gdbus_bookview) {
-		GError *local_error = NULL;
+	if (priv->flags != flags) {
 
-		e_gdbus_book_view_call_set_flags_sync (priv->gdbus_bookview, flags, NULL, &local_error);
+		if (priv->gdbus_bookview) {
+			GError *local_error = NULL;
+
+			e_gdbus_book_view_call_set_flags_sync (priv->gdbus_bookview, flags, NULL, &local_error);
+
+			/* Assign the flags only if we succeed */
+			if (!local_error)
+				priv->flags = flags;
+
+			e_client_unwrap_dbus_error (E_CLIENT (priv->client), local_error, error);
+		} else {
+			g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_DBUS_ERROR,
+					     _("Cannot set flags on view, D-Bus proxy gone"));
+		}
 
-		e_client_unwrap_dbus_error (E_CLIENT (priv->client), local_error, error);
-	} else {
-		g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_DBUS_ERROR,
-				     _("Cannot set flags on view, D-Bus proxy gone"));
 	}
 }
 
 /**
+ * e_book_client_view_get_flags:
+ * @view: an #EBookClientView
+ *
+ * Gets the currently set @flags which control the behaviour of @view.
+ *
+ * Returns: The #EBookClientViewFlags
+ */
+EBookClientViewFlags
+e_book_client_view_get_flags (EBookClientView *view)
+{
+	EBookClientViewPrivate *priv;
+
+	g_return_val_if_fail (E_IS_BOOK_CLIENT_VIEW (view),
+			      E_BOOK_CLIENT_VIEW_DEFAULT_FLAGS);
+
+	priv = view->priv;
+
+	return priv->flags;
+}
+
+
+/**
  * e_book_client_view_set_fields_of_interest:
  * @view: An #EBookClientView object
  * @fields_of_interest: List of field names in which the client is interested
@@ -329,6 +360,7 @@ e_book_client_view_init (EBookClientView *view)
 
 	view->priv->client = NULL;
 	view->priv->running = FALSE;
+	view->priv->flags = E_BOOK_CLIENT_VIEW_DEFAULT_FLAGS;
 }
 
 static void
diff --git a/addressbook/libebook/e-book-client-view.h b/addressbook/libebook/e-book-client-view.h
index 24a91d9..0a61817 100644
--- a/addressbook/libebook/e-book-client-view.h
+++ b/addressbook/libebook/e-book-client-view.h
@@ -45,11 +45,15 @@ struct _EBookClient;  /* Forward reference */
  *                                     view's query will be sent as notifications when starting
  *                                     the view, otherwise only future changes will be reported.
  *                                     The default for a #EBookClientView is %TRUE.
+ * @E_BOOK_CLIENT_VIEW_DIRECTORY:  Indicates that the view is a 'directory', such a view sends
+ *                                 only UIDs in the vCards reported.
+ *                                 The default for a #EBookClientView is %FALSE.
  *
  * Flags that control the behaviour of an #EBookClientView.
  */
 typedef enum {
 	E_BOOK_CLIENT_VIEW_NOTIFY_INITIAL = (1 << 0),
+	E_BOOK_CLIENT_VIEW_DIRECTORY      = (1 << 1),
 } EBookClientViewFlags;
 
 
@@ -88,6 +92,7 @@ void			e_book_client_view_set_fields_of_interest (EBookClientView *view, const G
 void			e_book_client_view_start		(EBookClientView *view, GError **error);
 void			e_book_client_view_stop			(EBookClientView *view, GError **error);
 void                    e_book_client_view_set_flags            (EBookClientView *view, EBookClientViewFlags  flags, GError **error);
+EBookClientViewFlags    e_book_client_view_get_flags            (EBookClientView *view);
 
 G_END_DECLS
 
diff --git a/addressbook/libedata-book/e-book-backend.c b/addressbook/libedata-book/e-book-backend.c
index 358f489..5d1908b 100644
--- a/addressbook/libedata-book/e-book-backend.c
+++ b/addressbook/libedata-book/e-book-backend.c
@@ -11,6 +11,8 @@
 #include <glib/gi18n-lib.h>
 
 #include <libedataserver/e-data-server-util.h>
+#include <libebook/e-book-client-view.h>
+#include <string.h>
 
 #include "e-data-book-view.h"
 #include "e-data-book.h"
@@ -804,7 +806,9 @@ e_book_backend_remove_client (EBookBackend *backend,
  * @callback returns %FALSE to stop further processing.
  **/
 void
-e_book_backend_foreach_view (EBookBackend *backend, gboolean (* callback) (EDataBookView *view, gpointer user_data), gpointer user_data)
+e_book_backend_foreach_view (EBookBackend *backend, 
+			     gboolean (* callback) (EDataBookView *view, gpointer user_data), 
+			     gpointer user_data)
 {
 	const GSList *views;
 	EDataBookView *view;
@@ -1027,9 +1031,28 @@ e_book_backend_sync (EBookBackend *backend)
 
 
 static gboolean
-view_notify_update (EDataBookView *view, gpointer contact)
+view_notify_update (EDataBookView *view, gpointer data)
 {
-	e_data_book_view_notify_update (view, contact);
+	EContact            *contact = data;
+	EBookClientViewFlags flags;
+
+	/* If the view is only a directory, only notify with the UID */
+	flags = e_data_book_view_get_flags (view);
+
+	if ((flags & E_BOOK_CLIENT_VIEW_DIRECTORY) != 0) {
+		/* Create a shallow version of the contacts for views that are
+		 * only interested in the uid. */
+		EContact *shallow = e_contact_new ();
+		gchar    *vcard;
+
+		e_contact_set (shallow, E_CONTACT_UID, e_contact_get_const (contact, E_CONTACT_UID));
+		vcard = e_vcard_to_string (E_VCARD (shallow), EVC_FORMAT_VCARD_30);
+		g_object_unref (shallow);
+
+		e_data_book_view_notify_update_vcard (view, vcard);
+	} else {
+		e_data_book_view_notify_update (view, contact);
+	}
 
 	return TRUE;
 }
