/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
/*
* Copyright (C) 2013 Intel Corporation
*
* This library 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.
*
* This library 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 this library. If not, see .
*
* Authors: Tristan Van Berkom
*/
#include "cursor-data.h"
#define CURSOR_DATA_SOURCE_ID "cursor-example-book"
/* We need to spin the main loop a bit to wait for the ESource
* to be created. This particular API is admittedly cumbersome,
* hopefully this will be fixed in a later version so that
* the ESource can be synchronously created.
*
* Just an example so lets just use some global variables here...
*/
static EBookClient *address_book = NULL;
static ESource *address_book_source = NULL;
static void
cursor_data_source_added (ESourceRegistry *registry,
ESource *source,
gpointer data)
{
GError *error = NULL;
GMainLoop *loop = (GMainLoop *) data;
if (g_strcmp0 (e_source_get_uid (source), CURSOR_DATA_SOURCE_ID) != 0)
return;
/* Open the address book */
address_book = (EBookClient *) e_book_client_connect_sync (source, 30, NULL, &error);
if (!address_book)
g_error ("Unable to create the test book: %s", error->message);
address_book_source = g_object_ref (source);
if (loop)
g_main_loop_quit (loop);
}
static gboolean
cursor_data_source_timeout (gpointer user_data)
{
g_error ("Timed out while waiting for ESource creation from the registry");
return FALSE;
}
/*
* Helper function to load a contact from a vcard file.
*/
static EContact *
contact_from_file (const gchar *vcard_file)
{
EContact *contact;
GError *error;
gchar *vcard = NULL;
if (!g_file_get_contents (vcard_file, &vcard, NULL, &error))
g_error ("Failed to load vcard: %s", error->message);
contact = e_contact_new_from_vcard (vcard);
g_free (vcard);
return contact;
}
/*
* Load all the contacts from 'vcard_directory', and add them to 'client'.
*/
static void
load_contacts (EBookClient *client,
const gchar *vcard_directory)
{
GDir *dir;
GError *error = NULL;
const gchar *filename;
GSList *contacts = NULL;
dir = g_dir_open (vcard_directory, 0, &error);
if (!dir)
g_error ("Failed to open vcard directory '%s': %s", vcard_directory, error->message);
while ((filename = g_dir_read_name (dir)) != NULL) {
if (g_str_has_suffix (filename, ".vcf")) {
gchar *fullpath = g_build_filename (vcard_directory, filename, NULL);
EContact *contact;
contact = contact_from_file (fullpath);
contacts = g_slist_prepend (contacts, contact);
g_free (fullpath);
}
}
g_dir_close (dir);
if (contacts != NULL) {
if (!e_book_client_add_contacts_sync (client, contacts, E_BOOK_OPERATION_FLAG_NONE, NULL, NULL, &error)) {
/* If they were already added, ignore the error */
if (g_error_matches (error, E_BOOK_CLIENT_ERROR,
E_BOOK_CLIENT_ERROR_CONTACT_ID_ALREADY_EXISTS))
g_clear_error (&error);
else
g_error ("Failed to add test contacts: %s", error->message);
}
}
}
/*
* Create an EBookClient cursor sorted by family name, and then by given name as
* the secondary sort key.
*/
static EBookClientCursor *
get_cursor (EBookClient *book_client)
{
EContactField sort_fields[] = { E_CONTACT_FAMILY_NAME, E_CONTACT_GIVEN_NAME };
EBookCursorSortType sort_types[] = { E_BOOK_CURSOR_SORT_ASCENDING, E_BOOK_CURSOR_SORT_ASCENDING };
EBookClientCursor *cursor = NULL;
GError *error = NULL;
if (!e_book_client_get_cursor_sync (book_client,
NULL,
sort_fields,
sort_types,
2,
&cursor,
NULL,
&error)) {
g_warning ("Unable to create cursor");
g_clear_error (&error);
}
return cursor;
}
/* Entry point for this file, here we take care of
* creating the addressbook if it doesn't exist,
* getting an EBookClient, and creating our EBookClientCursor.
*/
EBookClient *
cursor_load_data (const gchar *vcard_path,
EBookClientCursor **ret_cursor)
{
ESourceRegistry *registry;
ESource *scratch;
ESourceBackend *backend = NULL;
GMainLoop *loop;
GError *error = NULL;
EBookClient *ret_book;
g_return_val_if_fail (vcard_path != NULL, NULL);
g_return_val_if_fail (ret_cursor != NULL, NULL);
g_print ("Cursor loading data from %s\n", vcard_path);
loop = g_main_loop_new (NULL, FALSE);
registry = e_source_registry_new_sync (NULL, &error);
if (!registry)
g_error ("Unable to create the registry: %s", error->message);
/* Listen to the registry for our added source */
g_signal_connect (
registry, "source-added",
G_CALLBACK (cursor_data_source_added), loop);
/* Now create a scratch source for our addressbook */
scratch = e_source_new_with_uid (CURSOR_DATA_SOURCE_ID, NULL, &error);
/* Ensure the new ESource will be a local addressbook source */
backend = e_source_get_extension (scratch, E_SOURCE_EXTENSION_ADDRESS_BOOK);
e_source_backend_set_backend_name (backend, "local");
/* Now is the right time to use the ESourceBackendSummarySetup to configure
* your newly created addressbook. This configuration should happen on the
* scratch source before calling e_source_registry_commit_source_sync().
*/
/* Commit the source to the registry */
if (!e_source_registry_commit_source_sync (registry, scratch, NULL, &error)) {
/* It's possible the source already exists if we already ran the example with this data server */
if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_EXISTS)) {
/* If so... then just call our callback early */
ESource *source = e_source_registry_ref_source (registry, CURSOR_DATA_SOURCE_ID);
g_clear_error (&error);
g_return_val_if_fail (E_IS_SOURCE (source), NULL);
/* Run the callback which creates the addressbook client connection */
cursor_data_source_added (registry, source, NULL);
g_object_unref (source);
} else
g_error ("Unable to add new addressbook source to the registry: %s", error->message);
}
g_object_unref (scratch);
/* Give EDS a little time to actually create the ESource remotely and
* also have a copy if it cached locally, wait for the "source-added"
* signal.
*/
if (address_book == NULL) {
g_timeout_add_seconds (20, cursor_data_source_timeout, NULL);
g_main_loop_run (loop);
/* By now we aborted or we have an addressbook created */
g_return_val_if_fail (address_book != NULL, NULL);
}
/**********************************************************
* Ok, done with creating an addressbook, let's add data *
**********************************************************/
load_contacts (address_book, vcard_path);
/* Addressbook should have contacts now, let's create the cursor */
*ret_cursor = get_cursor (address_book);
/* Cleanup some resources we used to populate the addressbook */
g_main_loop_unref (loop);
g_object_unref (address_book_source);
g_object_unref (registry);
/* Give the ref through the return value*/
ret_book = address_book;
address_book_source = NULL;
address_book = NULL;
/* Return the addressbook */
return ret_book;
}