Adding cursor example program
[platform/upstream/evolution-data-server.git] / tests / cursor-example / cursor-data.c
1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
2 /*
3  * Copyright (C) 2013 Intel Corporation
4  *
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.
8  *
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.
13  *
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.
18  *
19  * Author: Tristan Van Berkom <tristanvb@openismus.com>
20  */
21 #include "cursor-data.h"
22
23 #define CURSOR_DATA_SOURCE_ID "cursor-example-book"
24
25 static void                  load_contacts (EBookClient          *client,
26                                             const gchar          *vcard_directory);
27 static EBookClientCursor    *get_cursor    (EBookClient          *book_client);
28
29 /* Just an example, we need to spin the main loop
30  * a bit to wait for the ESource to be created,
31  *
32  * So lets just use some global variables here
33  */
34 static EBookClient *address_book = NULL;
35 static ESource     *address_book_source = NULL;
36
37 static void
38 cursor_data_source_added (ESourceRegistry *registry,
39                           ESource *source,
40                           gpointer data)
41 {
42         GError    *error = NULL;
43         GMainLoop *loop = (GMainLoop *)data;
44
45         if (g_strcmp0 (e_source_get_uid (source), CURSOR_DATA_SOURCE_ID) != 0)
46                 return;
47
48         /* Open the address book */
49         address_book = (EBookClient *)e_book_client_connect_sync (source, NULL, &error);
50         if (!address_book)
51                 g_error ("Unable to create the test book: %s", error->message);
52
53         address_book_source = g_object_ref (source);
54
55         if (loop)
56                 g_main_loop_quit (loop);
57 }
58
59 static gboolean
60 cursor_data_source_timeout (gpointer user_data)
61 {
62         g_error ("Timed out while waiting for ESource creation from the registry");
63
64         return FALSE;
65 }
66
67 static void
68 setup_custom_book (ESource *scratch)
69 {
70         ESourceBackendSummarySetup *setup;
71
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 (
75                 setup,
76                 E_CONTACT_FULL_NAME,
77                 E_CONTACT_FAMILY_NAME,
78                 E_CONTACT_GIVEN_NAME,
79                 E_CONTACT_NICKNAME,
80                 E_CONTACT_TEL,
81                 E_CONTACT_EMAIL,
82                 0);
83         e_source_backend_summary_setup_set_indexed_fields (
84                 setup,
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,
92                 0);
93 }
94
95 /* This ensures that all of the test contacts are
96  * installed in the CURSOR_DATA_SOURCE_ID test book.
97  *
98  * Then it opens an EBookClientCursor.
99  *
100  * The cursor has no filter on the results and is
101  * ordered by family name (ascending) and then given name (ascending).
102  */
103 EBookClient *
104 cursor_load_data (const gchar        *vcard_path,
105                   EBookClientCursor **ret_cursor)
106 {
107         ESourceRegistry *registry;
108         ESource *scratch;
109         ESourceBackend *backend = NULL;
110         ESourceBackendSummarySetup *setup = NULL;
111         EBookClientCursor *cursor = NULL;
112         GMainLoop *loop;
113         GError  *error = NULL;
114         GSList *contacts = NULL;
115         EBookClient *ret_book;
116
117         g_return_val_if_fail (vcard_path != NULL, NULL);
118         g_return_val_if_fail (ret_cursor != NULL, NULL);
119
120         loop = g_main_loop_new (NULL, FALSE);
121
122         registry = e_source_registry_new_sync (NULL, &error);
123         if (!registry)
124                 g_error ("Unable to create the registry: %s", error->message);
125
126         /* Listen to the registry for our added source */
127         g_signal_connect (registry, "source-added",
128                           G_CALLBACK (cursor_data_source_added), loop);
129
130         /* Now create a scratch source for our addressbook */
131         scratch = e_source_new_with_uid (CURSOR_DATA_SOURCE_ID, NULL, &error);
132
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");
136
137         /* Setup custom summary fields, so that we can use those fields with the cursor */
138         setup_custom_book (scratch);
139
140         /* Commit the source to the registry */
141         if (!e_source_registry_commit_source_sync (registry, scratch, NULL, &error)) {
142
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);
147
148                         g_clear_error (&error);
149                         g_assert (E_IS_SOURCE (source));
150
151                         /* Run the callback which creates the addressbook client connection */
152                         cursor_data_source_added (registry, source, NULL);
153                         g_object_unref (source);
154                 } else
155                         g_error ("Unable to add new addressbook source to the registry: %s", error->message);
156         }
157
158         g_object_unref (scratch);
159
160         if (address_book == NULL) {
161                 g_timeout_add (20 * 1000, cursor_data_source_timeout, NULL);
162                 g_main_loop_run (loop);
163
164                 /* By now we aborted or we have an addressbook created */
165                 g_assert (address_book != NULL);
166         }
167
168         /**********************************************************
169          * Ok, done with creating an addressbook, let's add data  *
170          **********************************************************/
171
172         /* First check if there are already some contacts, if so then
173          * avoid adding them again
174          */
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");
178
179         if (contacts != NULL) {
180                 /* We already have contacts, no need to add them */
181                 g_slist_free_full (contacts, (GDestroyNotify)g_free);
182                 contacts = NULL;
183         } else {
184                 load_contacts (address_book, vcard_path);
185         }
186
187         /* Addressbook should have contacts now, let's create the cursor */
188         *ret_cursor = get_cursor (address_book);
189
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);
194
195         /* Give the ref through the return value*/
196         ret_book = address_book;
197
198         address_book_source = NULL;
199         address_book = NULL;
200
201         /* Return the addressbook */
202         return ret_book;
203 }
204
205 static EContact *
206 contact_from_file (const gchar *vcard_file)
207 {
208         EContact *contact;
209         GError *error;
210         gchar *vcard = NULL;
211
212         if (!g_file_get_contents (vcard_file, &vcard, NULL, &error))
213                 g_error ("Failed to load vcard: %s", error->message);
214
215         contact = e_contact_new_from_vcard (vcard);
216         g_free (vcard);
217
218         return contact;
219 }
220
221 static void
222 load_contacts (EBookClient *client,
223                const gchar *vcard_directory)
224 {
225         GDir *dir;
226         GError *error = NULL;
227         const gchar *filename;
228         GSList *contacts = NULL;
229
230         dir = g_dir_open (vcard_directory, 0, &error);
231         if (!dir)
232                 g_error ("Failed to open vcard directory '%s': %s", vcard_directory, error->message);
233
234         while ((filename = g_dir_read_name (dir)) != NULL) {
235
236                 if (g_str_has_suffix (filename, ".vcf")) {
237                         gchar *fullpath = g_build_filename (vcard_directory, filename, NULL);
238                         EContact *contact;
239
240                         g_print ("Loading contact from: %s\n", fullpath);
241
242                         contact = contact_from_file (fullpath);
243                         contacts = g_slist_prepend (contacts, contact);
244
245                         g_free (fullpath);
246                 }
247         }
248
249         g_dir_close (dir);
250
251         if (contacts != NULL) {
252
253                 if (!e_book_client_add_contacts_sync (client, contacts, NULL, NULL, &error))
254                         g_error ("Failed to add contacts");
255         } else
256                 g_error ("No contacts found in vcard directory: %s", vcard_directory);
257 }
258
259
260
261 static gchar *
262 get_addressbook_directory (ESourceRegistry *registry,
263                            ESource         *source)
264 {
265         ESource *builtin_source;
266         const gchar *user_data_dir;
267         const gchar *uid;
268         gchar *filename = NULL;
269
270         uid = e_source_get_uid (source);
271         g_return_val_if_fail (uid != NULL, NULL);
272
273         user_data_dir = e_get_user_data_dir ();
274
275         builtin_source = e_source_registry_ref_builtin_address_book (registry);
276
277         /* Special case directory for the builtin addressbook source */
278         if (builtin_source != NULL && e_source_equal (source, builtin_source))
279                 uid = "system";
280
281         filename = g_build_filename (user_data_dir, "addressbook", uid, NULL);
282
283         if (builtin_source)
284                 g_object_unref (builtin_source);
285
286         return filename;
287 }
288
289 static EBookClientCursor *
290 get_cursor (EBookClient *book_client)
291 {
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;
296
297   if (!e_book_client_get_cursor_sync (book_client,
298                                       NULL,
299                                       sort_fields,
300                                       sort_types,
301                                       2,
302                                       &cursor,
303                                       NULL,
304                                       &error)) {
305           g_warning ("Unable to create cursor");
306           g_clear_error (&error);
307   }
308
309   return cursor;
310 }