From: Jim Evins Date: Tue, 25 Oct 2005 03:01:56 +0000 (+0000) Subject: 2005-10-24 Jim Evins X-Git-Tag: glabels-2_3_0~398 X-Git-Url: https://git.sur5r.net/?a=commitdiff_plain;h=6564675732a6cf86f70960aa83070cc64e940235;p=glabels 2005-10-24 Jim Evins * AUTHORS: * src/Makefile.am: * src/merge-evolution.c: * src/merge-evolution.h: * src/merge-init.c: (gl_merge_init): * src/merge-properties-dialog.c: (type_changed_cb): * src/merge-vcard.c: * src/merge-vcard.h: * src/ui-commands.c: (gl_ui_cmd_help_about): Added Evolution Data Server and VCard merge backends. Original patch provided by Austin Henry . * configure.in: Only support EDS and VCard backends if libebook is installed. Allow user to disable support, even if installed. git-svn-id: https://glabels.svn.sourceforge.net/svnroot/glabels/trunk@557 f5e0f49d-192f-0410-a22d-a8d8700d0965 --- diff --git a/glabels2/AUTHORS b/glabels2/AUTHORS index b3a63e1d..21a47bb0 100644 --- a/glabels2/AUTHORS +++ b/glabels2/AUTHORS @@ -43,6 +43,7 @@ Glabels includes contributions from: Frederic Ruaudel Emmanuel Pacaud Wayne Schuller + Austin Henry -- EDS and vcard backends nestor di -- excellent splash screen that first appeared in 0.4.3: diff --git a/glabels2/ChangeLog b/glabels2/ChangeLog index bd2eaa6e..ce58c163 100644 --- a/glabels2/ChangeLog +++ b/glabels2/ChangeLog @@ -1,3 +1,20 @@ +2005-10-24 Jim Evins + + * AUTHORS: + * src/Makefile.am: + * src/merge-evolution.c: + * src/merge-evolution.h: + * src/merge-init.c: (gl_merge_init): + * src/merge-properties-dialog.c: (type_changed_cb): + * src/merge-vcard.c: + * src/merge-vcard.h: + * src/ui-commands.c: (gl_ui_cmd_help_about): + Added Evolution Data Server and VCard merge backends. Original patch + provided by Austin Henry . + * configure.in: + Only support EDS and VCard backends if libebook is installed. Allow + user to disable support, even if installed. + 2005-10-24 Jim Evins * AUTHORS: diff --git a/glabels2/configure.in b/glabels2/configure.in index fa0542e1..851b7bc8 100644 --- a/glabels2/configure.in +++ b/glabels2/configure.in @@ -59,6 +59,7 @@ LIBGNOMEPRINT_REQUIRED=2.10.0 LIBGNOMEPRINTUI_REQUIRED=2.10.0 LIBGNOMECANVAS_REQUIRED=2.10.0 LIBGLADE_REQUIRED=2.5.0 +LIBEBOOK_REQUIRED=1.2.0 dnl Make above strings available for packaging files (e.g. rpm spec files) AC_SUBST(GLIB_REQUIRED) @@ -70,6 +71,25 @@ AC_SUBST(LIBGNOMEPRINT_REQUIRED) AC_SUBST(LIBGNOMEPRINTUI_REQUIRED) AC_SUBST(LIBGNOMECANVAS_REQUIRED) AC_SUBST(LIBGLADE_REQUIRED) +AC_SUBST(LIBEBOOK_REQUIRED) + + +dnl --------------------------------------------------------------------------- +dnl - Check for evolution data server +dnl --------------------------------------------------------------------------- +AC_ARG_WITH(libebook, + [AC_HELP_STRING([--without-libebook], + [build without Evolution Data Server support])]) +have_libebook=no +if test "x$with_libebook" != xno; then + PKG_CHECK_MODULES(LIBEBOOK, libebook-1.2 >= $LIBEBOOK_REQUIRED, + [have_libebook=yes], [have_libebook=no]) +fi + +if test "x$have_libebook" = "xyes"; then + AC_DEFINE(HAVE_LIBEBOOK,1,[Define to 1 for EDS support]) + OPTIONAL_MODULES="$OPTIONAL_MODULES libebook-1.2 >= $LIBEBOOK_REQUIRED" +fi dnl --------------------------------------------------------------------------- @@ -85,6 +105,7 @@ libgnomeprint-2.2 >= $LIBGNOMEPRINT_REQUIRED \ libgnomeprintui-2.2 >= $LIBGNOMEPRINTUI_REQUIRED \ libgnomecanvas-2.0 >= $LIBGNOMECANVAS_REQUIRED \ libglade-2.0 >= $LIBGLADE_REQUIRED \ +$OPTIONAL_MODULES \ ) AC_SUBST(GLABELS_CFLAGS) @@ -190,10 +211,11 @@ dnl --------------------------------------------------------------------------- echo " Configuration: - Package: ${PACKAGE}-${VERSION}: - Installation prefix ${prefix} - Source code location: ${srcdir} - Compiler: ${CC} + Package: ${PACKAGE}-${VERSION}: + Installation prefix ${prefix} + Source code location: ${srcdir} + Compiler: ${CC} + Evolution Data Server support: ${have_libebook} " diff --git a/glabels2/src/Makefile.am b/glabels2/src/Makefile.am index fb9d6e9d..fb4cf2f1 100644 --- a/glabels2/src/Makefile.am +++ b/glabels2/src/Makefile.am @@ -144,6 +144,10 @@ glabels_SOURCES = \ merge-init.h \ merge-text.c \ merge-text.h \ + merge-evolution.c \ + merge-evolution.h \ + merge-vcard.c \ + merge-vcard.h \ text-node.c \ text-node.h \ wdgt-print-copies.c \ @@ -210,6 +214,10 @@ glabels_batch_SOURCES = \ merge-init.h \ merge-text.c \ merge-text.h \ + merge-evolution.c \ + merge-evolution.h \ + merge-vcard.c \ + merge-vcard.h \ text-node.c \ text-node.h \ prefs.c \ diff --git a/glabels2/src/merge-evolution.c b/glabels2/src/merge-evolution.c new file mode 100644 index 00000000..77d73de3 --- /dev/null +++ b/glabels2/src/merge-evolution.c @@ -0,0 +1,489 @@ +/* + * (GLABELS) Label and Business Card Creation program for GNOME + * + * merge_evolution.c: evolution merge backend module + * + * Copyright (C) 2001 Jim Evins . + * and + * Copyright (C) 2005 Austin Henry + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include + +#ifdef HAVE_LIBEBOOK + + +#include "merge-evolution.h" +#include + +#include + +#include "debug.h" + +#define DEFAULT_QUERY "(exists \"full_name\")" + +/*===========================================*/ +/* Private types */ +/*===========================================*/ + +struct _glMergeEvolutionPrivate { + gchar *query; + EBook *book; + GList *contacts; + GList *error_list; /* list of error strings */ +}; + +enum { + LAST_SIGNAL +}; + +enum { + ARG_0, + ARG_QUERY, +}; + +/*===========================================*/ +/* Private globals */ +/*===========================================*/ + +static glMergeClass *parent_class = NULL; + + +/*===========================================*/ +/* Local function prototypes */ +/*===========================================*/ + +static void gl_merge_evolution_class_init (glMergeEvolutionClass *klass); +static void gl_merge_evolution_instance_init (glMergeEvolution *object); +static void gl_merge_evolution_finalize (GObject *object); + +static void gl_merge_evolution_set_property (GObject *object, + guint param_id, + const GValue *value, + GParamSpec *pspec); + +static void gl_merge_evolution_get_property (GObject *object, + guint param_id, + GValue *value, + GParamSpec *pspec); + +static GList *gl_merge_evolution_get_key_list (glMerge *merge); +static gchar *gl_merge_evolution_get_primary_key (glMerge *merge); +static void gl_merge_evolution_open (glMerge *merge); +static void gl_merge_evolution_close (glMerge *merge); +static glMergeRecord *gl_merge_evolution_get_record (glMerge *merge); +static void gl_merge_evolution_copy (glMerge *dst_merge, + glMerge *src_merge); + +/* utility function prototypes go here */ + +/*****************************************************************************/ +/* Boilerplate object stuff. */ +/*****************************************************************************/ +GType +gl_merge_evolution_get_type (void) +{ + static GType type = 0; + + if (!type) { + static const GTypeInfo info = { + sizeof (glMergeEvolutionClass), + NULL, + NULL, + (GClassInitFunc) gl_merge_evolution_class_init, + NULL, + NULL, + sizeof (glMergeEvolution), + 0, + (GInstanceInitFunc) gl_merge_evolution_instance_init, + NULL + }; + + type = g_type_register_static (GL_TYPE_MERGE, + "glMergeEvolution", &info, 0); + } + + return type; +} + +static void +gl_merge_evolution_class_init (glMergeEvolutionClass *klass) +{ + GObjectClass *object_class = (GObjectClass *) klass; + glMergeClass *merge_class = (glMergeClass *) klass; + + gl_debug (DEBUG_MERGE, "START"); + + parent_class = g_type_class_peek_parent (klass); + + object_class->set_property = gl_merge_evolution_set_property; + object_class->get_property = gl_merge_evolution_get_property; + + g_object_class_install_property + (object_class, + ARG_QUERY, + g_param_spec_string ("query", NULL, + "Query used to select records from the addressbook", + "(exists \"full_name\")", + (G_PARAM_READABLE | G_PARAM_WRITABLE))); + + object_class->finalize = gl_merge_evolution_finalize; + + merge_class->get_key_list = gl_merge_evolution_get_key_list; + merge_class->get_primary_key = gl_merge_evolution_get_primary_key; + merge_class->open = gl_merge_evolution_open; + merge_class->close = gl_merge_evolution_close; + merge_class->get_record = gl_merge_evolution_get_record; + merge_class->copy = gl_merge_evolution_copy; + + gl_debug (DEBUG_MERGE, "END"); +} + +static void +gl_merge_evolution_instance_init (glMergeEvolution *merge_evolution) +{ + gl_debug (DEBUG_MERGE, "START"); + + merge_evolution->private = g_new0 (glMergeEvolutionPrivate, 1); + merge_evolution->private->query = g_strdup(DEFAULT_QUERY); + + gl_debug (DEBUG_MERGE, "END"); +} + +static void +gl_merge_evolution_finalize (GObject *object) +{ + glMergeEvolution *merge_evolution; + + gl_debug (DEBUG_MERGE, "START"); + + g_return_if_fail (object && GL_IS_MERGE_EVOLUTION (object)); + + G_OBJECT_CLASS (parent_class)->finalize (object); + + merge_evolution = GL_MERGE_EVOLUTION (object); + g_free (merge_evolution->private->query); + g_free (merge_evolution->private); + + gl_debug (DEBUG_MERGE, "END"); +} + +/*--------------------------------------------------------------------------*/ +/* Set argument. */ +/*--------------------------------------------------------------------------*/ +static void +gl_merge_evolution_set_property (GObject *object, + guint param_id, + const GValue *value, + GParamSpec *pspec) +{ + glMergeEvolution *merge_evolution; + + merge_evolution = GL_MERGE_EVOLUTION (object); + + switch (param_id) { + + case ARG_QUERY: + g_free (merge_evolution->private->query); + merge_evolution->private->query = g_value_dup_string (value); + gl_debug (DEBUG_MERGE, "ARG \"query\" = \"%s\"", + merge_evolution->private->query); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec); + break; + + } + +} + +/*--------------------------------------------------------------------------*/ +/* Get argument. */ +/*--------------------------------------------------------------------------*/ +static void +gl_merge_evolution_get_property (GObject *object, + guint param_id, + GValue *value, + GParamSpec *pspec) +{ + glMergeEvolution *merge_evolution; + + merge_evolution = GL_MERGE_EVOLUTION (object); + + switch (param_id) { + + case ARG_QUERY: + g_value_set_string (value, merge_evolution->private->query); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec); + break; + + } + +} + +/*--------------------------------------------------------------------------*/ +/* Get key list. */ +/*--------------------------------------------------------------------------*/ +static GList * +gl_merge_evolution_get_key_list (glMerge *merge) +{ + glMergeEvolution *merge_evolution; + GList *key_list; + + gl_debug (DEBUG_MERGE, "BEGIN"); + + merge_evolution = GL_MERGE_EVOLUTION (merge); + + /* extremely simple approach until I can list the available keys from the + * server, and return them. */ + key_list = NULL; + key_list = g_list_append (key_list, g_strdup ("record_key")); + key_list = g_list_append (key_list, g_strdup ("full_name")); + key_list = g_list_append (key_list, g_strdup ("home_address")); + key_list = g_list_append (key_list, g_strdup ("work_address")); + + gl_debug (DEBUG_MERGE, "END"); + + return key_list; +} + +/*--------------------------------------------------------------------------*/ +/* Get "primary" key. */ +/*--------------------------------------------------------------------------*/ +static gchar * +gl_merge_evolution_get_primary_key (glMerge *merge) +{ + return g_strdup ("record_key"); +} + +/*--------------------------------------------------------------------------*/ +/* Open merge source. */ +/*--------------------------------------------------------------------------*/ +static void +gl_merge_evolution_open (glMerge *merge) +{ + glMergeEvolution *merge_evolution; + EBookQuery *query; + gboolean status; + GError *error; + GList **error_list; + + merge_evolution = GL_MERGE_EVOLUTION (merge); + error_list = &merge_evolution->private->error_list; + + query = e_book_query_from_string(merge_evolution->private->query); + if (!query) { + merge_evolution->private->error_list = + g_list_append(merge_evolution->private->error_list, + g_strdup("Couldn't construct query")); + g_error_free (error); + return; + } + + merge_evolution->private->book = e_book_new_system_addressbook(&error); + if (!merge_evolution->private->book) { + *error_list = g_list_append(*error_list, + g_strdup_printf("Couldn't open addressbook: %s", + error->message)); + e_book_query_unref(query); + g_error_free (error); + return; + } + + if (!e_book_open(merge_evolution->private->book, TRUE, &error)) { + *error_list = g_list_append(*error_list, + g_strdup_printf("Couldn't open addressbook: %s", + error->message)); + g_error_free (error); + e_book_query_unref(query); + g_object_unref(merge_evolution->private->book); + merge_evolution->private->book = NULL; + + return; + } + + status = e_book_get_contacts (merge_evolution->private->book, + query, + &merge_evolution->private->contacts, + &error); + if (status == FALSE) { + *error_list = g_list_append(*error_list, + g_strdup_printf("Couldn't get contacts: %s", + error->message)); + g_error_free (error); + e_book_query_unref(query); + g_object_unref(merge_evolution->private->book); + merge_evolution->private->book = NULL; + + return; + } + + e_book_query_unref(query); + return; + /* XXX I should probably sort the list by name (or the file-as element)*/ +} + +/*--------------------------------------------------------------------------*/ +/* Close merge source. */ +/*--------------------------------------------------------------------------*/ +static void +gl_merge_evolution_close (glMerge *merge) +{ + glMergeEvolution *merge_evolution; + GList *iter; + + merge_evolution = GL_MERGE_EVOLUTION (merge); + + /* unref all of the objects created in _open */ + g_object_unref(merge_evolution->private->book); + merge_evolution->private->book = NULL; + + for (iter = merge_evolution->private->contacts; + iter != NULL; + iter = g_list_next(iter)) + { + EContact *contact = E_CONTACT (iter->data); + + g_object_unref(contact); + } + g_list_free(merge_evolution->private->contacts); + merge_evolution->private->contacts = NULL; + + for (iter = merge_evolution->private->error_list; + iter != NULL; + iter = g_list_next(iter)) + { + g_free(iter->data); + } + merge_evolution->private->error_list = NULL; +} + +/*--------------------------------------------------------------------------*/ +/* Get next record from merge source, NULL if no records left (i.e EOF) */ +/*--------------------------------------------------------------------------*/ +static glMergeRecord * +gl_merge_evolution_get_record (glMerge *merge) +{ + glMergeEvolution *merge_evolution; + glMergeRecord *record; + glMergeField *field; + + GList *head; + EContact *contact; + + merge_evolution = GL_MERGE_EVOLUTION (merge); + + /* we're in an error state */ + if (merge_evolution->private->error_list) { + head = merge_evolution->private->error_list; + char *error_str = head->data; + + /* a yucky hack to make the errors show up in the record list */ + record = g_new0 (glMergeRecord, 1); + record->select_flag = TRUE; + + field = g_new0 (glMergeField, 1); + field->key = g_strdup ("full_name"); + field->value = g_strdup (error_str); + + record->field_list = g_list_append (record->field_list, field); + + /* do a destructive read */ + g_free (error_str); + merge_evolution->private->error_list = + g_list_remove_link (merge_evolution->private->error_list, head); + g_list_free_1 (head); + + return record; + } + + head = merge_evolution->private->contacts; + if (head == NULL) { + return NULL; /* past the last record */ + } + contact = E_CONTACT(head->data); + + record = g_new0 (glMergeRecord, 1); + record->select_flag = TRUE; + + /* Take the interesting fields one by one from the contact, and put them + * into the glMergeRecord structure. When done, free up the resources for + * that contact */ + + /* get the record key */ + field = g_new0 (glMergeField, 1); + field->key = g_strdup ("record_key"); + field->value = g_strdup (e_contact_get(contact, E_CONTACT_FILE_AS)); + + record->field_list = g_list_append (record->field_list, field); + + /* get the full name */ + field = g_new0 (glMergeField, 1); + field->key = g_strdup ("full_name"); + field->value = g_strdup (e_contact_get(contact, E_CONTACT_FULL_NAME)); + + record->field_list = g_list_append (record->field_list, field); + + /* get the home address */ + field = g_new0 (glMergeField, 1); + field->key = g_strdup ("home_address"); + field->value = g_strdup (e_contact_get(contact, E_CONTACT_ADDRESS_LABEL_HOME)); + + record->field_list = g_list_append (record->field_list, field); + + /* get the work address */ + field = g_new0 (glMergeField, 1); + field->key = g_strdup ("work_address"); + field->value = g_strdup (e_contact_get(contact, E_CONTACT_ADDRESS_LABEL_WORK)); + + record->field_list = g_list_append (record->field_list, field); + + /* do a destructive read */ + g_object_unref (contact); + merge_evolution->private->contacts = + g_list_remove_link (merge_evolution->private->contacts, head); + g_list_free_1 (head); + + return record; +} + +/*---------------------------------------------------------------------------*/ +/* Copy merge_evolution specific fields. */ +/*---------------------------------------------------------------------------*/ +static void +gl_merge_evolution_copy (glMerge *dst_merge, + glMerge *src_merge) +{ + glMergeEvolution *dst_merge_evolution; + glMergeEvolution *src_merge_evolution; + + dst_merge_evolution = GL_MERGE_EVOLUTION (dst_merge); + src_merge_evolution = GL_MERGE_EVOLUTION (src_merge); + + dst_merge_evolution->private->query = g_strdup(src_merge_evolution->private->query); + /* I don't know that there's a good way to do a deep copy of the various + * libebook structures/objects, so I'm just going to leave them out. They + * are all regenerated on gl_merge_evolution_open, anyway */ +} + + + +#endif /* HAVE_LIBEBOOK */ diff --git a/glabels2/src/merge-evolution.h b/glabels2/src/merge-evolution.h new file mode 100644 index 00000000..32c8a9c0 --- /dev/null +++ b/glabels2/src/merge-evolution.h @@ -0,0 +1,68 @@ +/* + * (GLABELS) Label and Business Card Creation program for GNOME + * + * merge_evolution.h: evolution merge backend module header file + * + * Copyright (C) 2002 Jim Evins . + * and + * Copyright (C) 2005 Austin Henry + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +#ifndef __MERGE_EVOLUTION_H__ +#define __MERGE_EVOLUTION_H__ + +#include "merge.h" + +G_BEGIN_DECLS + +/* The following object arguments are available: + * + * name type description + * -------------------------------------------------------------------------------- + * query gchar* The query used to select records + * + */ + +#define GL_TYPE_MERGE_EVOLUTION (gl_merge_evolution_get_type ()) +#define GL_MERGE_EVOLUTION(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GL_TYPE_MERGE_EVOLUTION, glMergeEvolution)) +#define GL_MERGE_EVOLUTION_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GL_TYPE_MERGE_EVOLUTION, glMergeEvolutionClass)) +#define GL_IS_MERGE_EVOLUTION(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GL_TYPE_MERGE_EVOLUTION)) +#define GL_IS_MERGE_EVOLUTION_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GL_TYPE_MERGE_EVOLUTION)) +#define GL_MERGE_EVOLUTION_GET_CLASS(object) (G_TYPE_INSTANCE_GET_CLASS ((object), GL_TYPE_MERGE_EVOLUTION, glMergeEvolutionClass)) + + +typedef struct _glMergeEvolution glMergeEvolution; +typedef struct _glMergeEvolutionClass glMergeEvolutionClass; + +typedef struct _glMergeEvolutionPrivate glMergeEvolutionPrivate; + + +struct _glMergeEvolution { + glMerge object; + + glMergeEvolutionPrivate *private; +}; + +struct _glMergeEvolutionClass { + glMergeClass parent_class; +}; + + +GType gl_merge_evolution_get_type (void) G_GNUC_CONST; + +G_END_DECLS + +#endif /* __MERGE_EVOLUTION_H__ */ diff --git a/glabels2/src/merge-init.c b/glabels2/src/merge-init.c index cb6f2632..d44d3c07 100644 --- a/glabels2/src/merge-init.c +++ b/glabels2/src/merge-init.c @@ -25,6 +25,10 @@ #include "merge-init.h" #include "merge-text.h" +#ifdef HAVE_LIBEBOOK +#include "merge-evolution.h" +#include "merge-vcard.h" +#endif /* HAVE_LIBEBOOK */ #include "debug.h" @@ -69,4 +73,20 @@ gl_merge_init (void) "delim", '\t', NULL); +#ifdef HAVE_LIBEBOOK + + gl_merge_register_backend (GL_TYPE_MERGE_EVOLUTION, + "ebook/eds", + _("Data from default Evolution Addressbook"), + GL_MERGE_SRC_IS_FIXED, + NULL); + + gl_merge_register_backend (GL_TYPE_MERGE_VCARD, + "ebook/vcard", + _("Data from a file containing VCards"), + GL_MERGE_SRC_IS_FILE, + NULL); + +#endif /* HAVE_LIBEBOOK */ + } diff --git a/glabels2/src/merge-properties-dialog.c b/glabels2/src/merge-properties-dialog.c index 10efabd4..7f4c34fe 100644 --- a/glabels2/src/merge-properties-dialog.c +++ b/glabels2/src/merge-properties-dialog.c @@ -445,6 +445,13 @@ type_changed_cb (GtkWidget *widget, "selection-changed", G_CALLBACK (src_changed_cb), dialog); break; + case GL_MERGE_SRC_IS_FIXED: + dialog->priv->src_entry = gtk_label_new (_("Fixed")); + gtk_misc_set_alignment (GTK_MISC (dialog->priv->src_entry), 0.0, 0.5); + + gl_debug (DEBUG_MERGE, "Setting src = \"%s\"", dialog->priv->saved_src); + gl_merge_set_src (dialog->priv->merge, "Fixed"); + break; default: dialog->priv->src_entry = gtk_label_new (_("N/A")); gtk_misc_set_alignment (GTK_MISC (dialog->priv->src_entry), 0.0, 0.5); diff --git a/glabels2/src/merge-vcard.c b/glabels2/src/merge-vcard.c new file mode 100644 index 00000000..65834dd5 --- /dev/null +++ b/glabels2/src/merge-vcard.c @@ -0,0 +1,403 @@ +/* + * (GLABELS) Label and Business Card Creation program for GNOME + * + * merge_vcard.c: vcard merge backend module + * + * Copyright (C) 2001 Jim Evins . + * and + * Copyright (C) 2005 Austin Henry + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include + +#ifdef HAVE_LIBEBOOK + + +#include "merge-vcard.h" +#include + +#include +#include +#include + +#include "debug.h" + +/*===========================================*/ +/* Private types */ +/*===========================================*/ + +struct _glMergeVCardPrivate { + FILE *fp; +}; + +enum { + LAST_SIGNAL +}; + +enum { + ARG_0, +}; + +/*===========================================*/ +/* Private globals */ +/*===========================================*/ + +static glMergeClass *parent_class = NULL; + + +/*===========================================*/ +/* Local function prototypes */ +/*===========================================*/ + +static void gl_merge_vcard_class_init (glMergeVCardClass *klass); +static void gl_merge_vcard_instance_init (glMergeVCard *object); +static void gl_merge_vcard_finalize (GObject *object); + +static void gl_merge_vcard_set_property (GObject *object, + guint param_id, + const GValue *value, + GParamSpec *pspec); + +static void gl_merge_vcard_get_property (GObject *object, + guint param_id, + GValue *value, + GParamSpec *pspec); + +static GList *gl_merge_vcard_get_key_list (glMerge *merge); +static gchar *gl_merge_vcard_get_primary_key (glMerge *merge); +static void gl_merge_vcard_open (glMerge *merge); +static void gl_merge_vcard_close (glMerge *merge); +static glMergeRecord *gl_merge_vcard_get_record (glMerge *merge); +static void gl_merge_vcard_copy (glMerge *dst_merge, + glMerge *src_merge); +static char * parse_next_vcard (FILE *fp); + +/* utility function prototypes go here */ + +/*****************************************************************************/ +/* Boilerplate object stuff. */ +/*****************************************************************************/ +GType +gl_merge_vcard_get_type (void) +{ + static GType type = 0; + + if (!type) { + static const GTypeInfo info = { + sizeof (glMergeVCardClass), + NULL, + NULL, + (GClassInitFunc) gl_merge_vcard_class_init, + NULL, + NULL, + sizeof (glMergeVCard), + 0, + (GInstanceInitFunc) gl_merge_vcard_instance_init, + NULL + }; + + type = g_type_register_static (GL_TYPE_MERGE, + "glMergeVCard", &info, 0); + } + + return type; +} + +static void +gl_merge_vcard_class_init (glMergeVCardClass *klass) +{ + GObjectClass *object_class = (GObjectClass *) klass; + glMergeClass *merge_class = (glMergeClass *) klass; + + gl_debug (DEBUG_MERGE, "START"); + + parent_class = g_type_class_peek_parent (klass); + + object_class->set_property = gl_merge_vcard_set_property; + object_class->get_property = gl_merge_vcard_get_property; + + object_class->finalize = gl_merge_vcard_finalize; + + merge_class->get_key_list = gl_merge_vcard_get_key_list; + merge_class->get_primary_key = gl_merge_vcard_get_primary_key; + merge_class->open = gl_merge_vcard_open; + merge_class->close = gl_merge_vcard_close; + merge_class->get_record = gl_merge_vcard_get_record; + merge_class->copy = gl_merge_vcard_copy; + + gl_debug (DEBUG_MERGE, "END"); +} + +static void +gl_merge_vcard_instance_init (glMergeVCard *merge_vcard) +{ + gl_debug (DEBUG_MERGE, "START"); + + merge_vcard->private = g_new0 (glMergeVCardPrivate, 1); + + gl_debug (DEBUG_MERGE, "END"); +} + +static void +gl_merge_vcard_finalize (GObject *object) +{ + glMergeVCard *merge_vcard; + + gl_debug (DEBUG_MERGE, "START"); + + g_return_if_fail (object && GL_IS_MERGE_VCARD (object)); + + G_OBJECT_CLASS (parent_class)->finalize (object); + + merge_vcard = GL_MERGE_VCARD (object); + g_free (merge_vcard->private); + + gl_debug (DEBUG_MERGE, "END"); +} + +/*--------------------------------------------------------------------------*/ +/* Set argument. */ +/*--------------------------------------------------------------------------*/ +static void +gl_merge_vcard_set_property (GObject *object, + guint param_id, + const GValue *value, + GParamSpec *pspec) +{ + glMergeVCard *merge_vcard; + + merge_vcard = GL_MERGE_VCARD (object); + + switch (param_id) { + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec); + break; + } +} + +/*--------------------------------------------------------------------------*/ +/* Get argument. */ +/*--------------------------------------------------------------------------*/ +static void +gl_merge_vcard_get_property (GObject *object, + guint param_id, + GValue *value, + GParamSpec *pspec) +{ + glMergeVCard *merge_vcard; + + merge_vcard = GL_MERGE_VCARD (object); + + switch (param_id) { + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec); + break; + } + +} + +/* TODO */ +/*--------------------------------------------------------------------------*/ +/* Get key list. */ +/*--------------------------------------------------------------------------*/ +static GList * +gl_merge_vcard_get_key_list (glMerge *merge) +{ + glMergeVCard *merge_vcard; + GList *key_list; + + gl_debug (DEBUG_MERGE, "BEGIN"); + + merge_vcard = GL_MERGE_VCARD (merge); + + /* extremely simple approach until I can list the available keys from the + * server, and return them. */ + key_list = NULL; + key_list = g_list_append (key_list, g_strdup ("full_name")); + key_list = g_list_append (key_list, g_strdup ("home_address")); + key_list = g_list_append (key_list, g_strdup ("work_address")); + + gl_debug (DEBUG_MERGE, "END"); + + return key_list; +} + +/* TODO? */ +/*--------------------------------------------------------------------------*/ +/* Get "primary" key. */ +/*--------------------------------------------------------------------------*/ +static gchar * +gl_merge_vcard_get_primary_key (glMerge *merge) +{ + /* For now, let's always assume the full name is the primary key. */ + return g_strdup ("full_name"); +} + +/*--------------------------------------------------------------------------*/ +/* Open merge source. */ +/*--------------------------------------------------------------------------*/ +static void +gl_merge_vcard_open (glMerge *merge) +{ + glMergeVCard *merge_vcard; + gchar *src; + + merge_vcard = GL_MERGE_VCARD (merge); + + src = gl_merge_get_src (merge); + + if (src != NULL) { + merge_vcard->private->fp = fopen (src, "r"); + } + + g_free (src); + + return; +} + +/*--------------------------------------------------------------------------*/ +/* Close merge source. */ +/*--------------------------------------------------------------------------*/ +static void +gl_merge_vcard_close (glMerge *merge) +{ + glMergeVCard *merge_vcard; + + merge_vcard = GL_MERGE_VCARD (merge); + + if (merge_vcard->private->fp != NULL) { + fclose (merge_vcard->private->fp); + merge_vcard->private->fp = NULL; + } +} + +/*--------------------------------------------------------------------------*/ +/* Get next record from merge source, NULL if no records left (i.e EOF) */ +/*--------------------------------------------------------------------------*/ +static glMergeRecord * +gl_merge_vcard_get_record (glMerge *merge) +{ + glMergeVCard *merge_vcard; + glMergeRecord *record; + glMergeField *field; + + char *vcard; + EContact *contact; + + merge_vcard = GL_MERGE_VCARD (merge); + + vcard = parse_next_vcard(merge_vcard->private->fp); + if (vcard[0] == '\0') { + return NULL; /* EOF */ + } + contact = e_contact_new_from_vcard(vcard); + if (contact == NULL) { + return NULL; /* invalid vcard */ + } + + record = g_new0 (glMergeRecord, 1); + record->select_flag = TRUE; + + /* Take the interesting fields one by one from the contact, and put them + * into the glMergeRecord structure. When done, free up the resources for + * that contact */ + + /* get the full name */ + field = g_new0 (glMergeField, 1); + field->key = g_strdup ("full_name"); + field->value = g_strdup (e_contact_get(contact, E_CONTACT_FULL_NAME)); + + record->field_list = g_list_append (record->field_list, field); + + /* get the home address */ + field = g_new0 (glMergeField, 1); + field->key = g_strdup ("home_address"); + field->value = g_strdup (e_contact_get(contact, E_CONTACT_ADDRESS_LABEL_HOME)); + + record->field_list = g_list_append (record->field_list, field); + + /* get the work address */ + field = g_new0 (glMergeField, 1); + field->key = g_strdup ("work_address"); + field->value = g_strdup (e_contact_get(contact, E_CONTACT_ADDRESS_LABEL_WORK)); + + record->field_list = g_list_append (record->field_list, field); + + /* free the contact */ + g_object_unref (contact); + g_free(vcard); + + return record; +} + +/*---------------------------------------------------------------------------*/ +/* Copy merge_vcard specific fields. */ +/*---------------------------------------------------------------------------*/ +static void +gl_merge_vcard_copy (glMerge *dst_merge, + glMerge *src_merge) +{ + glMergeVCard *dst_merge_vcard; + glMergeVCard *src_merge_vcard; + + dst_merge_vcard = GL_MERGE_VCARD (dst_merge); + src_merge_vcard = GL_MERGE_VCARD (src_merge); +} + +/*---------------------------------------------------------------------------*/ +/* PRIVATE: pull out a full VCard from the open file */ +/* Arguments: */ +/* fp - an open stream to parse in put from */ +/* Returns: */ +/* a pointer to the buffer containing the vcard, the empty string on */ +/* end-of-file or error, this buffer needs to be free by the caller */ +/*---------------------------------------------------------------------------*/ +static char * +parse_next_vcard (FILE *fp) +{ + gboolean found_begin = FALSE, found_end = FALSE; + char *vcard; + char line[512]; + int size = 2048, cursize = 0; + + vcard = g_malloc0(size); + + while (fgets(line, sizeof(line), fp) && found_end == FALSE) { + if (found_begin == TRUE) { + if (g_str_has_prefix(line, "END:VCARD")) { found_end = TRUE; } + } else { + if (g_str_has_prefix(line, "BEGIN:VCARD")) { found_begin = TRUE; } + else { continue; }/* skip lines not in a vcard */ + } + + /* if the buffer passed us isn't big enough, reallocate it */ + cursize += strlen(line); + if (cursize >= size) { + size *= 2; + vcard = (char *)g_realloc(vcard, size); /* aborts program on error */ + } + + /* add the line (or portion thereof) to the vcard */ + strncat(vcard, line, size); + } + + return vcard; +} + + + +#endif /* HAVE_LIBEBOOK */ diff --git a/glabels2/src/merge-vcard.h b/glabels2/src/merge-vcard.h new file mode 100644 index 00000000..b6712e3c --- /dev/null +++ b/glabels2/src/merge-vcard.h @@ -0,0 +1,68 @@ +/* + * (GLABELS) Label and Business Card Creation program for GNOME + * + * merge_vcard.h: vcard merge backend module header file + * + * Copyright (C) 2002 Jim Evins . + * and + * Copyright (C) 2005 Austin Henry + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +#ifndef __MERGE_VCARD_H__ +#define __MERGE_VCARD_H__ + +#include "merge.h" + +G_BEGIN_DECLS + +/* The following object arguments are available: + * + * name type description + * -------------------------------------------------------------------------------- + * + */ + +#define GL_TYPE_MERGE_VCARD (gl_merge_vcard_get_type ()) +#define GL_MERGE_VCARD(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GL_TYPE_MERGE_VCARD, glMergeVCard)) +#define GL_MERGE_VCARD_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GL_TYPE_MERGE_VCARD, glMergeVCardClass)) +#define GL_IS_MERGE_VCARD(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GL_TYPE_MERGE_VCARD)) +#define GL_IS_MERGE_VCARD_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GL_TYPE_MERGE_VCARD)) +#define GL_MERGE_VCARD_GET_CLASS(object) (G_TYPE_INSTANCE_GET_CLASS ((object), GL_TYPE_MERGE_VCARD, glMergeVCardClass)) + + +typedef struct _glMergeVCard glMergeVCard; +typedef struct _glMergeVCardClass glMergeVCardClass; + +typedef struct _glMergeVCardPrivate glMergeVCardPrivate; + + +struct _glMergeVCard { + glMerge object; + + glMergeVCardPrivate *private; +}; + +struct _glMergeVCardClass { + glMergeClass parent_class; +}; + + +GType gl_merge_vcard_get_type (void) G_GNUC_CONST; + +G_END_DECLS + + +#endif /* __MERGE_VCARD_H__ */ diff --git a/glabels2/src/ui-commands.c b/glabels2/src/ui-commands.c index 6a9802ed..ac93d95c 100644 --- a/glabels2/src/ui-commands.c +++ b/glabels2/src/ui-commands.c @@ -1090,12 +1090,13 @@ gl_ui_cmd_help_about (GtkAction *action, GdkPixbuf *pixbuf = NULL; const gchar *authors[] = { - "Jim Evins ", + "Jim Evins", " ", _("Glabels includes contributions from:"), - "Frederic Ruaudel ", - "Wayne Schuller ", - "Emmanuel Pacaud ", + "Frederic Ruaudel", + "Wayne Schuller", + "Emmanuel Pacaud", + "Austin Henry", " ", _("See the file AUTHORS for additional credits,"), _("or visit http://glabels.sourceforge.net/"), @@ -1103,8 +1104,8 @@ gl_ui_cmd_help_about (GtkAction *action, }; const gchar *artists[] = { - "Nestor Di ", - "Jim Evins ", + "Nestor Di", + "Jim Evins", NULL };