[evolution/account-mgmt: 21/33] Adapt modules/addressbook to the new ESource API.



commit 30afc382496e00f38684a42cd5bafc9c50f59369
Author: Matthew Barnes <mbarnes redhat com>
Date:   Sun Dec 19 09:52:40 2010 -0500

    Adapt modules/addressbook to the new ESource API.

 modules/addressbook/Makefile.am                 |    2 -
 modules/addressbook/addressbook-config.c        | 1241 -----------------------
 modules/addressbook/addressbook-config.h        |   53 -
 modules/addressbook/autocompletion-config.c     |   98 +--
 modules/addressbook/e-book-shell-backend.c      |  197 +---
 modules/addressbook/e-book-shell-backend.h      |    3 -
 modules/addressbook/e-book-shell-content.c      |    8 +
 modules/addressbook/e-book-shell-migrate.c      |  186 ----
 modules/addressbook/e-book-shell-sidebar.c      |   30 +-
 modules/addressbook/e-book-shell-view-actions.c |   93 +-
 modules/addressbook/e-book-shell-view-private.c |   58 +-
 modules/addressbook/e-book-shell-view-private.h |   14 +-
 modules/addressbook/e-book-shell-view.c         |   63 --
 widgets/misc/Makefile.am                        |    2 +
 widgets/misc/e-autocomplete-selector.c          |  104 ++
 widgets/misc/e-autocomplete-selector.h          |   64 ++
 16 files changed, 330 insertions(+), 1886 deletions(-)
---
diff --git a/modules/addressbook/Makefile.am b/modules/addressbook/Makefile.am
index 35cf16a..230db18 100644
--- a/modules/addressbook/Makefile.am
+++ b/modules/addressbook/Makefile.am
@@ -25,8 +25,6 @@ libevolution_module_addressbook_la_CPPFLAGS =			\
 
 libevolution_module_addressbook_la_SOURCES = \
 	evolution-module-addressbook.c				\
-	addressbook-config.c					\
-	addressbook-config.h					\
 	autocompletion-config.c					\
 	autocompletion-config.h					\
 	eab-composer-util.c					\
diff --git a/modules/addressbook/autocompletion-config.c b/modules/addressbook/autocompletion-config.c
index 05b2b98..3f42bd0 100644
--- a/modules/addressbook/autocompletion-config.c
+++ b/modules/addressbook/autocompletion-config.c
@@ -26,70 +26,13 @@
 
 #include <gtk/gtk.h>
 #include <glib/gi18n.h>
-#include <libedataserver/e-source-list.h>
+#include <libebook/e-source-address-book.h>
+#include <libedataserver/e-source-autocomplete.h>
 #include <libedataserverui/e-source-selector.h>
 #include <libedataserverui/e-name-selector-entry.h>
 
 #include "e-util/e-datetime-format.h"
-
-static void
-source_selection_changed_cb (ESourceSelector *source_selector)
-{
-	ESourceList *source_list;
-	GSList *selection;
-	GSList *l;
-	GSList *groups;
-
-	source_list = e_source_selector_get_source_list (source_selector);
-
-	/* first we clear all the completion flags from all sources */
-	for (groups = e_source_list_peek_groups (source_list); groups; groups = groups->next) {
-		ESourceGroup *group = E_SOURCE_GROUP (groups->data);
-		GSList *sources;
-
-		for (sources = e_source_group_peek_sources (group); sources; sources = sources->next) {
-			ESource *source = E_SOURCE (sources->data);
-
-			e_source_set_property (source, "completion", NULL);
-		}
-	}
-
-	/* then we loop over the selector's selection, setting the
-	   property on those sources */
-	selection = e_source_selector_get_selection (source_selector);
-	for (l = selection; l; l = l->next) {
-		ESource *source = E_SOURCE (l->data);
-
-		e_source_set_property (source, "completion", "true");
-	}
-	e_source_selector_free_selection (selection);
-
-	/* XXX we should pop up a dialog if this fails */
-	e_source_list_sync (source_list, NULL);
-}
-
-static void
-initialize_selection (ESourceSelector *source_selector)
-{
-	ESourceList *source_list;
-	GSList *groups;
-
-	source_list = e_source_selector_get_source_list (source_selector);
-
-	for (groups = e_source_list_peek_groups (source_list); groups; groups = groups->next) {
-		ESourceGroup *group = E_SOURCE_GROUP (groups->data);
-		GSList *sources;
-
-		for (sources = e_source_group_peek_sources (group); sources; sources = sources->next) {
-			ESource *source = E_SOURCE (sources->data);
-			const gchar *completion;
-
-			completion = e_source_get_property (source, "completion");
-			if (completion && !g_ascii_strcasecmp (completion, "true"))
-				e_source_selector_select_source (source_selector, source);
-		}
-	}
-}
+#include "misc/e-autocomplete-selector.h"
 
 static GtkWidget *
 add_section (GtkWidget *container,
@@ -131,9 +74,8 @@ GtkWidget *
 autocompletion_config_new (EPreferencesWindow *window)
 {
 	EShellSettings *shell_settings;
-	ESourceList *source_list;
-	GtkWidget *scrolled_window;
-	GtkWidget *source_selector;
+	ESourceRegistry *registry;
+	GtkWidget *container;
 	GtkWidget *itembox;
 	GtkWidget *widget;
 	GtkWidget *vbox;
@@ -145,11 +87,7 @@ autocompletion_config_new (EPreferencesWindow *window)
 
 	shell_settings = e_shell_get_shell_settings (shell);
 
-	source_list = e_source_list_new_for_gconf_default (
-		"/apps/evolution/addressbook/sources");
-
 	vbox = gtk_vbox_new (FALSE, 12);
-	gtk_container_set_border_width (GTK_CONTAINER (vbox), 12);
 	gtk_widget_show (vbox);
 
 	itembox = add_section (vbox, _("Date/Time Format"), FALSE);
@@ -173,23 +111,21 @@ autocompletion_config_new (EPreferencesWindow *window)
 	gtk_box_pack_start (GTK_BOX (itembox), widget, FALSE, FALSE, 0);
 	gtk_widget_show (widget);
 
-	scrolled_window = gtk_scrolled_window_new (NULL, NULL);
+	widget = gtk_scrolled_window_new (NULL, NULL);
 	gtk_scrolled_window_set_policy (
-		GTK_SCROLLED_WINDOW (scrolled_window),
+		GTK_SCROLLED_WINDOW (widget),
 		GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
 	gtk_scrolled_window_set_shadow_type (
-		GTK_SCROLLED_WINDOW (scrolled_window), GTK_SHADOW_IN);
-	gtk_widget_show (scrolled_window);
-
-	source_selector = e_source_selector_new (source_list);
-	initialize_selection (E_SOURCE_SELECTOR (source_selector));
-	g_signal_connect (
-		source_selector, "selection_changed",
-		G_CALLBACK (source_selection_changed_cb), NULL);
-	gtk_container_add (GTK_CONTAINER (scrolled_window), source_selector);
-	gtk_widget_show (source_selector);
-
-	gtk_box_pack_start (GTK_BOX (itembox), scrolled_window, TRUE, TRUE, 0);
+		GTK_SCROLLED_WINDOW (widget), GTK_SHADOW_IN);
+	gtk_box_pack_start (GTK_BOX (itembox), widget, TRUE, TRUE, 0);
+	gtk_widget_show (widget);
+
+	container = widget;
+
+	registry = e_source_registry_get_default ();
+	widget = e_autocomplete_selector_new (registry);
+	gtk_container_add (GTK_CONTAINER (container), widget);
+	gtk_widget_show (widget);
 
 	return vbox;
 }
diff --git a/modules/addressbook/e-book-shell-backend.c b/modules/addressbook/e-book-shell-backend.c
index 4de5d1e..adfa66f 100644
--- a/modules/addressbook/e-book-shell-backend.c
+++ b/modules/addressbook/e-book-shell-backend.c
@@ -26,23 +26,24 @@
 #include <string.h>
 #include <glib/gi18n.h>
 #include <libebook/e-book.h>
+#include <libebook/e-source-address-book.h>
 #include <libedataserver/e-url.h>
 #include <libedataserver/e-source.h>
-#include <libedataserver/e-source-group.h>
 #include <libedataserverui/e-book-auth-util.h>
 
 #include "e-util/e-import.h"
 #include "shell/e-shell.h"
 #include "shell/e-shell-window.h"
 #include "widgets/misc/e-preferences-window.h"
+#include "widgets/misc/e-source-config-dialog.h"
 
 #include "addressbook/gui/widgets/eab-gui-util.h"
+#include "addressbook/gui/widgets/e-book-source-config.h"
 #include "addressbook/gui/contact-editor/e-contact-editor.h"
 #include "addressbook/gui/contact-editor/e-contact-quick-add.h"
 #include "addressbook/gui/contact-list-editor/e-contact-list-editor.h"
 #include "addressbook/importers/evolution-addressbook-importers.h"
 
-#include "addressbook-config.h"
 #include "autocompletion-config.h"
 
 #include "e-book-shell-migrate.h"
@@ -55,79 +56,13 @@
 #endif
 
 struct _EBookShellBackendPrivate {
-	ESourceList *source_list;
-};
-
-enum {
-	PROP_0,
-	PROP_SOURCE_LIST
+	gint placeholder;
 };
 
 static gpointer parent_class;
 static GType book_shell_backend_type;
 
 static void
-book_shell_backend_ensure_sources (EShellBackend *shell_backend)
-{
-	/* XXX This is basically the same algorithm across all backends.
-	 *     Maybe we could somehow integrate this into EShellBackend? */
-
-	EBookShellBackendPrivate *priv;
-	ESourceGroup *on_this_computer;
-	ESource *personal;
-	GSList *sources, *iter;
-	const gchar *name;
-
-	on_this_computer = NULL;
-	personal = NULL;
-
-	priv = E_BOOK_SHELL_BACKEND (shell_backend)->priv;
-
-	if (!e_book_get_addressbooks (&priv->source_list, NULL)) {
-		g_warning ("Could not get addressbook sources from GConf!");
-		return;
-	}
-
-	on_this_computer = e_source_list_ensure_group (
-		priv->source_list, _("On This Computer"), "local:", TRUE);
-	e_source_list_ensure_group (
-		priv->source_list, _("On LDAP Servers"), "ldap://";, FALSE);
-
-	g_return_if_fail (on_this_computer != NULL);
-
-	sources = e_source_group_peek_sources (on_this_computer);
-
-	/* Make sure this group includes a "Personal" source. */
-	for (iter = sources; iter != NULL; iter = iter->next) {
-		ESource *source = iter->data;
-		const gchar *relative_uri;
-
-		relative_uri = e_source_peek_relative_uri (source);
-		if (g_strcmp0 (relative_uri, "system") == 0) {
-			personal = source;
-			break;
-		}
-	}
-
-	name = _("Personal");
-
-	if (personal == NULL) {
-		ESource *source;
-
-		/* Create the default Personal address book. */
-		source = e_source_new (name, "system");
-		e_source_group_add_source (on_this_computer, source, -1);
-		e_source_set_property (source, "completion", "true");
-		g_object_unref (source);
-	} else {
-		/* Force the source name to the current locale. */
-		e_source_set_name (personal, name);
-	}
-
-	g_object_unref (on_this_computer);
-}
-
-static void
 book_shell_backend_init_importers (void)
 {
 	EImportClass *import_class;
@@ -159,12 +94,17 @@ book_shell_backend_new_contact_cb (ESource *source,
 	EBook *book;
 	EContact *contact;
 	EABEditor *editor;
+	GError *error = NULL;
 
-	book = e_load_book_source_finish (source, result, NULL);
+	book = e_load_book_source_finish (source, result, &error);
 
 	/* XXX Handle errors better. */
-	if (book == NULL)
+	if (error != NULL) {
+		g_warn_if_fail (book == NULL);
+		g_warning ("%s", error->message);
+		g_error_free (error);
 		goto exit;
+	}
 
 	contact = e_contact_new ();
 
@@ -188,12 +128,17 @@ book_shell_backend_new_contact_list_cb (ESource *source,
 	EBook *book;
 	EContact *contact;
 	EABEditor *editor;
+	GError *error = NULL;
 
-	book = e_load_book_source_finish (source, result, NULL);
+	book = e_load_book_source_finish (source, result, &error);
 
 	/* XXX Handle errors better. */
-	if (book == NULL)
+	if (error != NULL) {
+		g_warn_if_fail (book == NULL);
+		g_warning ("%s", error->message);
+		g_error_free (error);
 		goto exit;
+	}
 
 	contact = e_contact_new ();
 
@@ -214,35 +159,16 @@ action_contact_new_cb (GtkAction *action,
                        EShellWindow *shell_window)
 {
 	EShell *shell;
-	EShellBackend *shell_backend;
-	GConfClient *client;
-	ESourceList *source_list;
-	ESource *source = NULL;
+	ESource *source;
+	ESourceRegistry *registry;
 	const gchar *action_name;
-	const gchar *key;
-	gchar *uid;
 
 	/* This callback is used for both contacts and contact lists. */
 
 	shell = e_shell_window_get_shell (shell_window);
-	shell_backend = e_shell_get_backend_by_name (shell, "addressbook");
-
-	g_object_get (shell_backend, "source-list", &source_list, NULL);
-	g_return_if_fail (E_IS_SOURCE_LIST (source_list));
 
-	client = e_shell_get_gconf_client (shell);
-	key = "/apps/evolution/addressbook/display/primary_addressbook";
-	uid = gconf_client_get_string (client, key, NULL);
-
-	if (uid != NULL) {
-		source = e_source_list_peek_source_by_uid (source_list, uid);
-		g_free (uid);
-	}
-
-	if (source == NULL)
-		source = e_source_list_peek_default_source (source_list);
-
-	g_return_if_fail (E_IS_SOURCE (source));
+	registry = e_source_registry_get_default ();
+	source = e_source_registry_get_default_address_book (registry);
 
 	/* Use a callback function appropriate for the action. */
 	action_name = gtk_action_get_name (action);
@@ -258,15 +184,31 @@ action_contact_new_cb (GtkAction *action,
 			NULL, (GAsyncReadyCallback)
 			book_shell_backend_new_contact_list_cb,
 			g_object_ref (shell));
-
-	g_object_unref (source_list);
 }
 
 static void
 action_address_book_new_cb (GtkAction *action,
                             EShellWindow *shell_window)
 {
-	addressbook_config_create_new_source (NULL);
+	ESourceRegistry *registry;
+	GtkWidget *config;
+	GtkWidget *dialog;
+	const gchar *icon_name;
+
+	registry = e_source_registry_get_default ();
+	config = e_book_source_config_new (registry, NULL);
+
+	dialog = e_source_config_dialog_new (
+		E_SOURCE_CONFIG (config), GTK_WINDOW (shell_window));
+
+	icon_name = gtk_action_get_icon_name (action);
+	gtk_window_set_icon_name (GTK_WINDOW (dialog), icon_name);
+
+	gtk_window_set_title (GTK_WINDOW (dialog), _("New Address Book"));
+
+	gtk_dialog_run (GTK_DIALOG (dialog));
+
+	gtk_widget_destroy (dialog);
 }
 
 static GtkActionEntry item_entries[] = {
@@ -434,40 +376,6 @@ book_shell_backend_window_created_cb (EShellBackend *shell_backend,
 }
 
 static void
-book_shell_backend_get_property (GObject *object,
-                                 guint property_id,
-                                 GValue *value,
-                                 GParamSpec *pspec)
-{
-	switch (property_id) {
-		case PROP_SOURCE_LIST:
-			g_value_set_object (
-				value,
-				e_book_shell_backend_get_source_list (
-				E_BOOK_SHELL_BACKEND (object)));
-			return;
-	}
-
-	G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
-}
-
-static void
-book_shell_backend_dispose (GObject *object)
-{
-	EBookShellBackendPrivate *priv;
-
-	priv = E_BOOK_SHELL_BACKEND (object)->priv;
-
-	if (priv->source_list != NULL) {
-		g_object_unref (priv->source_list);
-		priv->source_list = NULL;
-	}
-
-	/* Chain up to parent's dispose() method. */
-	G_OBJECT_CLASS (parent_class)->dispose (object);
-}
-
-static void
 book_shell_backend_constructed (GObject *object)
 {
 	EShell *shell;
@@ -483,7 +391,6 @@ book_shell_backend_constructed (GObject *object)
 #endif
 
 	book_shell_backend_init_importers ();
-	book_shell_backend_ensure_sources (shell_backend);
 
 	g_signal_connect (
 		shell, "event::contact-quick-add-email",
@@ -523,8 +430,6 @@ book_shell_backend_class_init (EBookShellBackendClass *class)
 	g_type_class_add_private (class, sizeof (EBookShellBackendPrivate));
 
 	object_class = G_OBJECT_CLASS (class);
-	object_class->get_property = book_shell_backend_get_property;
-	object_class->dispose = book_shell_backend_dispose;
 	object_class->constructed = book_shell_backend_constructed;
 
 	shell_backend_class = E_SHELL_BACKEND_CLASS (class);
@@ -537,15 +442,8 @@ book_shell_backend_class_init (EBookShellBackendClass *class)
 	shell_backend_class->start = NULL;
 	shell_backend_class->migrate = e_book_shell_backend_migrate;
 
-	g_object_class_install_property (
-		object_class,
-		PROP_SOURCE_LIST,
-		g_param_spec_object (
-			"source-list",
-			"Source List",
-			"The registry of address books",
-			E_TYPE_SOURCE_LIST,
-			G_PARAM_READABLE));
+	/* Register relevant ESource extensions. */
+	E_TYPE_SOURCE_ADDRESS_BOOK;
 }
 
 static void
@@ -582,12 +480,3 @@ e_book_shell_backend_register_type (GTypeModule *type_module)
 		type_module, E_TYPE_SHELL_BACKEND,
 		"EBookShellBackend", &type_info, 0);
 }
-
-ESourceList *
-e_book_shell_backend_get_source_list (EBookShellBackend *book_shell_backend)
-{
-	g_return_val_if_fail (
-		E_IS_BOOK_SHELL_BACKEND (book_shell_backend), NULL);
-
-	return book_shell_backend->priv->source_list;
-}
diff --git a/modules/addressbook/e-book-shell-backend.h b/modules/addressbook/e-book-shell-backend.h
index c61e43b..679e8be 100644
--- a/modules/addressbook/e-book-shell-backend.h
+++ b/modules/addressbook/e-book-shell-backend.h
@@ -23,7 +23,6 @@
 #define E_BOOK_SHELL_BACKEND_H
 
 #include <shell/e-shell-backend.h>
-#include <libedataserver/e-source-list.h>
 
 /* Standard GObject macros */
 #define E_TYPE_BOOK_SHELL_BACKEND \
@@ -62,8 +61,6 @@ struct _EBookShellBackendClass {
 GType		e_book_shell_backend_get_type	(void);
 void		e_book_shell_backend_register_type
 					(GTypeModule *type_module);
-ESourceList *	e_book_shell_backend_get_source_list
-					(EBookShellBackend *book_shell_backend);
 
 G_END_DECLS
 
diff --git a/modules/addressbook/e-book-shell-content.c b/modules/addressbook/e-book-shell-content.c
index 4f39051..9e5a045 100644
--- a/modules/addressbook/e-book-shell-content.c
+++ b/modules/addressbook/e-book-shell-content.c
@@ -322,6 +322,7 @@ book_shell_content_check_state (EShellContent *shell_content)
 	ESelectionModel *selection_model;
 	EAddressbookModel *model;
 	EAddressbookView *view;
+	GtkNotebook *notebook;
 	gboolean has_email = TRUE;
 	gboolean is_contact_list = TRUE;
 	guint32 state = 0;
@@ -333,6 +334,13 @@ book_shell_content_check_state (EShellContent *shell_content)
 	} foreach_data;
 
 	book_shell_content = E_BOOK_SHELL_CONTENT (shell_content);
+
+	/* This function may be triggered at startup before any address
+	 * book views are added.  Check for that and return silently. */
+	notebook = GTK_NOTEBOOK (book_shell_content->priv->notebook);
+	if (gtk_notebook_get_n_pages (notebook) == 0)
+		return 0;
+
 	view = e_book_shell_content_get_current_view (book_shell_content);
 	model = e_addressbook_view_get_model (view);
 
diff --git a/modules/addressbook/e-book-shell-migrate.c b/modules/addressbook/e-book-shell-migrate.c
index 7b91a04..83491b5 100644
--- a/modules/addressbook/e-book-shell-migrate.c
+++ b/modules/addressbook/e-book-shell-migrate.c
@@ -22,171 +22,8 @@
  *
  */
 
-#include <config.h>
-
-#include <string.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <unistd.h>
-#include <fcntl.h>
-#include <errno.h>
-
-#include <glib.h>
-#include <glib/gstdio.h>
-
-#include <gtk/gtk.h>
-
-#include <libebook/e-destination.h>
-#include <libebook/e-book.h>
-#include <glib/gi18n.h>
-
-#include <libedataserver/e-xml-utils.h>
-
-#include "e-util/e-util.h"
-#include "e-util/e-util-private.h"
-#include "e-util/e-xml-utils.h"
-
 #include "e-book-shell-migrate.h"
 
-/*#define SLOW_MIGRATION*/
-
-typedef struct {
-	/* this hash table maps old folder uris to new uids.  It's
-	   build in migrate_contact_folder and it's used in
-	   migrate_completion_folders. */
-	GHashTable *folder_uid_map;
-
-	ESourceList *source_list;
-
-	const gchar *data_dir;
-
-	GtkWidget *window;
-	GtkWidget *label;
-	GtkWidget *folder_label;
-	GtkWidget *progress;
-} MigrationContext;
-
-#define LOCAL_BASE_URI "local:"
-#define LDAP_BASE_URI "ldap://";
-#define PERSONAL_RELATIVE_URI "system"
-
-static void
-create_groups (MigrationContext *context,
-	       ESourceGroup **on_this_computer,
-	       ESourceGroup **on_ldap_servers,
-	       ESource      **personal_source)
-{
-	GSList *groups;
-	ESourceGroup *group;
-
-	*on_this_computer = NULL;
-	*on_ldap_servers = NULL;
-	*personal_source = NULL;
-
-	groups = e_source_list_peek_groups (context->source_list);
-	if (groups) {
-		/* groups are already there, we need to search for things... */
-		GSList *g;
-		gchar *base_dir, *base_uri;
-
-		base_dir = g_build_filename (context->data_dir, "local", NULL);
-		base_uri = g_filename_to_uri (base_dir, NULL, NULL);
-
-		for (g = groups; g; g = g->next) {
-			group = E_SOURCE_GROUP (g->data);
-
-			if (strcmp (base_uri, e_source_group_peek_base_uri (group)) == 0)
-				e_source_group_set_base_uri (group, LOCAL_BASE_URI);
-
-			if (!*on_this_computer &&
-					!strcmp (LOCAL_BASE_URI,
-					e_source_group_peek_base_uri (group)))
-				*on_this_computer = g_object_ref (group);
-			else if (!*on_ldap_servers &&
-					!strcmp (LDAP_BASE_URI,
-					e_source_group_peek_base_uri (group)))
-				*on_ldap_servers = g_object_ref (group);
-		}
-
-		g_free (base_dir);
-		g_free (base_uri);
-	}
-
-	if (*on_this_computer) {
-		/* make sure "Personal" shows up as a source under
-		   this group */
-		GSList *sources = e_source_group_peek_sources (*on_this_computer);
-		GSList *s;
-		for (s = sources; s; s = s->next) {
-			ESource *source = E_SOURCE (s->data);
-			const gchar *relative_uri;
-
-			relative_uri = e_source_peek_relative_uri (source);
-			if (relative_uri == NULL)
-				continue;
-			if (!strcmp (PERSONAL_RELATIVE_URI, relative_uri)) {
-				*personal_source = g_object_ref (source);
-				break;
-			}
-		}
-	}
-	else {
-		/* create the local source group */
-		group = e_source_group_new (_("On This Computer"), LOCAL_BASE_URI);
-		e_source_list_add_group (context->source_list, group, -1);
-
-		*on_this_computer = group;
-	}
-
-	if (!*personal_source) {
-		/* Create the default Person addressbook */
-		ESource *source = e_source_new (_("Personal"), PERSONAL_RELATIVE_URI);
-		e_source_group_add_source (*on_this_computer, source, -1);
-
-		e_source_set_property (source, "completion", "true");
-
-		*personal_source = source;
-	}
-
-	if (!*on_ldap_servers) {
-		/* Create the LDAP source group */
-		group = e_source_group_new (_("On LDAP Servers"), LDAP_BASE_URI);
-		e_source_list_add_group (context->source_list, group, -1);
-
-		*on_ldap_servers = group;
-	}
-}
-
-static MigrationContext *
-migration_context_new (const gchar *data_dir)
-{
-	MigrationContext *context = g_new (MigrationContext, 1);
-
-	/* set up the mapping from old uris to new uids */
-	context->folder_uid_map = g_hash_table_new_full (
-		g_str_hash, g_str_equal,
-		(GDestroyNotify) g_free,
-		(GDestroyNotify) g_free);
-
-	e_book_get_addressbooks (&context->source_list, NULL);
-
-	context->data_dir = data_dir;
-
-	return context;
-}
-
-static void
-migration_context_free (MigrationContext *context)
-{
-	e_source_list_sync (context->source_list, NULL);
-
-	g_hash_table_destroy (context->folder_uid_map);
-
-	g_object_unref (context->source_list);
-
-	g_free (context);
-}
-
 gboolean
 e_book_shell_backend_migrate (EShellBackend *shell_backend,
                               gint major,
@@ -194,30 +31,7 @@ e_book_shell_backend_migrate (EShellBackend *shell_backend,
                               gint micro,
                               GError **error)
 {
-	ESourceGroup *on_this_computer;
-	ESourceGroup *on_ldap_servers;
-	ESource *personal_source;
-	MigrationContext *context;
-	const gchar *data_dir;
-
 	g_return_val_if_fail (E_IS_SHELL_BACKEND (shell_backend), FALSE);
 
-	data_dir = e_shell_backend_get_data_dir (shell_backend);
-	context = migration_context_new (data_dir);
-
-	/* we call this unconditionally now - create_groups either
-	   creates the groups/sources or it finds the necessary
-	   groups/sources. */
-	create_groups (context, &on_this_computer, &on_ldap_servers, &personal_source);
-
-	if (on_this_computer)
-		g_object_unref (on_this_computer);
-	if (on_ldap_servers)
-		g_object_unref (on_ldap_servers);
-	if (personal_source)
-		g_object_unref (personal_source);
-
-	migration_context_free (context);
-
 	return TRUE;
 }
diff --git a/modules/addressbook/e-book-shell-sidebar.c b/modules/addressbook/e-book-shell-sidebar.c
index 5505563..36ea3ef 100644
--- a/modules/addressbook/e-book-shell-sidebar.c
+++ b/modules/addressbook/e-book-shell-sidebar.c
@@ -23,6 +23,7 @@
 
 #include <string.h>
 #include <glib/gi18n.h>
+#include <libebook/e-source-address-book.h>
 
 #include <e-util/e-util.h>
 
@@ -84,7 +85,7 @@ book_shell_sidebar_constructed (GObject *object)
 	EShellBackend *shell_backend;
 	EShellSidebar *shell_sidebar;
 	EShellSettings *shell_settings;
-	ESourceList *source_list;
+	ESourceRegistry *registry;
 	GtkContainer *container;
 	GtkWidget *widget;
 
@@ -100,9 +101,6 @@ book_shell_sidebar_constructed (GObject *object)
 	shell = e_shell_backend_get_shell (shell_backend);
 	shell_settings = e_shell_get_shell_settings (shell);
 
-	source_list = e_book_shell_backend_get_source_list (
-		E_BOOK_SHELL_BACKEND (shell_backend));
-
 	container = GTK_CONTAINER (shell_sidebar);
 
 	widget = gtk_scrolled_window_new (NULL, NULL);
@@ -116,8 +114,8 @@ book_shell_sidebar_constructed (GObject *object)
 
 	container = GTK_CONTAINER (widget);
 
-	widget = e_addressbook_selector_new (source_list);
-	e_source_selector_show_selection (E_SOURCE_SELECTOR (widget), FALSE);
+	registry = e_source_registry_get_default ();
+	widget = e_addressbook_selector_new (registry);
 	gtk_container_add (GTK_CONTAINER (container), widget);
 	priv->selector = g_object_ref (widget);
 	gtk_widget_show (widget);
@@ -129,7 +127,7 @@ book_shell_sidebar_constructed (GObject *object)
 		G_BINDING_SYNC_CREATE,
 		(GBindingTransformFunc) e_binding_transform_uid_to_source,
 		(GBindingTransformFunc) e_binding_transform_source_to_uid,
-		g_object_ref (source_list),
+		g_object_ref (registry),
 		(GDestroyNotify) g_object_unref);
 }
 
@@ -148,15 +146,19 @@ book_shell_sidebar_check_state (EShellSidebar *shell_sidebar)
 	source = e_source_selector_get_primary_selection (selector);
 
 	if (source != NULL) {
-		const gchar *uri;
-		const gchar *delete;
+		ESourceSelectable *extension;
+		gboolean writable_hint;
+		const gchar *uid;
+
+		uid = e_source_get_uid (source);
+		is_system = (g_strcmp0 (uid, "system") == 0);
 
-		uri = e_source_peek_relative_uri (source);
-		is_system = (uri == NULL || strcmp (uri, "system") == 0);
+		extension = e_source_get_extension (
+			source, E_SOURCE_EXTENSION_ADDRESS_BOOK);
+		writable_hint =
+			e_source_selectable_get_writable_hint (extension);
 
-		can_delete = !is_system;
-		delete = e_source_get_property (source, "delete");
-		can_delete &= (delete == NULL || strcmp (delete, "no") != 0);
+		can_delete = !is_system && writable_hint;
 	}
 
 	if (source != NULL)
diff --git a/modules/addressbook/e-book-shell-view-actions.c b/modules/addressbook/e-book-shell-view-actions.c
index b2c63b8..d1c0b46 100644
--- a/modules/addressbook/e-book-shell-view-actions.c
+++ b/modules/addressbook/e-book-shell-view-actions.c
@@ -25,8 +25,6 @@
 #include <e-util/e-util.h>
 #include <filter/e-filter-rule.h>
 
-#include <addressbook-config.h>
-
 static void
 action_address_book_copy_cb (GtkAction *action,
                              EBookShellView *book_shell_view)
@@ -47,22 +45,15 @@ action_address_book_delete_cb (GtkAction *action,
 {
 	EShellView *shell_view;
 	EShellWindow *shell_window;
-	EBookShellBackend *book_shell_backend;
 	EBookShellSidebar *book_shell_sidebar;
 	ESource *source;
 	ESourceSelector *selector;
-	ESourceGroup *source_group;
-	ESourceList *source_list;
-	EBook *book;
+	GFile *file;
 	gint response;
-	GError *error = NULL;
 
 	shell_view = E_SHELL_VIEW (book_shell_view);
 	shell_window = e_shell_view_get_shell_window (shell_view);
 
-	book_shell_backend = book_shell_view->priv->book_shell_backend;
-	source_list = e_book_shell_backend_get_source_list (book_shell_backend);
-
 	book_shell_sidebar = book_shell_view->priv->book_shell_sidebar;
 	selector = e_book_shell_sidebar_get_selector (book_shell_sidebar);
 	source = e_source_selector_get_primary_selection (selector);
@@ -71,35 +62,14 @@ action_address_book_delete_cb (GtkAction *action,
 	response = e_alert_run_dialog_for_args (
 		GTK_WINDOW (shell_window),
 		"addressbook:ask-delete-addressbook",
-		e_source_peek_name (source), NULL);
+		e_source_get_display_name (source), NULL);
 
 	if (response != GTK_RESPONSE_YES)
 		return;
 
-	book = e_book_new (source, &error);
-	if (error != NULL) {
-		g_warning ("Error removing addressbook: %s", error->message);
-		g_error_free (error);
-		return;
-	}
-
-	if (!e_book_remove (book, NULL)) {
-		e_alert_run_dialog_for_args (
-			GTK_WINDOW (shell_window),
-			"addressbook:remove-addressbook", NULL);
-		g_object_unref (book);
-		return;
-	}
-
-	if (e_source_selector_source_is_selected (selector, source))
-		e_source_selector_unselect_source (selector, source);
-
-	source_group = e_source_peek_group (source);
-	e_source_group_remove_source (source_group, source);
-
-	e_source_list_sync (source_list, NULL);
-
-	g_object_unref (book);
+	/* FIXME Handle errors. */
+	file = e_source_get_file (source);
+	g_file_delete (file, NULL, NULL);
 }
 
 static void
@@ -122,11 +92,28 @@ action_address_book_new_cb (GtkAction *action,
 {
 	EShellView *shell_view;
 	EShellWindow *shell_window;
+	ESourceRegistry *registry;
+	GtkWidget *config;
+	GtkWidget *dialog;
+	const gchar *icon_name;
 
 	shell_view = E_SHELL_VIEW (book_shell_view);
 	shell_window = e_shell_view_get_shell_window (shell_view);
 
-	addressbook_config_create_new_source (GTK_WIDGET (shell_window));
+	registry = e_source_registry_get_default ();
+	config = e_book_source_config_new (registry, NULL);
+
+	dialog = e_source_config_dialog_new (
+		E_SOURCE_CONFIG (config), GTK_WINDOW (shell_window));
+
+	icon_name = gtk_action_get_icon_name (action);
+	gtk_window_set_icon_name (GTK_WINDOW (dialog), icon_name);
+
+	gtk_window_set_title (GTK_WINDOW (dialog), _("New Address Book"));
+
+	gtk_dialog_run (GTK_DIALOG (dialog));
+
+	gtk_widget_destroy (dialog);
 }
 
 static void
@@ -170,9 +157,10 @@ action_address_book_properties_cb (GtkAction *action,
 	EBookShellSidebar *book_shell_sidebar;
 	ESource *source;
 	ESourceSelector *selector;
-	EditorUidClosure *closure;
-	GHashTable *uid_to_editor;
-	const gchar *uid;
+	ESourceRegistry *registry;
+	GtkWidget *config;
+	GtkWidget *dialog;
+	const gchar *icon_name;
 
 	shell_view = E_SHELL_VIEW (book_shell_view);
 	shell_window = e_shell_view_get_shell_window (shell_view);
@@ -182,29 +170,20 @@ action_address_book_properties_cb (GtkAction *action,
 	source = e_source_selector_get_primary_selection (selector);
 	g_return_if_fail (source != NULL);
 
-	uid = e_source_peek_uid (source);
-	uid_to_editor = book_shell_view->priv->uid_to_editor;
+	registry = e_source_selector_get_registry (selector);
+	config = e_book_source_config_new (registry, source);
 
-	closure = g_hash_table_lookup (uid_to_editor, uid);
-	if (closure == NULL) {
-		GtkWidget *editor;
+	dialog = e_source_config_dialog_new (
+		E_SOURCE_CONFIG (config), GTK_WINDOW (shell_window));
 
-		editor = addressbook_config_edit_source (
-			GTK_WIDGET (shell_window), source);
+	icon_name = gtk_action_get_icon_name (action);
+	gtk_window_set_icon_name (GTK_WINDOW (dialog), icon_name);
 
-		closure = g_new (EditorUidClosure, 1);
-		closure->editor = editor;
-		closure->uid = g_strdup (uid);
-		closure->view = book_shell_view;
+	gtk_window_set_title (GTK_WINDOW (dialog), _("Address Book Properties"));
 
-		g_hash_table_insert (uid_to_editor, closure->uid, closure);
-
-		g_object_weak_ref (
-			G_OBJECT (closure->editor), (GWeakNotify)
-			e_book_shell_view_editor_weak_notify, closure);
-	}
+	gtk_dialog_run (GTK_DIALOG (dialog));
 
-	gtk_window_present (GTK_WINDOW (closure->editor));
+	gtk_widget_destroy (dialog);
 }
 
 static void
diff --git a/modules/addressbook/e-book-shell-view-private.c b/modules/addressbook/e-book-shell-view-private.c
index 9228905..a7bcd83 100644
--- a/modules/addressbook/e-book-shell-view-private.c
+++ b/modules/addressbook/e-book-shell-view-private.c
@@ -238,7 +238,7 @@ book_shell_view_activate_selected_source (EBookShellView *book_shell_view,
 	if (source == NULL)
 		return;
 
-	uid = e_source_peek_uid (source);
+	uid = e_source_get_uid (source);
 	hash_table = book_shell_view->priv->uid_to_view;
 	widget = g_hash_table_lookup (hash_table, uid);
 
@@ -389,6 +389,30 @@ book_shell_view_selector_key_press_event_cb (EShellView *shell_view,
 }
 
 static void
+book_shell_view_source_removed_cb (ESourceRegistry *registry,
+                                   ESource *source,
+                                   EBookShellView *book_shell_view)
+{
+	EBookShellViewPrivate *priv = book_shell_view->priv;
+	EBookShellContent *book_shell_content;
+	EAddressbookView *view;
+	const gchar *uid;
+
+	uid = e_source_get_uid (source);
+
+	book_shell_content = book_shell_view->priv->book_shell_content;
+
+	/* Remove the EAddressbookView for the deleted source. */
+	view = g_hash_table_lookup (priv->uid_to_view, uid);
+	if (view != NULL) {
+		e_book_shell_content_remove_view (book_shell_content, view);
+		g_hash_table_remove (priv->uid_to_view, uid);
+	}
+
+	e_shell_view_update_actions (E_SHELL_VIEW (book_shell_view));
+}
+
+static void
 book_shell_view_load_view_collection (EShellViewClass *shell_view_class)
 {
 	GalViewCollection *collection;
@@ -449,20 +473,13 @@ e_book_shell_view_private_init (EBookShellView *book_shell_view,
 {
 	EBookShellViewPrivate *priv = book_shell_view->priv;
 	GHashTable *uid_to_view;
-	GHashTable *uid_to_editor;
 
 	uid_to_view = g_hash_table_new_full (
 		g_str_hash, g_str_equal,
 		(GDestroyNotify) g_free,
 		(GDestroyNotify) g_object_unref);
 
-	uid_to_editor = g_hash_table_new_full (
-		g_str_hash, g_str_equal,
-		(GDestroyNotify) g_free,
-		(GDestroyNotify) g_free);
-
 	priv->uid_to_view = uid_to_view;
-	priv->uid_to_editor = uid_to_editor;
 	priv->preview_index = -1;
 
 	if (!gal_view_collection_loaded (shell_view_class->view_collection))
@@ -483,6 +500,7 @@ e_book_shell_view_private_constructed (EBookShellView *book_shell_view)
 	EShellView *shell_view;
 	EShellWindow *shell_window;
 	ESourceSelector *selector;
+	ESourceRegistry *registry;
 
 	shell_view = E_SHELL_VIEW (book_shell_view);
 	shell_backend = e_shell_view_get_shell_backend (shell_view);
@@ -498,9 +516,16 @@ e_book_shell_view_private_constructed (EBookShellView *book_shell_view)
 	priv->book_shell_content = g_object_ref (shell_content);
 	priv->book_shell_sidebar = g_object_ref (shell_sidebar);
 
+	registry = e_source_registry_get_default ();
+
 	selector = e_book_shell_sidebar_get_selector (
 		E_BOOK_SHELL_SIDEBAR (shell_sidebar));
 
+	g_signal_connect (
+		registry, "source-removed",
+		G_CALLBACK (book_shell_view_source_removed_cb),
+		book_shell_view);
+
 	g_signal_connect_object (
 		selector, "button-press-event",
 		G_CALLBACK (book_shell_view_selector_button_press_event_cb),
@@ -534,13 +559,17 @@ void
 e_book_shell_view_private_dispose (EBookShellView *book_shell_view)
 {
 	EBookShellViewPrivate *priv = book_shell_view->priv;
+	ESourceRegistry *registry = e_source_registry_get_default ();
 
 	DISPOSE (priv->book_shell_backend);
 	DISPOSE (priv->book_shell_content);
 	DISPOSE (priv->book_shell_sidebar);
 
 	g_hash_table_remove_all (priv->uid_to_view);
-	g_hash_table_remove_all (priv->uid_to_editor);
+
+	g_signal_handlers_disconnect_matched (
+		registry, G_SIGNAL_MATCH_DATA,
+		0, 0, NULL, NULL, book_shell_view);
 }
 
 void
@@ -549,15 +578,4 @@ e_book_shell_view_private_finalize (EBookShellView *book_shell_view)
 	EBookShellViewPrivate *priv = book_shell_view->priv;
 
 	g_hash_table_destroy (priv->uid_to_view);
-	g_hash_table_destroy (priv->uid_to_editor);
-}
-
-void
-e_book_shell_view_editor_weak_notify (EditorUidClosure *closure,
-                                      GObject *where_the_object_was)
-{
-	GHashTable *hash_table;
-
-	hash_table = closure->view->priv->uid_to_editor;
-	g_hash_table_remove (hash_table, closure->uid);
 }
diff --git a/modules/addressbook/e-book-shell-view-private.h b/modules/addressbook/e-book-shell-view-private.h
index 528a34d..e942386 100644
--- a/modules/addressbook/e-book-shell-view-private.h
+++ b/modules/addressbook/e-book-shell-view-private.h
@@ -42,6 +42,7 @@
 #include "shell/e-shell-utils.h"
 #include "misc/e-popup-action.h"
 #include "misc/e-selectable.h"
+#include "misc/e-source-config-dialog.h"
 
 #include "addressbook/util/eab-book-util.h"
 #include "addressbook/gui/contact-editor/e-contact-editor.h"
@@ -49,6 +50,7 @@
 #include "addressbook/gui/widgets/eab-gui-util.h"
 #include "addressbook/gui/widgets/e-addressbook-view.h"
 #include "addressbook/gui/widgets/e-addressbook-selector.h"
+#include "addressbook/gui/widgets/e-book-source-config.h"
 
 #include "e-book-shell-backend.h"
 #include "e-book-shell-content.h"
@@ -72,14 +74,6 @@
 
 G_BEGIN_DECLS
 
-typedef struct _EditorUidClosure EditorUidClosure;
-
-struct _EditorUidClosure {
-	GtkWidget *editor;
-	gchar *uid;
-	EBookShellView *view;
-};
-
 /* List these in the order to be displayed.
  * Positive values are reserved for categories. */
 enum {
@@ -103,7 +97,6 @@ struct _EBookShellViewPrivate {
 	EBookShellSidebar *book_shell_sidebar;
 
 	GHashTable *uid_to_view;
-	GHashTable *uid_to_editor;
 
 	gint preview_index;
 
@@ -126,9 +119,6 @@ void		e_book_shell_view_private_finalize
 
 void		e_book_shell_view_actions_init
 					(EBookShellView *book_shell_view);
-void		e_book_shell_view_editor_weak_notify
-					(EditorUidClosure *closure,
-					 GObject *where_the_object_was);
 void		e_book_shell_view_update_search_filter
 					(EBookShellView *book_shell_view);
 
diff --git a/modules/addressbook/e-book-shell-view.c b/modules/addressbook/e-book-shell-view.c
index 4f0d349..e5f01b9 100644
--- a/modules/addressbook/e-book-shell-view.c
+++ b/modules/addressbook/e-book-shell-view.c
@@ -25,59 +25,6 @@ static gpointer parent_class;
 static GType book_shell_view_type;
 
 static void
-book_shell_view_source_list_changed_cb (EBookShellView *book_shell_view,
-                                        ESourceList *source_list)
-{
-	EBookShellViewPrivate *priv = book_shell_view->priv;
-	EBookShellContent *book_shell_content;
-	EShellView *shell_view;
-	GList *keys, *iter;
-
-	g_return_if_fail (E_IS_SHELL_VIEW (book_shell_view));
-	g_return_if_fail (book_shell_view->priv != NULL);
-
-	shell_view = E_SHELL_VIEW (book_shell_view);
-	book_shell_content = book_shell_view->priv->book_shell_content;
-
-	keys = g_hash_table_get_keys (priv->uid_to_view);
-	for (iter = keys; iter != NULL; iter = iter->next) {
-		gchar *uid = iter->data;
-		EAddressbookView *view;
-
-		/* If the source still exists, move on. */
-		if (e_source_list_peek_source_by_uid (source_list, uid))
-			continue;
-
-		/* Remove the view for the deleted source. */
-		view = g_hash_table_lookup (priv->uid_to_view, uid);
-		e_book_shell_content_remove_view (book_shell_content, view);
-		g_hash_table_remove (priv->uid_to_view, uid);
-	}
-	g_list_free (keys);
-
-	keys = g_hash_table_get_keys (priv->uid_to_editor);
-	for (iter = keys; iter != NULL; iter = iter->next) {
-		gchar *uid = iter->data;
-		EditorUidClosure *closure;
-
-		/* If the source still exists, move on. */
-		if (e_source_list_peek_source_by_uid (source_list, uid))
-			continue;
-
-		/* Remove the editor for the deleted source. */
-		closure = g_hash_table_lookup (priv->uid_to_editor, uid);
-		g_object_weak_unref (
-			G_OBJECT (closure->editor), (GWeakNotify)
-			e_book_shell_view_editor_weak_notify, closure);
-		gtk_widget_destroy (closure->editor);
-		g_hash_table_remove (priv->uid_to_editor, uid);
-	}
-	g_list_free (keys);
-
-	e_shell_view_update_actions (shell_view);
-}
-
-static void
 book_shell_view_dispose (GObject *object)
 {
 	EBookShellView *book_shell_view;
@@ -105,22 +52,12 @@ static void
 book_shell_view_constructed (GObject *object)
 {
 	EBookShellView *book_shell_view;
-	EBookShellBackend *book_shell_backend;
-	ESourceList *source_list;
 
 	/* Chain up to parent's constructed() method. */
 	G_OBJECT_CLASS (parent_class)->constructed (object);
 
 	book_shell_view = E_BOOK_SHELL_VIEW (object);
 	e_book_shell_view_private_constructed (book_shell_view);
-
-	book_shell_backend = book_shell_view->priv->book_shell_backend;
-	source_list = e_book_shell_backend_get_source_list (book_shell_backend);
-
-	g_signal_connect_object (
-		source_list, "changed",
-		G_CALLBACK (book_shell_view_source_list_changed_cb),
-		book_shell_view, G_CONNECT_SWAPPED);
 }
 
 static void
diff --git a/widgets/misc/Makefile.am b/widgets/misc/Makefile.am
index 57c7101..3ccb95b 100644
--- a/widgets/misc/Makefile.am
+++ b/widgets/misc/Makefile.am
@@ -23,6 +23,7 @@ widgetsinclude_HEADERS =			\
 	e-attachment-store.h			\
 	e-attachment-tree-view.h		\
 	e-attachment-view.h			\
+	e-autocomplete-selector.h		\
 	e-buffer-tagger.h			\
 	e-calendar.h				\
 	e-calendar-item.h			\
@@ -106,6 +107,7 @@ libemiscwidgets_la_SOURCES =			\
 	e-attachment-store.c			\
 	e-attachment-tree-view.c		\
 	e-attachment-view.c			\
+	e-autocomplete-selector.c		\
 	e-buffer-tagger.c			\
 	e-calendar.c				\
 	e-calendar-item.c			\
diff --git a/widgets/misc/e-autocomplete-selector.c b/widgets/misc/e-autocomplete-selector.c
new file mode 100644
index 0000000..7323e74
--- /dev/null
+++ b/widgets/misc/e-autocomplete-selector.c
@@ -0,0 +1,104 @@
+/*
+ * e-autocomplete-selector.c
+ *
+ * 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.
+ *
+ * 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/>
+ *
+ */
+
+#include "e-autocomplete-selector.h"
+
+#include <libebook/e-source-address-book.h>
+#include <libedataserver/e-source-autocomplete.h>
+
+G_DEFINE_TYPE (
+	EAutocompleteSelector,
+	e_autocomplete_selector,
+	E_TYPE_SOURCE_SELECTOR)
+
+static gboolean
+autocomplete_selector_get_source_selected (ESourceSelector *selector,
+                                           ESource *source)
+{
+	ESourceAutocomplete *extension;
+	const gchar *extension_name;
+
+	extension_name = e_source_selector_get_extension_name (selector);
+
+	/* Make sure this source is an address book. */
+	if (!e_source_has_extension (source, extension_name))
+		return FALSE;
+
+	extension_name = E_SOURCE_EXTENSION_AUTOCOMPLETE;
+	extension = e_source_get_extension (source, extension_name);
+	g_return_val_if_fail (E_IS_SOURCE_AUTOCOMPLETE (extension), FALSE);
+
+	return e_source_autocomplete_get_include_me (extension);
+}
+
+static gboolean
+autocomplete_selector_set_source_selected (ESourceSelector *selector,
+                                           ESource *source,
+                                           gboolean selected)
+{
+	ESourceAutocomplete *extension;
+	const gchar *extension_name;
+
+	extension_name = e_source_selector_get_extension_name (selector);
+
+	/* Make sure this source is an address book. */
+	if (!e_source_has_extension (source, extension_name))
+		return FALSE;
+
+	extension_name = E_SOURCE_EXTENSION_AUTOCOMPLETE;
+	extension = e_source_get_extension (source, extension_name);
+	g_return_val_if_fail (E_IS_SOURCE_AUTOCOMPLETE (extension), FALSE);
+
+	/* Avoid unnecessary signal emissions and disk writes. */
+	if (selected == e_source_autocomplete_get_include_me (extension))
+		return FALSE;
+
+	e_source_autocomplete_set_include_me (extension, selected);
+
+	return TRUE;
+}
+
+static void
+e_autocomplete_selector_class_init (EAutocompleteSelectorClass *class)
+{
+	ESourceSelectorClass *source_selector_class;
+
+	source_selector_class = E_SOURCE_SELECTOR_CLASS (class);
+	source_selector_class->get_source_selected =
+				autocomplete_selector_get_source_selected;
+	source_selector_class->set_source_selected =
+				autocomplete_selector_set_source_selected;
+}
+
+static void
+e_autocomplete_selector_init (EAutocompleteSelector *selector)
+{
+	e_source_selector_set_show_colors (
+		E_SOURCE_SELECTOR (selector), FALSE);
+}
+
+GtkWidget *
+e_autocomplete_selector_new (ESourceRegistry *registry)
+{
+	g_return_val_if_fail (E_IS_SOURCE_REGISTRY (registry), NULL);
+
+	return g_object_new (
+		E_TYPE_AUTOCOMPLETE_SELECTOR,
+		"extension-name", E_SOURCE_EXTENSION_ADDRESS_BOOK,
+		"registry", registry, NULL);
+}
diff --git a/widgets/misc/e-autocomplete-selector.h b/widgets/misc/e-autocomplete-selector.h
new file mode 100644
index 0000000..8caa132
--- /dev/null
+++ b/widgets/misc/e-autocomplete-selector.h
@@ -0,0 +1,64 @@
+/*
+ * e-autocomplete-selector.h
+ *
+ * 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.
+ *
+ * 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/>
+ *
+ */
+
+#ifndef E_AUTOCOMPLETE_SELECTOR_H
+#define E_AUTOCOMPLETE_SELECTOR_H
+
+#include <libedataserverui/e-source-selector.h>
+
+/* Standard GObject macros */
+#define E_TYPE_AUTOCOMPLETE_SELECTOR \
+	(e_autocomplete_selector_get_type ())
+#define E_AUTOCOMPLETE_SELECTOR(obj) \
+	(G_TYPE_CHECK_INSTANCE_CAST \
+	((obj), E_TYPE_AUTOCOMPLETE_SELECTOR, EAutocompleteSelector))
+#define E_AUTOCOMPLETE_SELECTOR_CLASS(cls) \
+	(G_TYPE_CHECK_CLASS_CAST \
+	((cls), E_TYPE_AUTOCOMPLETE_SELECTOR, EAutocompleteSelectorClass))
+#define E_IS_AUTOCOMPLETE_SELECTOR(obj) \
+	(G_TYPE_CHECK_INSTANCE_TYPE \
+	((obj), E_TYPE_AUTOCOMPLETE_SELECTOR))
+#define E_IS_AUTOCOMPLETE_SELECTOR_CLASS(cls) \
+	(G_TYPE_CHECK_CLASS_TYPE \
+	((cls), E_TYPE_AUTOCOMPLETE_SELECTOR))
+#define E_AUTOCOMPLETE_SELECTOR_GET_CLASS(obj) \
+	(G_TYPE_INSTANCE_GET_CLASS \
+	((obj), E_TYPE_AUTOCOMPLETE_SELECTOR, EAutocompleteSelectorClass))
+
+G_BEGIN_DECLS
+
+typedef struct _EAutocompleteSelector EAutocompleteSelector;
+typedef struct _EAutocompleteSelectorClass EAutocompleteSelectorClass;
+typedef struct _EAutocompleteSelectorPrivate EAutocompleteSelectorPrivate;
+
+struct _EAutocompleteSelector {
+	ESourceSelector parent;
+	EAutocompleteSelectorPrivate *priv;
+};
+
+struct _EAutocompleteSelectorClass {
+	ESourceSelectorClass parent_class;
+};
+
+GType		e_autocomplete_selector_get_type
+						(void) G_GNUC_CONST;
+GtkWidget *	e_autocomplete_selector_new	(ESourceRegistry *registry);
+
+G_END_DECLS
+
+#endif /* E_AUTOCOMPLETE_SELECTOR_H */



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]