[evolution-data-server] EBookBackendFile cleanups.



commit fafd0685d2bdb92ddddbcaeb7466796da65f5a20
Author: Matthew Barnes <mbarnes redhat com>
Date:   Wed Apr 3 12:41:36 2013 -0400

    EBookBackendFile cleanups.

 addressbook/backends/file/e-book-backend-file.c |  975 +++++++++++------------
 1 files changed, 487 insertions(+), 488 deletions(-)
---
diff --git a/addressbook/backends/file/e-book-backend-file.c b/addressbook/backends/file/e-book-backend-file.c
index 9da18fb..9231ef8 100644
--- a/addressbook/backends/file/e-book-backend-file.c
+++ b/addressbook/backends/file/e-book-backend-file.c
@@ -787,117 +787,319 @@ do_create (EBookBackendFile *bf,
        return (status != STATUS_ERROR);
 }
 
+typedef struct {
+       EBookBackendFile *bf;
+       GThread *thread;
+       EFlag *running;
+} FileBackendSearchClosure;
+
 static void
-e_book_backend_file_create_contacts (EBookBackendSync *backend,
-                                     EDataBook *book,
-                                     GCancellable *cancellable,
-                                     const GSList *vcards,
-                                     GSList **added_contacts,
-                                     GError **perror)
+closure_destroy (FileBackendSearchClosure *closure)
 {
-       EBookBackendFile *bf = E_BOOK_BACKEND_FILE (backend);
+       d (printf ("destroying search closure\n"));
+       e_flag_free (closure->running);
+       if (closure->thread)
+               g_thread_unref (closure->thread);
+       g_free (closure);
+}
 
-       g_rw_lock_writer_lock (&(bf->priv->lock));
+static FileBackendSearchClosure *
+init_closure (EDataBookView *book_view,
+              EBookBackendFile *bf)
+{
+       FileBackendSearchClosure *closure = g_new (FileBackendSearchClosure, 1);
 
-       if (do_create (bf, vcards, added_contacts, perror)) {
-               e_book_backend_file_bump_revision (bf);
-       }
+       closure->bf = bf;
+       closure->thread = NULL;
+       closure->running = e_flag_new ();
 
-       g_rw_lock_writer_unlock (&(bf->priv->lock));
+       g_object_set_data_full (
+               G_OBJECT (book_view),
+               "EBookBackendFile.BookView::closure",
+               closure, (GDestroyNotify) closure_destroy);
+
+       return closure;
+}
+
+static FileBackendSearchClosure *
+get_closure (EDataBookView *book_view)
+{
+       return g_object_get_data (
+               G_OBJECT (book_view),
+               "EBookBackendFile.BookView::closure");
 }
 
 static void
-e_book_backend_file_remove_contacts (EBookBackendSync *backend,
-                                     EDataBook *book,
-                                     GCancellable *cancellable,
-                                     const GSList *id_list,
-                                     GSList **ids,
-                                     GError **perror)
+notify_update_vcard (EDataBookView *book_view,
+                     gboolean prefiltered,
+                     const gchar *id,
+                     const gchar *vcard)
 {
-       EBookBackendFile *bf = E_BOOK_BACKEND_FILE (backend);
-       GSList           *removed_ids = NULL, *removed_contacts = NULL;
-       GError           *local_error = NULL;
-       gboolean          delete_failed = FALSE;
-       const GSList     *l;
+       if (prefiltered)
+               e_data_book_view_notify_update_prefiltered_vcard (book_view, id, vcard);
+       else
+               e_data_book_view_notify_update_vcard (book_view, id, vcard);
+}
 
-       g_rw_lock_writer_lock (&(bf->priv->lock));
+static gpointer
+book_view_thread (gpointer data)
+{
+       EDataBookView *book_view;
+       FileBackendSearchClosure *closure;
+       EBookBackendFile *bf;
+       EBookBackendSExp *sexp;
+       const gchar *query;
+       GSList *summary_list, *l;
+       GHashTable *fields_of_interest;
+       GError *local_error = NULL;
 
-       for (l = id_list; l != NULL; l = l->next) {
-               const gchar *id;
-               EContact *contact;
+       g_return_val_if_fail (E_IS_DATA_BOOK_VIEW (data), NULL);
 
-               id = l->data;
+       book_view = data;
+       closure = get_closure (book_view);
+       if (!closure) {
+               g_warning (G_STRLOC ": NULL closure in book view thread");
+               return NULL;
+       }
+       bf = closure->bf;
 
-               /* First load the EContacts which need to be removed, we might delete some
-                * photos from disk because of this...
-                *
-                * Note: sqlitedb backend can probably make this faster by executing a
-                * single query to fetch a list of contacts for a list of ids, the
-                * current method makes a query for each UID.
-                */
-               contact = e_book_backend_sqlitedb_get_contact (
-                       bf->priv->sqlitedb,
-                       SQLITEDB_FOLDER_ID, id,
-                       NULL, NULL, &local_error);
+       d (printf ("starting initial population of book view\n"));
 
-               if (contact) {
-                       removed_ids      = g_slist_prepend (removed_ids, g_strdup (id));
-                       removed_contacts = g_slist_prepend (removed_contacts, contact);
-               } else {
-                       g_warning ("Failed to fetch contact to be removed: %s", local_error->message);
+       /* ref the book view because it'll be removed and unrefed
+        * when/if it's stopped */
+       g_object_ref (book_view);
 
-                       if (g_error_matches (local_error,
-                                            E_BOOK_SDB_ERROR,
-                                            E_BOOK_SDB_ERROR_CONTACT_NOT_FOUND)) {
-                               g_set_error (
-                                       perror, E_BOOK_CLIENT_ERROR,
-                                       E_BOOK_CLIENT_ERROR_CONTACT_NOT_FOUND,
-                                       _("Contact '%s' not found"), id);
-                               g_error_free (local_error);
-                       } else
-                               g_propagate_error (perror, local_error);
+       sexp = e_data_book_view_get_sexp (book_view);
+       query = e_book_backend_sexp_text (sexp);
 
-                       /* Abort as soon as missing contact is to be deleted */
-                       delete_failed = TRUE;
-                       break;
-               }
+       fields_of_interest = e_data_book_view_get_fields_of_interest (book_view);
+
+       if ( !strcmp (query, "(contains \"x-evolution-any-field\" \"\")")) {
+               e_data_book_view_notify_progress (book_view, -1, _("Loading..."));
+       } else {
+               e_data_book_view_notify_progress (book_view, -1, _("Searching..."));
        }
 
-       if (!delete_failed) {
+       d (printf ("signalling parent thread\n"));
+       e_flag_set (closure->running);
 
-               /* Delete URI associated to those contacts */
-               for (l = removed_contacts; l; l = l->next) {
-                       maybe_delete_unused_uris (bf, E_CONTACT (l->data), NULL);
+       g_rw_lock_reader_lock (&(bf->priv->lock));
+       summary_list = e_book_backend_sqlitedb_search (
+               bf->priv->sqlitedb,
+               SQLITEDB_FOLDER_ID,
+               query, fields_of_interest,
+               NULL, NULL, &local_error);
+       g_rw_lock_reader_unlock (&(bf->priv->lock));
+
+       if (!summary_list && local_error != NULL) {
+               g_warning (G_STRLOC ": Failed to query initial contacts: %s", local_error->message);
+               g_error_free (local_error);
+               e_data_book_view_notify_complete (
+                       book_view,
+                       g_error_new_literal (
+                               E_CLIENT_ERROR,
+                               E_CLIENT_ERROR_NOT_OPENED,
+                               e_client_error_to_string (
+                               E_CLIENT_ERROR_NOT_OPENED)));
+               g_object_unref (book_view);
+               return NULL;
+       }
+
+       for (l = summary_list; l; l = l->next) {
+               EbSdbSearchData *data = l->data;
+               gchar *vcard = NULL;
+
+               vcard = data->vcard;
+               data->vcard = NULL;
+
+               notify_update_vcard (book_view, TRUE, data->uid, vcard);
+               g_free (vcard);
+       }
+
+       g_slist_foreach (summary_list, (GFunc) e_book_backend_sqlitedb_search_data_free, NULL);
+       g_slist_free (summary_list);
+
+       if (e_flag_is_set (closure->running))
+               e_data_book_view_notify_complete (book_view, NULL /* Success */);
+
+       g_object_unref (book_view);
+
+       d (printf ("finished population of book view\n"));
+
+       return NULL;
+}
+
+static void
+view_notify_update (EBookBackendFile *backend,
+                    EDataBookView *view,
+                    EContact *contact)
+{
+       EBookBackendSExp *sexp;
+       GHashTable *fields   = e_data_book_view_get_fields_of_interest (view);
+       const gchar *query;
+       gboolean    notified = FALSE;
+       gboolean    with_all_required_fields = FALSE;
+
+       sexp = e_data_book_view_get_sexp (view);
+       query = e_book_backend_sexp_text (sexp);
+
+       if (e_book_backend_sqlitedb_check_summary_query (backend->priv->sqlitedb, query, NULL) &&
+           e_book_backend_sqlitedb_check_summary_fields (backend->priv->sqlitedb, fields)) {
+
+               const gchar *uid = e_contact_get_const (contact, E_CONTACT_UID);
+               gchar       *vcard;
+
+               vcard = e_book_backend_sqlitedb_get_vcard_string (
+                       backend->priv->sqlitedb,
+                       SQLITEDB_FOLDER_ID, uid,
+                       fields, &with_all_required_fields, NULL);
+
+               if (vcard) {
+                       if (with_all_required_fields) {
+                               e_data_book_view_notify_update_prefiltered_vcard (view, uid, vcard);
+                               notified = TRUE;
+                       }
+                       g_free (vcard);
                }
+       }
 
-               /* Remove from summary as well */
-               if (!e_book_backend_sqlitedb_remove_contacts (bf->priv->sqlitedb,
-                                                     SQLITEDB_FOLDER_ID,
-                                                     removed_ids, &local_error)) {
-                       g_warning ("Failed to remove contacts: %s", local_error->message);
-                       g_propagate_error (perror, local_error);
+       if (!notified)
+               e_data_book_view_notify_update (view, contact);
+}
+
+static void
+book_backend_file_dispose (GObject *object)
+{
+       EBookBackendFile *bf;
+
+       bf = E_BOOK_BACKEND_FILE (object);
+
+       if (bf->priv->sqlitedb) {
+               g_object_unref (bf->priv->sqlitedb);
+               bf->priv->sqlitedb = NULL;
+       }
+
+       G_OBJECT_CLASS (e_book_backend_file_parent_class)->dispose (object);
+}
+
+static void
+book_backend_file_finalize (GObject *object)
+{
+       EBookBackendFilePrivate *priv;
+
+       priv = E_BOOK_BACKEND_FILE_GET_PRIVATE (object);
+
+       g_free (priv->photo_dirname);
+       g_free (priv->revision);
+       g_free (priv->base_directory);
+       g_rw_lock_clear (&(priv->lock));
+
+       /* Chain up to parent's finalize() method. */
+       G_OBJECT_CLASS (e_book_backend_file_parent_class)->finalize (object);
+}
+
+static gchar *
+book_backend_file_get_backend_property (EBookBackend *backend,
+                                        const gchar *prop_name)
+{
+       EBookBackendFile *bf = E_BOOK_BACKEND_FILE (backend);
+
+       g_return_val_if_fail (prop_name != NULL, NULL);
+
+       if (g_str_equal (prop_name, CLIENT_BACKEND_PROPERTY_CAPABILITIES)) {
+               return g_strdup ("local,do-initial-query,bulk-adds,bulk-modifies,bulk-removes,contact-lists");
+
+       } else if (g_str_equal (prop_name, BOOK_BACKEND_PROPERTY_REQUIRED_FIELDS)) {
+               return g_strdup (e_contact_field_name (E_CONTACT_FILE_AS));
+
+       } else if (g_str_equal (prop_name, BOOK_BACKEND_PROPERTY_SUPPORTED_FIELDS)) {
+               GString *fields;
+               gint ii;
+
+               fields = g_string_sized_new (1024);
+
+               /* XXX we need a way to say "we support everything", since the
+                * file backend does */
+               for (ii = 1; ii < E_CONTACT_FIELD_LAST; ii++) {
+                       if (fields->len > 0)
+                               g_string_append_c (fields, ',');
+                       g_string_append (fields, e_contact_field_name (ii));
                }
 
-               e_book_backend_file_bump_revision (bf);
+               return g_string_free (fields, FALSE);
+
+       } else if (g_str_equal (prop_name, BOOK_BACKEND_PROPERTY_REVISION)) {
+               gchar *prop_value;
+
+               g_rw_lock_reader_lock (&(bf->priv->lock));
+               prop_value = g_strdup (bf->priv->revision);
+               g_rw_lock_reader_unlock (&(bf->priv->lock));
+
+               return prop_value;
+       }
+
+       /* Chain up to parent's get_backend_property() method. */
+       return E_BOOK_BACKEND_CLASS (e_book_backend_file_parent_class)->
+               get_backend_property (backend, prop_name);
+}
+
+static void
+book_backend_file_open (EBookBackendSync *backend,
+                        EDataBook *book,
+                        GCancellable *cancellable,
+                        gboolean only_if_exists,
+                        GError **perror)
+{
+       EBookBackendFile *bf = E_BOOK_BACKEND_FILE (backend);
+       ESource          *source;
+       ESourceRevisionGuards *guards;
+
+       source = e_backend_get_source (E_BACKEND (backend));
+
+       g_type_ensure (E_TYPE_SOURCE_REVISION_GUARDS);
+       guards = e_source_get_extension (source, E_SOURCE_EXTENSION_REVISION_GUARDS);
+
+       bf->priv->revision_guards = e_source_revision_guards_get_enabled (guards);
+
+       g_rw_lock_writer_lock (&(bf->priv->lock));
+       if (!bf->priv->revision) {
+               e_book_backend_file_load_revision (bf);
+               e_book_backend_notify_property_changed (E_BOOK_BACKEND (backend),
+                                                       BOOK_BACKEND_PROPERTY_REVISION,
+                                                       bf->priv->revision);
+       }
+       g_rw_lock_writer_unlock (&(bf->priv->lock));
+
+       e_backend_set_online (E_BACKEND (backend), TRUE);
+       e_book_backend_set_writable (E_BOOK_BACKEND (backend), TRUE);
+}
+
+static void
+book_backend_file_create_contacts (EBookBackendSync *backend,
+                                   EDataBook *book,
+                                   GCancellable *cancellable,
+                                   const GSList *vcards,
+                                   GSList **added_contacts,
+                                   GError **perror)
+{
+       EBookBackendFile *bf = E_BOOK_BACKEND_FILE (backend);
+
+       g_rw_lock_writer_lock (&(bf->priv->lock));
 
-               *ids = removed_ids;
-       } else {
-               *ids = NULL;
-               g_slist_free_full (removed_ids, (GDestroyNotify) g_free);
+       if (do_create (bf, vcards, added_contacts, perror)) {
+               e_book_backend_file_bump_revision (bf);
        }
 
        g_rw_lock_writer_unlock (&(bf->priv->lock));
-
-       g_slist_free_full (removed_contacts, (GDestroyNotify) g_object_unref);
 }
 
 static void
-e_book_backend_file_modify_contacts (EBookBackendSync *backend,
-                                     EDataBook *book,
-                                     GCancellable *cancellable,
-                                     const GSList *vcards,
-                                     GSList **contacts,
-                                     GError **perror)
+book_backend_file_modify_contacts (EBookBackendSync *backend,
+                                   EDataBook *book,
+                                   GCancellable *cancellable,
+                                   const GSList *vcards,
+                                   GSList **contacts,
+                                   GError **perror)
 {
        EBookBackendFile *bf = E_BOOK_BACKEND_FILE (backend);
        const GSList     *lold, *l;
@@ -1026,12 +1228,97 @@ e_book_backend_file_modify_contacts (EBookBackendSync *backend,
 }
 
 static void
-e_book_backend_file_get_contact (EBookBackendSync *backend,
-                                 EDataBook *book,
-                                 GCancellable *cancellable,
-                                 const gchar *id,
-                                 gchar **vcard,
-                                 GError **perror)
+book_backend_file_remove_contacts (EBookBackendSync *backend,
+                                   EDataBook *book,
+                                   GCancellable *cancellable,
+                                   const GSList *id_list,
+                                   GSList **ids,
+                                   GError **perror)
+{
+       EBookBackendFile *bf = E_BOOK_BACKEND_FILE (backend);
+       GSList           *removed_ids = NULL, *removed_contacts = NULL;
+       GError           *local_error = NULL;
+       gboolean          delete_failed = FALSE;
+       const GSList     *l;
+
+       g_rw_lock_writer_lock (&(bf->priv->lock));
+
+       for (l = id_list; l != NULL; l = l->next) {
+               const gchar *id;
+               EContact *contact;
+
+               id = l->data;
+
+               /* First load the EContacts which need to be removed, we might delete some
+                * photos from disk because of this...
+                *
+                * Note: sqlitedb backend can probably make this faster by executing a
+                * single query to fetch a list of contacts for a list of ids, the
+                * current method makes a query for each UID.
+                */
+               contact = e_book_backend_sqlitedb_get_contact (
+                       bf->priv->sqlitedb,
+                       SQLITEDB_FOLDER_ID, id,
+                       NULL, NULL, &local_error);
+
+               if (contact) {
+                       removed_ids      = g_slist_prepend (removed_ids, g_strdup (id));
+                       removed_contacts = g_slist_prepend (removed_contacts, contact);
+               } else {
+                       g_warning ("Failed to fetch contact to be removed: %s", local_error->message);
+
+                       if (g_error_matches (local_error,
+                                            E_BOOK_SDB_ERROR,
+                                            E_BOOK_SDB_ERROR_CONTACT_NOT_FOUND)) {
+                               g_set_error (
+                                       perror, E_BOOK_CLIENT_ERROR,
+                                       E_BOOK_CLIENT_ERROR_CONTACT_NOT_FOUND,
+                                       _("Contact '%s' not found"), id);
+                               g_error_free (local_error);
+                       } else
+                               g_propagate_error (perror, local_error);
+
+                       /* Abort as soon as missing contact is to be deleted */
+                       delete_failed = TRUE;
+                       break;
+               }
+       }
+
+       if (!delete_failed) {
+
+               /* Delete URI associated to those contacts */
+               for (l = removed_contacts; l; l = l->next) {
+                       maybe_delete_unused_uris (bf, E_CONTACT (l->data), NULL);
+               }
+
+               /* Remove from summary as well */
+               if (!e_book_backend_sqlitedb_remove_contacts (bf->priv->sqlitedb,
+                                                     SQLITEDB_FOLDER_ID,
+                                                     removed_ids, &local_error)) {
+                       g_warning ("Failed to remove contacts: %s", local_error->message);
+                       g_propagate_error (perror, local_error);
+               }
+
+               e_book_backend_file_bump_revision (bf);
+
+               *ids = removed_ids;
+       } else {
+               *ids = NULL;
+               g_slist_free_full (removed_ids, (GDestroyNotify) g_free);
+       }
+
+       g_rw_lock_writer_unlock (&(bf->priv->lock));
+
+       g_slist_free_full (removed_contacts, (GDestroyNotify) g_object_unref);
+}
+
+static void
+book_backend_file_get_contact (EBookBackendSync *backend,
+                               EDataBook *book,
+                               GCancellable *cancellable,
+                               const gchar *id,
+                               gchar **vcard,
+                               GError **perror)
 {
        EBookBackendFile *bf = E_BOOK_BACKEND_FILE (backend);
        GError *local_error = NULL;
@@ -1060,19 +1347,19 @@ e_book_backend_file_get_contact (EBookBackendSync *backend,
 }
 
 static void
-e_book_backend_file_get_contact_list (EBookBackendSync *backend,
-                                      EDataBook *book,
-                                      GCancellable *cancellable,
-                                      const gchar *query,
-                                      GSList **contacts,
-                                      GError **perror)
+book_backend_file_get_contact_list (EBookBackendSync *backend,
+                                    EDataBook *book,
+                                    GCancellable *cancellable,
+                                    const gchar *query,
+                                    GSList **contacts,
+                                    GError **perror)
 {
        EBookBackendFile *bf = E_BOOK_BACKEND_FILE (backend);
        GSList           *contact_list = NULL, *l;
        GSList           *summary_list = NULL;
        GError           *local_error = NULL;
 
-       d (printf ("e_book_backend_file_get_contact_list (%s)\n", query));
+       d (printf ("book_backend_file_get_contact_list (%s)\n", query));
 
        g_rw_lock_reader_lock (&(bf->priv->lock));
        summary_list = e_book_backend_sqlitedb_search (
@@ -1120,204 +1407,62 @@ e_book_backend_file_get_contact_list (EBookBackendSync *backend,
                }
        }
 
-       *contacts = contact_list;
-}
-
-static void
-e_book_backend_file_get_contact_list_uids (EBookBackendSync *backend,
-                                           EDataBook *book,
-                                           GCancellable *cancellable,
-                                           const gchar *query,
-                                           GSList **contacts_uids,
-                                           GError **perror)
-{
-       EBookBackendFile *bf = E_BOOK_BACKEND_FILE (backend);
-       GSList           *uids = NULL;
-       GError           *local_error = NULL;
-
-       d (printf ("e_book_backend_file_get_contact_list (%s)\n", query));
-
-       g_rw_lock_reader_lock (&(bf->priv->lock));
-       uids = e_book_backend_sqlitedb_search_uids (
-               bf->priv->sqlitedb,
-               SQLITEDB_FOLDER_ID,
-               query, NULL, &local_error);
-       g_rw_lock_reader_unlock (&(bf->priv->lock));
-
-       if (uids == NULL && local_error != NULL) {
-
-               if (g_error_matches (local_error,
-                                    E_BOOK_SDB_ERROR,
-                                    E_BOOK_SDB_ERROR_NOT_SUPPORTED)) {
-                       g_set_error (
-                               perror, E_CLIENT_ERROR,
-                               E_CLIENT_ERROR_NOT_SUPPORTED,
-                               _("Query '%s' not supported"), query);
-                       g_error_free (local_error);
-
-               } else if (g_error_matches (local_error,
-                                    E_BOOK_SDB_ERROR,
-                                    E_BOOK_SDB_ERROR_INVALID_QUERY)) {
-                       g_set_error (
-                               perror, E_CLIENT_ERROR,
-                               E_CLIENT_ERROR_INVALID_QUERY,
-                               _("Invalid Query '%s'"), query);
-                       g_error_free (local_error);
-
-               } else {
-                       g_warning ("Failed to fetch contact ids: %s", local_error->message);
-                       g_propagate_error (perror, local_error);
-               }
-       }
-
-       *contacts_uids = g_slist_reverse (uids);
-}
-
-typedef struct {
-       EBookBackendFile *bf;
-       GThread *thread;
-       EFlag *running;
-} FileBackendSearchClosure;
-
-static void
-closure_destroy (FileBackendSearchClosure *closure)
-{
-       d (printf ("destroying search closure\n"));
-       e_flag_free (closure->running);
-       if (closure->thread)
-               g_thread_unref (closure->thread);
-       g_free (closure);
-}
-
-static FileBackendSearchClosure *
-init_closure (EDataBookView *book_view,
-              EBookBackendFile *bf)
-{
-       FileBackendSearchClosure *closure = g_new (FileBackendSearchClosure, 1);
-
-       closure->bf = bf;
-       closure->thread = NULL;
-       closure->running = e_flag_new ();
-
-       g_object_set_data_full (
-               G_OBJECT (book_view),
-               "EBookBackendFile.BookView::closure",
-               closure, (GDestroyNotify) closure_destroy);
-
-       return closure;
-}
-
-static FileBackendSearchClosure *
-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 prefiltered,
-                     const gchar *id,
-                     const gchar *vcard)
-{
-       if (prefiltered)
-               e_data_book_view_notify_update_prefiltered_vcard (book_view, id, vcard);
-       else
-               e_data_book_view_notify_update_vcard (book_view, id, vcard);
-}
-
-static gpointer
-book_view_thread (gpointer data)
-{
-       EDataBookView *book_view;
-       FileBackendSearchClosure *closure;
-       EBookBackendFile *bf;
-       EBookBackendSExp *sexp;
-       const gchar *query;
-       GSList *summary_list, *l;
-       GHashTable *fields_of_interest;
-       GError *local_error = NULL;
-
-       g_return_val_if_fail (E_IS_DATA_BOOK_VIEW (data), NULL);
-
-       book_view = data;
-       closure = get_closure (book_view);
-       if (!closure) {
-               g_warning (G_STRLOC ": NULL closure in book view thread");
-               return NULL;
-       }
-       bf = closure->bf;
-
-       d (printf ("starting initial population of book view\n"));
-
-       /* ref the book view because it'll be removed and unrefed
-        * when/if it's stopped */
-       g_object_ref (book_view);
-
-       sexp = e_data_book_view_get_sexp (book_view);
-       query = e_book_backend_sexp_text (sexp);
-
-       fields_of_interest = e_data_book_view_get_fields_of_interest (book_view);
-
-       if ( !strcmp (query, "(contains \"x-evolution-any-field\" \"\")")) {
-               e_data_book_view_notify_progress (book_view, -1, _("Loading..."));
-       } else {
-               e_data_book_view_notify_progress (book_view, -1, _("Searching..."));
-       }
-
-       d (printf ("signalling parent thread\n"));
-       e_flag_set (closure->running);
-
-       g_rw_lock_reader_lock (&(bf->priv->lock));
-       summary_list = e_book_backend_sqlitedb_search (
-               bf->priv->sqlitedb,
-               SQLITEDB_FOLDER_ID,
-               query, fields_of_interest,
-               NULL, NULL, &local_error);
-       g_rw_lock_reader_unlock (&(bf->priv->lock));
-
-       if (!summary_list && local_error != NULL) {
-               g_warning (G_STRLOC ": Failed to query initial contacts: %s", local_error->message);
-               g_error_free (local_error);
-               e_data_book_view_notify_complete (
-                       book_view,
-                       g_error_new_literal (
-                               E_CLIENT_ERROR,
-                               E_CLIENT_ERROR_NOT_OPENED,
-                               e_client_error_to_string (
-                               E_CLIENT_ERROR_NOT_OPENED)));
-               g_object_unref (book_view);
-               return NULL;
-       }
+       *contacts = contact_list;
+}
 
-       for (l = summary_list; l; l = l->next) {
-               EbSdbSearchData *data = l->data;
-               gchar *vcard = NULL;
+static void
+book_backend_file_get_contact_list_uids (EBookBackendSync *backend,
+                                         EDataBook *book,
+                                         GCancellable *cancellable,
+                                         const gchar *query,
+                                         GSList **contacts_uids,
+                                         GError **perror)
+{
+       EBookBackendFile *bf = E_BOOK_BACKEND_FILE (backend);
+       GSList           *uids = NULL;
+       GError           *local_error = NULL;
 
-               vcard = data->vcard;
-               data->vcard = NULL;
+       d (printf ("book_backend_file_get_contact_list (%s)\n", query));
 
-               notify_update_vcard (book_view, TRUE, data->uid, vcard);
-               g_free (vcard);
-       }
+       g_rw_lock_reader_lock (&(bf->priv->lock));
+       uids = e_book_backend_sqlitedb_search_uids (
+               bf->priv->sqlitedb,
+               SQLITEDB_FOLDER_ID,
+               query, NULL, &local_error);
+       g_rw_lock_reader_unlock (&(bf->priv->lock));
 
-       g_slist_foreach (summary_list, (GFunc) e_book_backend_sqlitedb_search_data_free, NULL);
-       g_slist_free (summary_list);
+       if (uids == NULL && local_error != NULL) {
 
-       if (e_flag_is_set (closure->running))
-               e_data_book_view_notify_complete (book_view, NULL /* Success */);
+               if (g_error_matches (local_error,
+                                    E_BOOK_SDB_ERROR,
+                                    E_BOOK_SDB_ERROR_NOT_SUPPORTED)) {
+                       g_set_error (
+                               perror, E_CLIENT_ERROR,
+                               E_CLIENT_ERROR_NOT_SUPPORTED,
+                               _("Query '%s' not supported"), query);
+                       g_error_free (local_error);
 
-       g_object_unref (book_view);
+               } else if (g_error_matches (local_error,
+                                    E_BOOK_SDB_ERROR,
+                                    E_BOOK_SDB_ERROR_INVALID_QUERY)) {
+                       g_set_error (
+                               perror, E_CLIENT_ERROR,
+                               E_CLIENT_ERROR_INVALID_QUERY,
+                               _("Invalid Query '%s'"), query);
+                       g_error_free (local_error);
 
-       d (printf ("finished population of book view\n"));
+               } else {
+                       g_warning ("Failed to fetch contact ids: %s", local_error->message);
+                       g_propagate_error (perror, local_error);
+               }
+       }
 
-       return NULL;
+       *contacts_uids = g_slist_reverse (uids);
 }
 
 static void
-e_book_backend_file_start_view (EBookBackend *backend,
-                                EDataBookView *book_view)
+book_backend_file_start_view (EBookBackend *backend,
+                              EDataBookView *book_view)
 {
        FileBackendSearchClosure *closure = init_closure (book_view, E_BOOK_BACKEND_FILE (backend));
 
@@ -1331,8 +1476,8 @@ e_book_backend_file_start_view (EBookBackend *backend,
 }
 
 static void
-e_book_backend_file_stop_view (EBookBackend *backend,
-                               EDataBookView *book_view)
+book_backend_file_stop_view (EBookBackend *backend,
+                             EDataBookView *book_view)
 {
        FileBackendSearchClosure *closure = get_closure (book_view);
        gboolean need_join;
@@ -1351,132 +1496,8 @@ e_book_backend_file_stop_view (EBookBackend *backend,
 }
 
 static void
-e_book_backend_file_open (EBookBackendSync *backend,
-                          EDataBook *book,
-                          GCancellable *cancellable,
-                          gboolean only_if_exists,
-                          GError **perror)
-{
-       EBookBackendFile *bf = E_BOOK_BACKEND_FILE (backend);
-       ESource          *source;
-       ESourceRevisionGuards *guards;
-
-       source = e_backend_get_source (E_BACKEND (backend));
-
-       g_type_ensure (E_TYPE_SOURCE_REVISION_GUARDS);
-       guards = e_source_get_extension (source, E_SOURCE_EXTENSION_REVISION_GUARDS);
-
-       bf->priv->revision_guards = e_source_revision_guards_get_enabled (guards);
-
-       g_rw_lock_writer_lock (&(bf->priv->lock));
-       if (!bf->priv->revision) {
-               e_book_backend_file_load_revision (bf);
-               e_book_backend_notify_property_changed (E_BOOK_BACKEND (backend),
-                                                       BOOK_BACKEND_PROPERTY_REVISION,
-                                                       bf->priv->revision);
-       }
-       g_rw_lock_writer_unlock (&(bf->priv->lock));
-
-       e_backend_set_online (E_BACKEND (backend), TRUE);
-       e_book_backend_set_writable (E_BOOK_BACKEND (backend), TRUE);
-}
-
-static gchar *
-e_book_backend_file_get_backend_property (EBookBackend *backend,
-                                          const gchar *prop_name)
-{
-       EBookBackendFile *bf = E_BOOK_BACKEND_FILE (backend);
-
-       g_return_val_if_fail (prop_name != NULL, NULL);
-
-       if (g_str_equal (prop_name, CLIENT_BACKEND_PROPERTY_CAPABILITIES)) {
-               return g_strdup ("local,do-initial-query,bulk-adds,bulk-modifies,bulk-removes,contact-lists");
-
-       } else if (g_str_equal (prop_name, BOOK_BACKEND_PROPERTY_REQUIRED_FIELDS)) {
-               return g_strdup (e_contact_field_name (E_CONTACT_FILE_AS));
-
-       } else if (g_str_equal (prop_name, BOOK_BACKEND_PROPERTY_SUPPORTED_FIELDS)) {
-               GString *fields;
-               gint ii;
-
-               fields = g_string_sized_new (1024);
-
-               /* XXX we need a way to say "we support everything", since the
-                * file backend does */
-               for (ii = 1; ii < E_CONTACT_FIELD_LAST; ii++) {
-                       if (fields->len > 0)
-                               g_string_append_c (fields, ',');
-                       g_string_append (fields, e_contact_field_name (ii));
-               }
-
-               return g_string_free (fields, FALSE);
-
-       } else if (g_str_equal (prop_name, BOOK_BACKEND_PROPERTY_REVISION)) {
-               gchar *prop_value;
-
-               g_rw_lock_reader_lock (&(bf->priv->lock));
-               prop_value = g_strdup (bf->priv->revision);
-               g_rw_lock_reader_unlock (&(bf->priv->lock));
-
-               return prop_value;
-       }
-
-       /* Chain up to parent's get_backend_property() method. */
-       return E_BOOK_BACKEND_CLASS (e_book_backend_file_parent_class)->
-               get_backend_property (backend, prop_name);
-}
-
-static void
-e_book_backend_file_sync (EBookBackend *backend)
-{
-       EBookBackendFile *bf = E_BOOK_BACKEND_FILE (backend);
-
-       g_return_if_fail (bf != NULL);
-
-       /* FIXME: Tell sqlite to dump NOW ! */
-}
-
-static void
-view_notify_update (EBookBackendFile *backend,
-                    EDataBookView *view,
-                    EContact *contact)
-{
-       EBookBackendSExp *sexp;
-       GHashTable *fields   = e_data_book_view_get_fields_of_interest (view);
-       const gchar *query;
-       gboolean    notified = FALSE;
-       gboolean    with_all_required_fields = FALSE;
-
-       sexp = e_data_book_view_get_sexp (view);
-       query = e_book_backend_sexp_text (sexp);
-
-       if (e_book_backend_sqlitedb_check_summary_query (backend->priv->sqlitedb, query, NULL) &&
-           e_book_backend_sqlitedb_check_summary_fields (backend->priv->sqlitedb, fields)) {
-
-               const gchar *uid = e_contact_get_const (contact, E_CONTACT_UID);
-               gchar       *vcard;
-
-               vcard = e_book_backend_sqlitedb_get_vcard_string (
-                       backend->priv->sqlitedb,
-                       SQLITEDB_FOLDER_ID, uid,
-                       fields, &with_all_required_fields, NULL);
-
-               if (vcard) {
-                       if (with_all_required_fields) {
-                               e_data_book_view_notify_update_prefiltered_vcard (view, uid, vcard);
-                               notified = TRUE;
-                       }
-                       g_free (vcard);
-               }
-       }
-
-       if (!notified)
-               e_data_book_view_notify_update (view, contact);
-}
-
-static void
-e_book_backend_file_notify_update (EBookBackend *backend,
-                                   const EContact *contact)
+book_backend_file_notify_update (EBookBackend *backend,
+                                 const EContact *contact)
 {
        GList *list, *link;
 
@@ -1491,35 +1512,54 @@ e_book_backend_file_notify_update (EBookBackend *backend,
        g_list_free_full (list, (GDestroyNotify) g_object_unref);
 }
 
-static void
-e_book_backend_file_dispose (GObject *object)
+static EDataBookDirect *
+book_backend_file_get_direct_book (EBookBackend *backend)
 {
-       EBookBackendFile *bf;
+       EDataBookDirect *direct;
+       ESourceRegistry *registry;
+       ESource *source;
+       gchar *backend_path;
+       gchar *dirname;
+       const gchar *modules_env = NULL;
 
-       bf = E_BOOK_BACKEND_FILE (object);
+       modules_env = g_getenv (EDS_ADDRESS_BOOK_MODULES);
 
-       if (bf->priv->sqlitedb) {
-               g_object_unref (bf->priv->sqlitedb);
-               bf->priv->sqlitedb = NULL;
-       }
+       source = e_backend_get_source (E_BACKEND (backend));
+       registry = e_book_backend_get_registry (backend);
+       dirname = e_book_backend_file_extract_path_from_source (
+               registry, source, GET_PATH_DB_DIR);
 
-       G_OBJECT_CLASS (e_book_backend_file_parent_class)->dispose (object);
+       /* Support in-tree testing / relocated modules */
+       if (modules_env)
+               backend_path = g_build_filename (modules_env, "libebookbackendfile.so", NULL);
+       else
+               backend_path = g_build_filename (BACKENDDIR, "libebookbackendfile.so", NULL);
+       direct = e_data_book_direct_new (backend_path, "EBookBackendFileFactory", dirname);
+
+       g_free (backend_path);
+       g_free (dirname);
+
+       return direct;
 }
 
 static void
-e_book_backend_file_finalize (GObject *object)
+book_backend_file_configure_direct (EBookBackend *backend,
+                                    const gchar *config)
 {
        EBookBackendFilePrivate *priv;
 
-       priv = E_BOOK_BACKEND_FILE_GET_PRIVATE (object);
+       priv = E_BOOK_BACKEND_FILE_GET_PRIVATE (backend);
+       priv->base_directory = g_strdup (config);
+}
 
-       g_free (priv->photo_dirname);
-       g_free (priv->revision);
-       g_free (priv->base_directory);
-       g_rw_lock_clear (&(priv->lock));
+static void
+book_backend_file_sync (EBookBackend *backend)
+{
+       EBookBackendFile *bf = E_BOOK_BACKEND_FILE (backend);
 
-       /* Chain up to parent's finalize() method. */
-       G_OBJECT_CLASS (e_book_backend_file_parent_class)->finalize (object);
+       g_return_if_fail (bf != NULL);
+
+       /* FIXME: Tell sqlite to dump NOW ! */
 }
 
 static gboolean
@@ -1656,77 +1696,36 @@ exit:
        return success;
 }
 
-static EDataBookDirect *
-e_book_backend_file_get_direct_book (EBookBackend *backend)
-{
-       EDataBookDirect *direct;
-       ESourceRegistry *registry;
-       ESource *source;
-       gchar *backend_path;
-       gchar *dirname;
-       const gchar *modules_env = NULL;
-
-       modules_env = g_getenv (EDS_ADDRESS_BOOK_MODULES);
-
-       source = e_backend_get_source (E_BACKEND (backend));
-       registry = e_book_backend_get_registry (backend);
-       dirname = e_book_backend_file_extract_path_from_source (
-               registry, source, GET_PATH_DB_DIR);
-
-       /* Support in-tree testing / relocated modules */
-       if (modules_env)
-               backend_path = g_build_filename (modules_env, "libebookbackendfile.so", NULL);
-       else
-               backend_path = g_build_filename (BACKENDDIR, "libebookbackendfile.so", NULL);
-       direct = e_data_book_direct_new (backend_path, "EBookBackendFileFactory", dirname);
-
-       g_free (backend_path);
-       g_free (dirname);
-
-       return direct;
-}
-
-static void
-e_book_backend_file_configure_direct (EBookBackend *backend,
-                                      const gchar *config)
-{
-       EBookBackendFilePrivate *priv;
-
-       priv = E_BOOK_BACKEND_FILE_GET_PRIVATE (backend);
-       priv->base_directory = g_strdup (config);
-}
-
 static void
 e_book_backend_file_class_init (EBookBackendFileClass *class)
 {
-       GObjectClass    *object_class = G_OBJECT_CLASS (class);
-       EBookBackendSyncClass *sync_class;
+       GObjectClass *object_class;
        EBookBackendClass *backend_class;
+       EBookBackendSyncClass *sync_class;
 
        g_type_class_add_private (class, sizeof (EBookBackendFilePrivate));
 
-       sync_class = E_BOOK_BACKEND_SYNC_CLASS (class);
+       object_class = G_OBJECT_CLASS (class);
+       object_class->dispose = book_backend_file_dispose;
+       object_class->finalize = book_backend_file_finalize;
+
        backend_class = E_BOOK_BACKEND_CLASS (class);
+       backend_class->get_backend_property = book_backend_file_get_backend_property;
+       backend_class->start_view = book_backend_file_start_view;
+       backend_class->stop_view = book_backend_file_stop_view;
+       backend_class->notify_update = book_backend_file_notify_update;
+       backend_class->get_direct_book = book_backend_file_get_direct_book;
+       backend_class->configure_direct = book_backend_file_configure_direct;
+       backend_class->sync = book_backend_file_sync;
 
-       /* Set the virtual methods. */
-       backend_class->get_backend_property = e_book_backend_file_get_backend_property;
-       backend_class->start_view               = e_book_backend_file_start_view;
-       backend_class->stop_view                = e_book_backend_file_stop_view;
-       backend_class->sync                     = e_book_backend_file_sync;
-       backend_class->notify_update            = e_book_backend_file_notify_update;
-       backend_class->get_direct_book          = e_book_backend_file_get_direct_book;
-       backend_class->configure_direct         = e_book_backend_file_configure_direct;
-
-       sync_class->open_sync                   = e_book_backend_file_open;
-       sync_class->create_contacts_sync        = e_book_backend_file_create_contacts;
-       sync_class->remove_contacts_sync        = e_book_backend_file_remove_contacts;
-       sync_class->modify_contacts_sync        = e_book_backend_file_modify_contacts;
-       sync_class->get_contact_sync            = e_book_backend_file_get_contact;
-       sync_class->get_contact_list_sync       = e_book_backend_file_get_contact_list;
-       sync_class->get_contact_list_uids_sync  = e_book_backend_file_get_contact_list_uids;
-
-       object_class->dispose = e_book_backend_file_dispose;
-       object_class->finalize = e_book_backend_file_finalize;
+       sync_class = E_BOOK_BACKEND_SYNC_CLASS (class);
+       sync_class->open_sync = book_backend_file_open;
+       sync_class->create_contacts_sync = book_backend_file_create_contacts;
+       sync_class->modify_contacts_sync = book_backend_file_modify_contacts;
+       sync_class->remove_contacts_sync = book_backend_file_remove_contacts;
+       sync_class->get_contact_sync = book_backend_file_get_contact;
+       sync_class->get_contact_list_sync = book_backend_file_get_contact_list;
+       sync_class->get_contact_list_uids_sync = book_backend_file_get_contact_list_uids;
 }
 
 static void


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