diff --git a/libedataserverui/e-contact-store.c b/libedataserverui/e-contact-store.c
index b251451..e43eab9 100644
--- a/libedataserverui/e-contact-store.c
+++ b/libedataserverui/e-contact-store.c
@@ -36,6 +36,17 @@ G_STMT_START {                                            \
 	(iter)->user_data = GINT_TO_POINTER (index);        \
 } G_STMT_END
 
+
+#define E_CONTACT_STORE_GET_PRIVATE(obj) \
+	(G_TYPE_INSTANCE_GET_PRIVATE \
+	((obj), E_TYPE_CONTACT_STORE, EContactStorePrivate))
+
+struct _EContactStorePrivate {
+	/* Generates rows for email ids inside contacts. Intended for use by ENameSelectorModel and ENameSelectorDialog */
+	gboolean expand_contacts;	
+	
+};
+
 static void         e_contact_store_init            (EContactStore      *contact_store);
 static void         e_contact_store_class_init      (EContactStoreClass *class);
 static void         e_contact_store_tree_model_init (GtkTreeModelIface  *iface);
@@ -69,6 +80,8 @@ static gboolean     e_contact_store_iter_nth_child  (GtkTreeModel       *tree_mo
 static gboolean     e_contact_store_iter_parent     (GtkTreeModel       *tree_model,
 						     GtkTreeIter        *iter,
 						     GtkTreeIter        *child);
+static gint	    get_start_array_index (GPtrArray *contacts, EContact *contact, gint index, 
+					   gint len);
 
 typedef struct
 {
@@ -136,6 +149,8 @@ e_contact_store_class_init (EContactStoreClass *class)
 	parent_class = g_type_class_peek_parent (class);
 	object_class = (GObjectClass *) class;
 
+	g_type_class_add_private (class, sizeof (EContactStorePrivate));
+
 	object_class->finalize = e_contact_store_finalize;
 }
 
@@ -159,9 +174,14 @@ e_contact_store_tree_model_init (GtkTreeModelIface *iface)
 static void
 e_contact_store_init (EContactStore *contact_store)
 {
+	EContactStorePrivate *priv;
+	
+	priv = E_CONTACT_STORE_GET_PRIVATE (contact_store);
+
 	contact_store->stamp           = g_random_int ();
 	contact_store->query           = NULL;
 	contact_store->contact_sources = g_array_new (FALSE, FALSE, sizeof (ContactSource));
+	priv->expand_contacts 	       = FALSE;
 }
 
 static void
@@ -169,6 +189,9 @@ e_contact_store_finalize (GObject *object)
 {
 	EContactStore *contact_store = E_CONTACT_STORE (object);
 	gint           i;
+	EContactStorePrivate *priv;
+
+	priv = E_CONTACT_STORE_GET_PRIVATE (contact_store);
 
 	/* Free sources and cached contacts */
 
@@ -176,7 +199,7 @@ e_contact_store_finalize (GObject *object)
 		ContactSource *source = &g_array_index (contact_store->contact_sources, ContactSource, i);
 
 		clear_contact_source (contact_store, source);
-
+	
 		free_contact_ptrarray (source->contacts);
 		g_object_unref (source->book);
 	}
@@ -202,6 +225,20 @@ e_contact_store_new (void)
 	return E_CONTACT_STORE (g_object_new (E_TYPE_CONTACT_STORE, NULL));
 }
 
+EContactStore *
+e_contact_store_new_with_options (gboolean expand_contacts)
+{
+	EContactStore *contact_store;
+	EContactStorePrivate *priv;
+
+	contact_store = E_CONTACT_STORE (g_object_new (E_TYPE_CONTACT_STORE, NULL));
+	priv = E_CONTACT_STORE_GET_PRIVATE (contact_store);
+	
+	priv->expand_contacts = expand_contacts;
+	
+	return contact_store;
+}
+
 /* ------------------ *
  * Row update helpers *
  * ------------------ */
@@ -247,6 +284,67 @@ row_changed (EContactStore *contact_store, gint n)
 	gtk_tree_path_free (path);
 }
 
+
+static guint 
+get_email_count (EContact *contact)
+{
+	GList *email_list, *l;
+	guint len;
+
+
+	if (e_contact_get (contact, E_CONTACT_IS_LIST))
+		return 1;
+
+	email_list = e_contact_get (contact, E_CONTACT_EMAIL);
+	len = g_list_length (email_list);
+
+	for (l = email_list; l; l = g_list_next (l))
+		g_free (l->data);
+
+	g_list_free (email_list);
+
+	return len;
+}
+
+/* ------------------ *
+ * Row Generators *
+ * ------------------ */
+static void
+insert_contact_expanded (EContactStore *contact_store, ContactSource *source, EContact *contact, gint offset)
+{
+	guint len, i;
+       
+	len = get_email_count (contact);
+
+	for (i = 0; i < len; i++) {
+		/* add same contact into array to preserve row and array mapping */
+		g_ptr_array_add (source->contacts, contact);
+		g_object_ref (contact);
+		row_inserted (contact_store, offset + source->contacts->len - 1);
+	}
+}
+
+static gint
+delete_expanded_contacts (EContactStore *contact_store, ContactSource *source, EContact *contact, gint offset, gint index)
+{
+	guint len, i;
+       
+	len = get_email_count (contact);
+	
+	if (len > 1)
+		index  = get_start_array_index (source->contacts, contact, index, len);
+	
+	for (i = 0; i < len; i++) 
+	{
+		contact = g_ptr_array_index (source->contacts, index + i);
+		g_object_unref (contact);
+		g_ptr_array_remove_index (source->contacts, index + i);
+		row_deleted (contact_store, offset + index + i);
+	}
+
+	return len;
+}
+
 /* ---------------------- *
  * Contact source helpers *
  * ---------------------- */
@@ -477,6 +575,9 @@ view_contacts_added (EContactStore *contact_store, const GList *contacts, EBookV
 	ContactSource *source;
 	gint           offset;
 	const GList   *l;
+	EContactStorePrivate *priv;
+
+	priv = E_CONTACT_STORE_GET_PRIVATE (contact_store);
 
 	if (!find_contact_source_details_by_view (contact_store, book_view, &source, &offset)) {
 		g_warning ("EContactStore got 'contacts_added' signal from unknown EBookView!");
@@ -490,8 +591,11 @@ view_contacts_added (EContactStore *contact_store, const GList *contacts, EBookV
 
 		if (book_view == source->book_view) {
 			/* Current view */
-			g_ptr_array_add (source->contacts, contact);
-			row_inserted (contact_store, offset + source->contacts->len - 1);
+			if (!priv->expand_contacts) {
+				g_ptr_array_add (source->contacts, contact);
+				row_inserted (contact_store, offset + source->contacts->len - 1);
+			} else
+				insert_contact_expanded (contact_store, source, contact, offset);
 		} else {
 			/* Pending view */
 			g_ptr_array_add (source->contacts_pending, contact);
@@ -503,9 +607,13 @@ static void
 view_contacts_removed (EContactStore *contact_store, const GList *uids, EBookView *book_view)
 {
 	ContactSource *source;
+	EContactStorePrivate *priv;
 	gint           offset;
 	const GList   *l;
 
+
+	priv = E_CONTACT_STORE_GET_PRIVATE (contact_store);
+
 	if (!find_contact_source_details_by_view (contact_store, book_view, &source, &offset)) {
 		g_warning ("EContactStore got 'contacts_removed' signal from unknown EBookView!");
 		return;
@@ -522,11 +630,16 @@ view_contacts_removed (EContactStore *contact_store, const GList *uids, EBookVie
 		}
 
 		if (book_view == source->book_view) {
-			/* Current view */
 			contact = g_ptr_array_index (source->contacts, n);
-			g_object_unref (contact);
-			g_ptr_array_remove_index (source->contacts, n);
-			row_deleted (contact_store, offset + n);
+		
+			/* Current view */
+			if (!priv->expand_contacts) {
+				g_object_unref (contact);
+				g_ptr_array_remove_index (source->contacts, n);
+				row_deleted (contact_store, offset + n);
+			} else {
+				delete_expanded_contacts (contact_store, source, contact, offset, n);
+			}
 		} else {
 			/* Pending view */
 			contact = g_ptr_array_index (source->contacts_pending, n);
@@ -540,10 +653,13 @@ static void
 view_contacts_changed (EContactStore *contact_store, const GList *contacts, EBookView *book_view)
 {
 	GPtrArray     *cached_contacts;
+	EContactStorePrivate *priv;
 	ContactSource *source;
 	gint           offset;
 	const GList   *l;
 
+	priv = E_CONTACT_STORE_GET_PRIVATE (contact_store);
+
 	if (!find_contact_source_details_by_view (contact_store, book_view, &source, &offset)) {
 		g_warning ("EContactStore got 'contacts_changed' signal from unknown EBookView!");
 		return;
@@ -559,23 +675,32 @@ view_contacts_changed (EContactStore *contact_store, const GList *contacts, EBoo
 		EContact    *contact = l->data;
 		const gchar *uid     = e_contact_get_const (contact, E_CONTACT_UID);
 		gint         n       = find_contact_by_view_and_uid (contact_store, book_view, uid);
+		gboolean emit_changed;
 
 		if (n < 0) {
 			g_warning ("EContactStore got change notification on unknown contact!");
 			continue;
 		}
 
-		cached_contact = g_ptr_array_index (cached_contacts, n);
+		emit_changed = (book_view == source->book_view);
 
-		/* Update cached contact */
-		if (cached_contact != contact) {
-			g_object_unref (cached_contact);
-			cached_contacts->pdata [n] = g_object_ref (contact);
+		cached_contact = g_ptr_array_index (cached_contacts, n);
+		if (!priv->expand_contacts || ((get_email_count (cached_contact) == get_email_count (contact)) == 1))
+		{
+			/* Update cached contact */
+			if (cached_contact != contact) {
+				g_object_unref (cached_contact);
+				cached_contacts->pdata [n] = g_object_ref (contact);
+			}
+
+			/* Emit changes for current view only */
+			if (emit_changed) {
+				row_changed (contact_store, offset + n);
+			}
+		} else {
+			delete_expanded_contacts (contact_store, source, cached_contact, offset, n);
+			insert_contact_expanded (contact_store, source, contact, offset);
 		}
-
-		/* Emit changes for current view only */
-		if (book_view == source->book_view)
-			row_changed (contact_store, offset + n);
 	}
 }
 
@@ -583,9 +708,13 @@ static void
 view_sequence_complete (EContactStore *contact_store, EBookViewStatus status, EBookView *book_view)
 {
 	ContactSource *source;
+	EContactStorePrivate *priv;
 	gint           offset;
 	gint           i;
 
+
+	priv = E_CONTACT_STORE_GET_PRIVATE (contact_store);
+
 	if (!find_contact_source_details_by_view (contact_store, book_view, &source, &offset)) {
 		g_warning ("EContactStore got 'sequence_complete' signal from unknown EBookView!");
 		return;
@@ -613,10 +742,17 @@ view_sequence_complete (EContactStore *contact_store, EBookViewStatus status, EB
 		result = find_contact_by_view_and_uid (contact_store, source->book_view_pending, old_uid);
 		if (result < 0) {
 			/* Contact is not in new view; removed */
-			g_object_unref (old_contact);
-			g_ptr_array_remove_index (source->contacts, i);
-			row_deleted (contact_store, offset + i);
-			i--;  /* Stay in place */
+			if (!priv->expand_contacts)
+			{
+				g_object_unref (old_contact);
+				g_ptr_array_remove_index (source->contacts, i);
+				row_deleted (contact_store, offset + i);
+				i--;  /* Stay in place */
+			} else {
+				gint len = delete_expanded_contacts (contact_store, source, old_contact, offset, i);
+				i = i - len;
+			}
+
 		}
 	}
 
@@ -629,8 +765,12 @@ view_sequence_complete (EContactStore *contact_store, EBookViewStatus status, EB
 		result = find_contact_by_view_and_uid (contact_store, source->book_view, new_uid);
 		if (result < 0) {
 			/* Contact is not in old view; inserted */
-			g_ptr_array_add (source->contacts, new_contact);
-			row_inserted (contact_store, offset + source->contacts->len - 1);
+			if (!priv->expand_contacts) {
+				g_ptr_array_add (source->contacts, new_contact);
+				row_inserted (contact_store, offset + source->contacts->len - 1);
+			} else
+				insert_contact_expanded (contact_store, source, new_contact, offset);
+
 		} else {
 			/* Contact already in old view; drop the new one */
 			g_object_unref (new_contact);
@@ -902,6 +1042,7 @@ e_contact_store_add_book (EContactStore *contact_store, EBook *book)
 {
 	ContactSource  source;
 	ContactSource *indexed_source;
+	EContactStorePrivate *priv;
 
 	g_return_if_fail (E_IS_CONTACT_STORE (contact_store));
 	g_return_if_fail (E_IS_BOOK (book));
@@ -911,10 +1052,13 @@ e_contact_store_add_book (EContactStore *contact_store, EBook *book)
 		return;
 	}
 
+	priv = E_CONTACT_STORE_GET_PRIVATE (contact_store);
 	memset (&source, 0, sizeof (ContactSource));
 	source.book     = g_object_ref (book);
 	source.contacts = g_ptr_array_new ();
+	
 	g_array_append_val (contact_store->contact_sources, source);
+	
 
 	indexed_source = &g_array_index (contact_store->contact_sources, ContactSource,
 					 contact_store->contact_sources->len - 1);
@@ -934,6 +1078,7 @@ e_contact_store_remove_book (EContactStore *contact_store, EBook *book)
 {
 	ContactSource *source;
 	gint           source_index;
+	EContactStorePrivate *priv;
 
 	g_return_if_fail (E_IS_CONTACT_STORE (contact_store));
 	g_return_if_fail (E_IS_BOOK (book));
@@ -944,8 +1089,11 @@ e_contact_store_remove_book (EContactStore *contact_store, EBook *book)
 		return;
 	}
 
+	priv = E_CONTACT_STORE_GET_PRIVATE (contact_store);
+
 	source = &g_array_index (contact_store->contact_sources, ContactSource, source_index);
 	clear_contact_source (contact_store, source);
+
 	free_contact_ptrarray (source->contacts);
 	g_object_unref (book);
 
@@ -1060,20 +1208,73 @@ e_contact_store_get_column_type (GtkTreeModel *tree_model,
 	return get_column_type (contact_store, index);
 }
 
+static gint
+get_start_array_index (GPtrArray *contacts, EContact *contact, gint index, gint len)
+{
+	gint i;
+	
+	for (i = 1; i <= len; i++) {
+		EContact *contact_prev = g_ptr_array_index (contacts, index - i);
+
+		if (contact != contact_prev) 
+			break;
+	}
+
+	return index - i + 1;
+}
+
+static void
+set_iter_metadata (EContactStore *contact_store, GtkTreeIter *iter, gint row)
+{
+	ContactSource *source;
+	gint           source_index;
+	gint           offset;
+	EContact       *contact;
+	gint           index = row;
+	gint	       len;
+
+	source_index = find_contact_source_by_offset (contact_store, index);
+	if (source_index < 0) {
+		iter->user_data2 = GINT_TO_POINTER (0);
+		return;
+	}
+
+	source = &g_array_index (contact_store->contact_sources, ContactSource, source_index);
+	offset = get_contact_source_offset (contact_store, source_index);
+	index -= offset;
+
+	contact = g_ptr_array_index (source->contacts, index);
+	len = get_email_count (contact);
+
+	if (len > 1) {
+		gint email_n = index - get_start_array_index (source->contacts, contact, index, len);
+		iter->user_data2 = GINT_TO_POINTER (email_n);
+	} else
+		iter->user_data2 = GINT_TO_POINTER (0);
+}
+
 static gboolean
 e_contact_store_get_iter (GtkTreeModel *tree_model, GtkTreeIter *iter, GtkTreePath *path)
 {
 	EContactStore *contact_store = E_CONTACT_STORE (tree_model);
 	gint           index;
+	EContactStorePrivate *priv;
 
 	g_return_val_if_fail (E_IS_CONTACT_STORE (tree_model), FALSE);
 	g_return_val_if_fail (gtk_tree_path_get_depth (path) > 0, FALSE);
 
+	priv = E_CONTACT_STORE_GET_PRIVATE (contact_store);
+
 	index = gtk_tree_path_get_indices (path)[0];
 	if (index >= count_contacts (contact_store))
 		return FALSE;
 
 	ITER_SET (contact_store, iter, index);
+
+	if (priv->expand_contacts) {
+		set_iter_metadata (contact_store, iter, index);
+	}
+
 	return TRUE;
 }
 
@@ -1101,14 +1302,21 @@ e_contact_store_iter_next (GtkTreeModel  *tree_model,
 {
 	EContactStore *contact_store = E_CONTACT_STORE (tree_model);
 	gint           index;
+	EContactStorePrivate *priv;
 
 	g_return_val_if_fail (E_IS_CONTACT_STORE (tree_model), FALSE);
 	g_return_val_if_fail (ITER_IS_VALID (contact_store, iter), FALSE);
 
+	priv = E_CONTACT_STORE_GET_PRIVATE (contact_store);
 	index = ITER_GET (iter);
 
 	if (index + 1 < count_contacts (contact_store)) {
 		ITER_SET (contact_store, iter, index + 1);
+		
+		if (priv->expand_contacts) {
+			set_iter_metadata (contact_store, iter, index + 1);
+		}
+
 		return TRUE;
 	}
 
@@ -1121,9 +1329,12 @@ e_contact_store_iter_children (GtkTreeModel *tree_model,
 			       GtkTreeIter  *parent)
 {
 	EContactStore *contact_store = E_CONTACT_STORE (tree_model);
+	EContactStorePrivate *priv;
 
 	g_return_val_if_fail (E_IS_CONTACT_STORE (tree_model), FALSE);
 
+	priv = E_CONTACT_STORE_GET_PRIVATE (contact_store);
+
 	/* This is a list, nodes have no children. */
 	if (parent)
 		return FALSE;
@@ -1133,6 +1344,11 @@ e_contact_store_iter_children (GtkTreeModel *tree_model,
 		return FALSE;
 
 	ITER_SET (contact_store, iter, 0);
+		
+	if (priv->expand_contacts) {
+		set_iter_metadata (contact_store, iter, 0);
+	}
+
 	return TRUE;
 }
 
@@ -1170,14 +1386,22 @@ e_contact_store_iter_nth_child (GtkTreeModel *tree_model,
 				gint          n)
 {
 	EContactStore *contact_store = E_CONTACT_STORE (tree_model);
+	EContactStorePrivate *priv;
 
 	g_return_val_if_fail (E_IS_CONTACT_STORE (tree_model), FALSE);
 
+	priv = E_CONTACT_STORE_GET_PRIVATE (contact_store);
+
 	if (parent)
 		return FALSE;
 
 	if (n < count_contacts (contact_store)) {
 		ITER_SET (contact_store, iter, n);
+		
+		if (priv->expand_contacts) {
+			set_iter_metadata (contact_store, iter, n);
+		}
+
 		return TRUE;
 	}
 
diff --git a/libedataserverui/e-name-selector-dialog.c b/libedataserverui/e-name-selector-dialog.c
index c64a93b..1d08c4b 100644
--- a/libedataserverui/e-name-selector-dialog.c
+++ b/libedataserverui/e-name-selector-dialog.c
@@ -366,18 +366,13 @@ static void
 sort_iter_to_contact_store_iter (ENameSelectorDialog *name_selector_dialog, GtkTreeIter *iter,
 				 gint *email_n)
 {
-	ETreeModelGenerator *contact_filter;
 	GtkTreeIter          child_iter;
-	gint                 email_n_local;
-
-	contact_filter = e_name_selector_model_peek_contact_filter (name_selector_dialog->name_selector_model);
 
 	gtk_tree_model_sort_convert_iter_to_child_iter (name_selector_dialog->contact_sort,
 							&child_iter, iter);
-	e_tree_model_generator_convert_iter_to_child_iter (contact_filter, iter, &email_n_local, &child_iter);
-
+	*iter = child_iter;
 	if (email_n)
-		*email_n = email_n_local;
+		*email_n = GPOINTER_TO_INT (iter->user_data2);
 }
 
 static void
@@ -1044,7 +1039,6 @@ static void
 setup_name_selector_model (ENameSelectorDialog *name_selector_dialog)
 {
 	EContactStore       *contact_store;
-	ETreeModelGenerator *contact_filter;
 	GList               *new_sections;
 	GList               *l;
 
@@ -1078,12 +1072,11 @@ setup_name_selector_model (ENameSelectorDialog *name_selector_dialog)
 	/* Get contact store and its filter wrapper */
 
 	contact_store  = e_name_selector_model_peek_contact_store  (name_selector_dialog->name_selector_model);
-	contact_filter = e_name_selector_model_peek_contact_filter (name_selector_dialog->name_selector_model);
 
 	/* Create sorting model on top of filter, assign it to view */
 
 	name_selector_dialog->contact_sort = GTK_TREE_MODEL_SORT (
-		gtk_tree_model_sort_new_with_model (GTK_TREE_MODEL (contact_filter)));
+		gtk_tree_model_sort_new_with_model (GTK_TREE_MODEL (contact_store)));
 
 	/* sort on full name as we display full name in name selector dialog */
 	gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE (name_selector_dialog->contact_sort),
