1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- */
4 * (GLABELS) Label and Business Card Creation program for GNOME
6 * merge_evolution.c: evolution merge backend module
8 * Copyright (C) 2001 Jim Evins <evins@snaught.com>.
10 * Copyright (C) 2005 Austin Henry <ahenry@users.sourceforge.net>
12 * This program is free software; you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License as published by
14 * the Free Software Foundation; either version 2 of the License, or
15 * (at your option) any later version.
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
32 #include "merge-evolution.h"
34 #include <libebook/e-book.h>
35 #include <glib/gi18n.h>
41 #define DEFAULT_QUERY "(exists \"full_name\")"
43 /*===========================================*/
45 /*===========================================*/
47 struct _glMergeEvolutionPrivate {
51 GList *fields; /* the fields supported by the addressbook */
63 /*===========================================*/
65 /*===========================================*/
67 /*===========================================*/
68 /* Local function prototypes */
69 /*===========================================*/
71 static void gl_merge_evolution_finalize (GObject *object);
73 static void gl_merge_evolution_set_property (GObject *object,
78 static void gl_merge_evolution_get_property (GObject *object,
83 static GList *gl_merge_evolution_get_key_list (glMerge *merge);
84 static gchar *gl_merge_evolution_get_primary_key (glMerge *merge);
85 static void gl_merge_evolution_open (glMerge *merge);
86 static void gl_merge_evolution_close (glMerge *merge);
87 static glMergeRecord *gl_merge_evolution_get_record (glMerge *merge);
88 static void gl_merge_evolution_copy (glMerge *dst_merge,
91 /* utility function prototypes go here */
92 static void free_field_list (GList *fields);
95 /*****************************************************************************/
96 /* Boilerplate object stuff. */
97 /*****************************************************************************/
98 G_DEFINE_TYPE (glMergeEvolution, gl_merge_evolution, GL_TYPE_MERGE);
101 gl_merge_evolution_class_init (glMergeEvolutionClass *class)
103 GObjectClass *object_class = G_OBJECT_CLASS (class);
104 glMergeClass *merge_class = GL_MERGE_CLASS (class);
106 gl_debug (DEBUG_MERGE, "START");
108 gl_merge_evolution_parent_class = g_type_class_peek_parent (class);
110 object_class->set_property = gl_merge_evolution_set_property;
111 object_class->get_property = gl_merge_evolution_get_property;
113 g_object_class_install_property
116 g_param_spec_string ("query", NULL,
117 "Query used to select records from the addressbook",
118 "(exists \"full_name\")",
119 (G_PARAM_READABLE | G_PARAM_WRITABLE)));
121 object_class->finalize = gl_merge_evolution_finalize;
123 merge_class->get_key_list = gl_merge_evolution_get_key_list;
124 merge_class->get_primary_key = gl_merge_evolution_get_primary_key;
125 merge_class->open = gl_merge_evolution_open;
126 merge_class->close = gl_merge_evolution_close;
127 merge_class->get_record = gl_merge_evolution_get_record;
128 merge_class->copy = gl_merge_evolution_copy;
130 gl_debug (DEBUG_MERGE, "END");
134 gl_merge_evolution_init (glMergeEvolution *merge_evolution)
136 gl_debug (DEBUG_MERGE, "START");
138 merge_evolution->priv = g_new0 (glMergeEvolutionPrivate, 1);
139 merge_evolution->priv->query = g_strdup(DEFAULT_QUERY);
141 gl_debug (DEBUG_MERGE, "END");
145 gl_merge_evolution_finalize (GObject *object)
147 glMergeEvolution *merge_evolution = GL_MERGE_EVOLUTION (object);
149 gl_debug (DEBUG_MERGE, "START");
151 g_return_if_fail (object && GL_IS_MERGE_EVOLUTION (object));
153 free_field_list(merge_evolution->priv->fields);
154 g_free (merge_evolution->priv->query);
155 g_free (merge_evolution->priv);
157 G_OBJECT_CLASS (gl_merge_evolution_parent_class)->finalize (object);
159 gl_debug (DEBUG_MERGE, "END");
162 /*--------------------------------------------------------------------------*/
164 /*--------------------------------------------------------------------------*/
166 gl_merge_evolution_set_property (GObject *object,
171 glMergeEvolution *merge_evolution;
173 merge_evolution = GL_MERGE_EVOLUTION (object);
178 g_free (merge_evolution->priv->query);
179 merge_evolution->priv->query = g_value_dup_string (value);
180 gl_debug (DEBUG_MERGE, "ARG \"query\" = \"%s\"",
181 merge_evolution->priv->query);
185 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
192 /*--------------------------------------------------------------------------*/
194 /*--------------------------------------------------------------------------*/
196 gl_merge_evolution_get_property (GObject *object,
201 glMergeEvolution *merge_evolution;
203 merge_evolution = GL_MERGE_EVOLUTION (object);
208 g_value_set_string (value, merge_evolution->priv->query);
212 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
219 /*--------------------------------------------------------------------------*/
221 /*--------------------------------------------------------------------------*/
223 gl_merge_evolution_get_key_list (glMerge *merge)
225 glMergeEvolution *merge_evolution;
226 GList *key_list = NULL;
229 gl_debug (DEBUG_MERGE, "BEGIN");
231 merge_evolution = GL_MERGE_EVOLUTION (merge);
233 /* for the previously retrieved supported fileds, go through them and find
234 * their pretty names */
235 for (iter = merge_evolution->priv->fields;
237 iter = g_list_next(iter))
239 key_list = g_list_prepend (key_list,
240 g_strdup (e_contact_pretty_name (*(EContactField *)iter->data)));
243 key_list = g_list_reverse (key_list);
245 gl_debug (DEBUG_MERGE, "END");
250 /*--------------------------------------------------------------------------*/
251 /* Get "primary" key. */
252 /*--------------------------------------------------------------------------*/
254 gl_merge_evolution_get_primary_key (glMerge *merge)
256 return g_strdup (e_contact_pretty_name(E_CONTACT_FILE_AS));
259 /*--------------------------------------------------------------------------*/
260 /* Open merge source. */
261 /*--------------------------------------------------------------------------*/
263 gl_merge_evolution_open (glMerge *merge)
265 glMergeEvolution *merge_evolution;
268 GList *fields, *iter;
269 EContactField *field_id;
272 gl_debug (DEBUG_MERGE, "BEGIN");
274 merge_evolution = GL_MERGE_EVOLUTION (merge);
276 query = e_book_query_from_string(merge_evolution->priv->query);
278 g_warning (_("Couldn't construct query"));
282 merge_evolution->priv->book = e_book_new_system_addressbook(&error);
283 if (!merge_evolution->priv->book) {
284 g_warning (_("Couldn't open addressbook: %s"), error->message);
285 e_book_query_unref(query);
286 g_error_free (error);
290 if (!e_book_open(merge_evolution->priv->book, TRUE, &error)) {
291 g_warning (_("Couldn't open addressbook: %s"), error->message);
292 g_error_free (error);
293 e_book_query_unref(query);
294 g_object_unref(merge_evolution->priv->book);
295 merge_evolution->priv->book = NULL;
299 /* fetch the list of fields supported by this address book */
300 status = e_book_get_supported_fields(merge_evolution->priv->book,
302 if (status == FALSE) {
303 g_warning (_("Couldn't list available fields: %s"), error->message);
304 g_error_free (error);
305 e_book_query_unref(query);
306 g_object_unref(merge_evolution->priv->book);
307 merge_evolution->priv->book = NULL;
311 /* generate a list of field_ids, and put that into private->fields */
312 for (iter = fields; iter != NULL; iter = g_list_next(iter)) {
313 field_id = g_new(EContactField, 1);
314 *field_id = e_contact_field_id(iter->data);
316 /* above this value, the data aren't strings anymore */
317 if (*field_id >= E_CONTACT_LAST_SIMPLE_STRING) {
322 merge_evolution->priv->fields =
323 g_list_prepend(merge_evolution->priv->fields, field_id);
325 free_field_list(fields); /* don't need the list of names anymore */
327 gl_debug(DEBUG_MERGE, "Field list length: %d", g_list_length(merge_evolution->priv->fields));
329 /* finally retrieve the contacts */
330 status = e_book_get_contacts (merge_evolution->priv->book,
332 &merge_evolution->priv->contacts,
334 if (status == FALSE) {
335 g_warning (_("Couldn't get contacts: %s"), error->message);
336 g_error_free (error);
337 e_book_query_unref(query);
338 free_field_list(merge_evolution->priv->fields);
339 g_object_unref(merge_evolution->priv->book);
340 merge_evolution->priv->book = NULL;
345 e_book_query_unref(query);
347 gl_debug (DEBUG_MERGE, "END");
350 /* XXX I should probably sort the list by name (or the file-as element)*/
353 /*--------------------------------------------------------------------------*/
354 /* Close merge source. */
355 /*--------------------------------------------------------------------------*/
357 gl_merge_evolution_close (glMerge *merge)
359 glMergeEvolution *merge_evolution;
362 merge_evolution = GL_MERGE_EVOLUTION (merge);
364 /* unref all of the objects created in _open */
365 g_object_unref(merge_evolution->priv->book);
366 merge_evolution->priv->book = NULL;
368 for (iter = merge_evolution->priv->contacts;
370 iter = g_list_next(iter))
372 EContact *contact = E_CONTACT (iter->data);
374 g_object_unref(contact);
376 g_list_free(merge_evolution->priv->contacts);
377 merge_evolution->priv->contacts = NULL;
380 /*--------------------------------------------------------------------------*/
381 /* Get next record from merge source, NULL if no records left (i.e EOF) */
382 /*--------------------------------------------------------------------------*/
383 static glMergeRecord *
384 gl_merge_evolution_get_record (glMerge *merge)
386 glMergeEvolution *merge_evolution;
387 glMergeRecord *record;
389 EContactField field_id;
394 merge_evolution = GL_MERGE_EVOLUTION (merge);
396 head = merge_evolution->priv->contacts;
398 return NULL; /* past the last record */
400 contact = E_CONTACT(head->data);
402 record = g_new0 (glMergeRecord, 1);
403 record->select_flag = TRUE;
405 /* Take the interesting fields one by one from the contact, and put them
406 * into the glMergeRecord structure. When done, free up the resources for
409 /* iterate through the supported fields, and add them to the list */
410 for (iter = merge_evolution->priv->fields;
412 iter = g_list_next(iter))
415 field_id = *(EContactField *)iter->data;
416 value = g_strdup (e_contact_get_const (contact, field_id));
419 field = g_new0 (glMergeField, 1);
420 field->key = g_strdup (e_contact_pretty_name (field_id));
421 field->value = value;
422 record->field_list = g_list_prepend (record->field_list, field);
426 record->field_list = g_list_reverse (record->field_list);
428 /* do a destructive read */
429 g_object_unref (contact);
430 merge_evolution->priv->contacts =
431 g_list_remove_link (merge_evolution->priv->contacts, head);
432 g_list_free_1 (head);
437 /*---------------------------------------------------------------------------*/
438 /* Copy merge_evolution specific fields. */
439 /*---------------------------------------------------------------------------*/
441 gl_merge_evolution_copy (glMerge *dst_merge,
444 GList *src_iter, *dst_iter;
446 gl_debug (DEBUG_MERGE, "BEGIN");
448 glMergeEvolution *dst_merge_evolution;
449 glMergeEvolution *src_merge_evolution;
451 dst_merge_evolution = GL_MERGE_EVOLUTION (dst_merge);
452 src_merge_evolution = GL_MERGE_EVOLUTION (src_merge);
454 dst_merge_evolution->priv->query = g_strdup(src_merge_evolution->priv->query);
456 dst_merge_evolution->priv->fields = g_list_copy(src_merge_evolution->priv->fields);
457 for (src_iter = src_merge_evolution->priv->fields,
458 dst_iter = dst_merge_evolution->priv->fields;
459 src_iter != NULL && dst_iter != NULL;
460 src_iter = g_list_next(src_iter), dst_iter = g_list_next(dst_iter))
462 dst_iter->data = g_new(EContactField, 1);
463 if (src_iter->data) { /* this better not be null, but... */
464 memcpy(dst_iter->data, src_iter->data, sizeof(EContactField));
468 /* I don't know that there's a good way to do a deep copy of the various
469 * libebook structures/objects, so I'm just going to leave them out. They
470 * are all regenerated on gl_merge_evolution_open, anyway */
472 gl_debug (DEBUG_MERGE, "END");
475 /*---------------------------------------------------------------------------*/
476 /* Free the list of supported fields */
477 /*---------------------------------------------------------------------------*/
479 free_field_list (GList *fields)
483 for (iter = fields; iter != NULL; iter = g_list_next(iter))
494 #endif /* HAVE_LIBEBOOK */