1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
3 * Copyright (C) 2013 Intel Corporation
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of version 2 of the GNU Lesser General Public
7 * License as published by the Free Software Foundation.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * General Public License for more details.
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this program; if not, write to the
16 * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
17 * Boston, MA 02110-1301, USA.
19 * Author: Tristan Van Berkom <tristanvb@openismus.com>
21 #include "cursor-data.h"
23 #define CURSOR_DATA_SOURCE_ID "cursor-example-book"
25 static void load_contacts (EBookClient *client,
26 const gchar *vcard_directory);
27 static EBookClientCursor *get_cursor (EBookClient *book_client);
29 /* Just an example, we need to spin the main loop
30 * a bit to wait for the ESource to be created,
32 * So lets just use some global variables here
34 static EBookClient *address_book = NULL;
35 static ESource *address_book_source = NULL;
38 cursor_data_source_added (ESourceRegistry *registry,
43 GMainLoop *loop = (GMainLoop *)data;
45 if (g_strcmp0 (e_source_get_uid (source), CURSOR_DATA_SOURCE_ID) != 0)
48 /* Open the address book */
49 address_book = (EBookClient *)e_book_client_connect_sync (source, NULL, &error);
51 g_error ("Unable to create the test book: %s", error->message);
53 address_book_source = g_object_ref (source);
56 g_main_loop_quit (loop);
60 cursor_data_source_timeout (gpointer user_data)
62 g_error ("Timed out while waiting for ESource creation from the registry");
68 setup_custom_book (ESource *scratch)
70 ESourceBackendSummarySetup *setup;
72 g_type_ensure (E_TYPE_SOURCE_BACKEND_SUMMARY_SETUP);
73 setup = e_source_get_extension (scratch, E_SOURCE_EXTENSION_BACKEND_SUMMARY_SETUP);
74 e_source_backend_summary_setup_set_summary_fields (
77 E_CONTACT_FAMILY_NAME,
83 e_source_backend_summary_setup_set_indexed_fields (
85 E_CONTACT_FULL_NAME, E_BOOK_INDEX_PREFIX,
86 E_CONTACT_FAMILY_NAME, E_BOOK_INDEX_PREFIX,
87 E_CONTACT_GIVEN_NAME, E_BOOK_INDEX_PREFIX,
88 E_CONTACT_NICKNAME, E_BOOK_INDEX_PREFIX,
89 E_CONTACT_TEL, E_BOOK_INDEX_PREFIX,
90 E_CONTACT_TEL, E_BOOK_INDEX_PHONE,
91 E_CONTACT_EMAIL, E_BOOK_INDEX_PREFIX,
95 /* This ensures that all of the test contacts are
96 * installed in the CURSOR_DATA_SOURCE_ID test book.
98 * Then it opens an EBookClientCursor.
100 * The cursor has no filter on the results and is
101 * ordered by family name (ascending) and then given name (ascending).
104 cursor_load_data (const gchar *vcard_path,
105 EBookClientCursor **ret_cursor)
107 ESourceRegistry *registry;
109 ESourceBackend *backend = NULL;
110 ESourceBackendSummarySetup *setup = NULL;
111 EBookClientCursor *cursor = NULL;
113 GError *error = NULL;
114 GSList *contacts = NULL;
115 EBookClient *ret_book;
117 g_return_val_if_fail (vcard_path != NULL, NULL);
118 g_return_val_if_fail (ret_cursor != NULL, NULL);
120 loop = g_main_loop_new (NULL, FALSE);
122 registry = e_source_registry_new_sync (NULL, &error);
124 g_error ("Unable to create the registry: %s", error->message);
126 /* Listen to the registry for our added source */
127 g_signal_connect (registry, "source-added",
128 G_CALLBACK (cursor_data_source_added), loop);
130 /* Now create a scratch source for our addressbook */
131 scratch = e_source_new_with_uid (CURSOR_DATA_SOURCE_ID, NULL, &error);
133 /* Ensure the new ESource will be a local addressbook source */
134 backend = e_source_get_extension (scratch, E_SOURCE_EXTENSION_ADDRESS_BOOK);
135 e_source_backend_set_backend_name (backend, "local");
137 /* Setup custom summary fields, so that we can use those fields with the cursor */
138 setup_custom_book (scratch);
140 /* Commit the source to the registry */
141 if (!e_source_registry_commit_source_sync (registry, scratch, NULL, &error)) {
143 /* It's possible the source already exists if we already ran the example with this data server */
144 if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_EXISTS)) {
145 /* If so... then just call our callback early */
146 ESource *source = e_source_registry_ref_source (registry, CURSOR_DATA_SOURCE_ID);
148 g_clear_error (&error);
149 g_assert (E_IS_SOURCE (source));
151 /* Run the callback which creates the addressbook client connection */
152 cursor_data_source_added (registry, source, NULL);
153 g_object_unref (source);
155 g_error ("Unable to add new addressbook source to the registry: %s", error->message);
158 g_object_unref (scratch);
160 if (address_book == NULL) {
161 g_timeout_add (20 * 1000, cursor_data_source_timeout, NULL);
162 g_main_loop_run (loop);
164 /* By now we aborted or we have an addressbook created */
165 g_assert (address_book != NULL);
168 /**********************************************************
169 * Ok, done with creating an addressbook, let's add data *
170 **********************************************************/
172 /* First check if there are already some contacts, if so then
173 * avoid adding them again
175 if (!e_book_client_get_contacts_uids_sync (address_book,
176 "", &contacts, NULL, &error))
177 g_error ("Failed to query addressbook for existing contacts");
179 if (contacts != NULL) {
180 /* We already have contacts, no need to add them */
181 g_slist_free_full (contacts, (GDestroyNotify)g_free);
184 load_contacts (address_book, vcard_path);
187 /* Addressbook should have contacts now, let's create the cursor */
188 *ret_cursor = get_cursor (address_book);
190 /* Cleanup some resources we used to populate the addressbook */
191 g_main_loop_unref (loop);
192 g_object_unref (address_book_source);
193 g_object_unref (registry);
195 /* Give the ref through the return value*/
196 ret_book = address_book;
198 address_book_source = NULL;
201 /* Return the addressbook */
206 contact_from_file (const gchar *vcard_file)
212 if (!g_file_get_contents (vcard_file, &vcard, NULL, &error))
213 g_error ("Failed to load vcard: %s", error->message);
215 contact = e_contact_new_from_vcard (vcard);
222 load_contacts (EBookClient *client,
223 const gchar *vcard_directory)
226 GError *error = NULL;
227 const gchar *filename;
228 GSList *contacts = NULL;
230 dir = g_dir_open (vcard_directory, 0, &error);
232 g_error ("Failed to open vcard directory '%s': %s", vcard_directory, error->message);
234 while ((filename = g_dir_read_name (dir)) != NULL) {
236 if (g_str_has_suffix (filename, ".vcf")) {
237 gchar *fullpath = g_build_filename (vcard_directory, filename, NULL);
240 g_print ("Loading contact from: %s\n", fullpath);
242 contact = contact_from_file (fullpath);
243 contacts = g_slist_prepend (contacts, contact);
251 if (contacts != NULL) {
253 if (!e_book_client_add_contacts_sync (client, contacts, NULL, NULL, &error))
254 g_error ("Failed to add contacts");
256 g_error ("No contacts found in vcard directory: %s", vcard_directory);
262 get_addressbook_directory (ESourceRegistry *registry,
265 ESource *builtin_source;
266 const gchar *user_data_dir;
268 gchar *filename = NULL;
270 uid = e_source_get_uid (source);
271 g_return_val_if_fail (uid != NULL, NULL);
273 user_data_dir = e_get_user_data_dir ();
275 builtin_source = e_source_registry_ref_builtin_address_book (registry);
277 /* Special case directory for the builtin addressbook source */
278 if (builtin_source != NULL && e_source_equal (source, builtin_source))
281 filename = g_build_filename (user_data_dir, "addressbook", uid, NULL);
284 g_object_unref (builtin_source);
289 static EBookClientCursor *
290 get_cursor (EBookClient *book_client)
292 EContactField sort_fields[] = { E_CONTACT_FAMILY_NAME, E_CONTACT_GIVEN_NAME };
293 EBookCursorSortType sort_types[] = { E_BOOK_CURSOR_SORT_ASCENDING, E_BOOK_CURSOR_SORT_ASCENDING };
294 EBookClientCursor *cursor = NULL;
295 GError *error = NULL;
297 if (!e_book_client_get_cursor_sync (book_client,
305 g_warning ("Unable to create cursor");
306 g_clear_error (&error);