From ef7690c3845e3c1cebcf3caba7f7667a10e7123d Mon Sep 17 00:00:00 2001 From: Milan Crha Date: Tue, 18 May 2010 22:47:29 +0200 Subject: Bug #499320 - Preview before import from command line --- addressbook/importers/Makefile.am | 2 + .../importers/evolution-addressbook-importers.h | 3 + addressbook/importers/evolution-csv-importer.c | 81 ++++- addressbook/importers/evolution-ldif-importer.c | 63 +++- addressbook/importers/evolution-vcard-importer.c | 345 +++++++++++++++++++++ 5 files changed, 488 insertions(+), 6 deletions(-) (limited to 'addressbook') diff --git a/addressbook/importers/Makefile.am b/addressbook/importers/Makefile.am index 7ccc4c7545..742f46a334 100644 --- a/addressbook/importers/Makefile.am +++ b/addressbook/importers/Makefile.am @@ -7,6 +7,7 @@ libevolution_addressbook_importers_la_CPPFLAGS = \ -DG_LOG_DOMAIN=\"Evolution-Importer\" \ -I$(top_srcdir) \ -I$(top_srcdir)/addressbook \ + -I$(top_srcdir)/widgets \ -I$(top_builddir)/addressbook \ $(EVOLUTION_ADDRESSBOOK_CFLAGS) @@ -21,6 +22,7 @@ libevolution_addressbook_importers_la_LDFLAGS = $(NO_UNDEFINED) libevolution_addressbook_importers_la_LIBADD = \ $(top_builddir)/e-util/libeutil.la \ $(top_builddir)/addressbook/util/libeabutil.la \ + $(top_builddir)/widgets/misc/libemiscwidgets.la \ $(IMPORTERS_LIBS) -include $(top_srcdir)/git.mk diff --git a/addressbook/importers/evolution-addressbook-importers.h b/addressbook/importers/evolution-addressbook-importers.h index 747fe4281d..adaa62931a 100644 --- a/addressbook/importers/evolution-addressbook-importers.h +++ b/addressbook/importers/evolution-addressbook-importers.h @@ -23,3 +23,6 @@ struct _EImportImporter *evolution_vcard_importer_peek(void); struct _EImportImporter *evolution_csv_outlook_importer_peek(void); struct _EImportImporter *evolution_csv_mozilla_importer_peek(void); struct _EImportImporter *evolution_csv_evolution_importer_peek(void); + +/* private utility function for importers only */ +struct _GtkWidget *evolution_contact_importer_get_preview_widget (const GList *contacts); diff --git a/addressbook/importers/evolution-csv-importer.c b/addressbook/importers/evolution-csv-importer.c index 6a12d7075a..9ad939dea9 100644 --- a/addressbook/importers/evolution-csv-importer.c +++ b/addressbook/importers/evolution-csv-importer.c @@ -762,17 +762,26 @@ csv_import (EImport *ei, EImportTarget *target, EImportImporter *im) { CSVImporter *gci; EBook *book; + gchar *filename; FILE *file; EImportTargetURI *s = (EImportTargetURI *) target; + filename = g_filename_from_uri (s->uri_src, NULL, NULL); + if (filename == NULL) { + g_message (G_STRLOC ": Couldn't get filename from URI '%s'", s->uri_src); + return; + } + book = e_book_new(g_datalist_get_data(&target->data, "csv-source"), NULL); if (book == NULL) { g_message("Couldn't Create EBook"); e_import_complete(ei, target); + g_free (filename); return; } - file = g_fopen (g_filename_from_uri(s->uri_src, NULL, NULL), "r"); + file = g_fopen (filename, "r"); + g_free (filename); if (file == NULL) { g_message("Can't open .csv file"); e_import_complete(ei, target); @@ -825,6 +834,73 @@ csv_cancel(EImport *ei, EImportTarget *target, EImportImporter *im) { gci->state = 1; } +static GtkWidget * +csv_get_preview (EImport *ei, EImportTarget *target, EImportImporter *im) +{ + GtkWidget *preview; + GList *contacts = NULL; + EContact *contact; + EImportTargetURI *s = (EImportTargetURI *)target; + gchar *filename; + FILE *file; + CSVImporter *gci; + + filename = g_filename_from_uri (s->uri_src, NULL, NULL); + if (filename == NULL) { + g_message (G_STRLOC ": Couldn't get filename from URI '%s'", s->uri_src); + return NULL; + } + + file = g_fopen (filename, "r"); + g_free (filename); + if (file == NULL) { + g_message (G_STRLOC ": Can't open .csv file"); + return NULL; + } + + gci = g_malloc0 (sizeof (*gci)); + gci->file = file; + gci->count = 0; + fseek(file, 0, SEEK_END); + gci->size = ftell (file); + fseek (file, 0, SEEK_SET); + + while (contact = getNextCSVEntry (gci, gci->file), contact != NULL) { + contacts = g_list_prepend (contacts, contact); + } + + contacts = g_list_reverse (contacts); + preview = evolution_contact_importer_get_preview_widget (contacts); + + g_list_foreach (contacts, (GFunc) g_object_unref, NULL); + g_list_free (contacts); + fclose (file); + g_free (gci); + + return preview; +} + +static GtkWidget * +outlook_csv_get_preview (EImport *ei, EImportTarget *target, EImportImporter *im) +{ + importer = OUTLOOK_IMPORTER; + return csv_get_preview (ei, target, im); +} + +static GtkWidget * +mozilla_csv_get_preview (EImport *ei, EImportTarget *target, EImportImporter *im) +{ + importer = MOZILLA_IMPORTER; + return csv_get_preview (ei, target, im); +} + +static GtkWidget * +evolution_csv_get_preview (EImport *ei, EImportTarget *target, EImportImporter *im) +{ + importer = EVOLUTION_IMPORTER; + return csv_get_preview (ei, target, im); +} + static EImportImporter csv_outlook_importer = { E_IMPORT_TARGET_URI, 0, @@ -832,6 +908,7 @@ static EImportImporter csv_outlook_importer = { csv_getwidget, outlook_csv_import, csv_cancel, + outlook_csv_get_preview, }; static EImportImporter csv_mozilla_importer = { @@ -841,6 +918,7 @@ static EImportImporter csv_mozilla_importer = { csv_getwidget, mozilla_csv_import, csv_cancel, + mozilla_csv_get_preview, }; static EImportImporter csv_evolution_importer = { @@ -850,6 +928,7 @@ static EImportImporter csv_evolution_importer = { csv_getwidget, evolution_csv_import, csv_cancel, + evolution_csv_get_preview, }; EImportImporter * diff --git a/addressbook/importers/evolution-ldif-importer.c b/addressbook/importers/evolution-ldif-importer.c index 41dda05a40..52ce90e212 100644 --- a/addressbook/importers/evolution-ldif-importer.c +++ b/addressbook/importers/evolution-ldif-importer.c @@ -221,7 +221,7 @@ populate_contact_address (EContactAddress *address, gchar *attr, gchar *value) } static gboolean -parseLine (LDIFImporter *gci, EContact *contact, +parseLine (GHashTable *dn_contact_hash, EContact *contact, EContactAddress *work_address, EContactAddress *home_address, gchar **buf) { @@ -307,7 +307,7 @@ parseLine (LDIFImporter *gci, EContact *contact, if (!field_handled) { if (!g_ascii_strcasecmp (ptr, "dn")) g_hash_table_insert ( - gci->dn_contact_hash, + dn_contact_hash, g_strdup (ldif_value->str), contact); else if (!g_ascii_strcasecmp (ptr, "objectclass") && !g_ascii_strcasecmp (ldif_value->str, "groupofnames")) { @@ -342,7 +342,7 @@ parseLine (LDIFImporter *gci, EContact *contact, } static EContact * -getNextLDIFEntry(LDIFImporter *gci, FILE *f ) +getNextLDIFEntry(GHashTable *dn_contact_hash, FILE *f ) { EContact *contact; EContactAddress *work_address, *home_address; @@ -372,7 +372,7 @@ getNextLDIFEntry(LDIFImporter *gci, FILE *f ) buf = str->str; while (buf) { - if (!parseLine (gci, contact, work_address, home_address, &buf)) { + if (!parseLine (dn_contact_hash, contact, work_address, home_address, &buf)) { /* parsing error */ g_string_free (str, TRUE); e_contact_address_free (work_address); @@ -480,7 +480,7 @@ ldif_import_contacts(gpointer d) ones till the end */ if (gci->state == 0) { - while (count < 50 && (contact = getNextLDIFEntry(gci, gci->file))) { + while (count < 50 && (contact = getNextLDIFEntry(gci->dn_contact_hash, gci->file))) { if (e_contact_get (contact, E_CONTACT_IS_LIST)) { gci->list_contacts = g_slist_prepend(gci->list_contacts, contact); } else { @@ -674,6 +674,58 @@ ldif_cancel(EImport *ei, EImportTarget *target, EImportImporter *im) gci->state = 2; } +static GtkWidget * +ldif_get_preview (EImport *ei, EImportTarget *target, EImportImporter *im) +{ + GtkWidget *preview; + GList *contacts = NULL; + EContact *contact; + EImportTargetURI *s = (EImportTargetURI *)target; + gchar *filename; + GHashTable *dn_contact_hash; + FILE *file; + + filename = g_filename_from_uri (s->uri_src, NULL, NULL); + if (filename == NULL) { + g_message (G_STRLOC ": Couldn't get filename from URI '%s'", s->uri_src); + return NULL; + } + + file = g_fopen(filename, "r"); + g_free (filename); + + if (file == NULL) { + g_message (G_STRLOC ": Can't open .ldif file"); + return NULL; + } + + dn_contact_hash = g_hash_table_new_full ( + g_str_hash, g_str_equal, + (GDestroyNotify) g_free, + (GDestroyNotify) NULL); + + while (contact = getNextLDIFEntry (dn_contact_hash, file), contact != NULL) { + if (!e_contact_get (contact, E_CONTACT_IS_LIST)) { + add_to_notes(contact, E_CONTACT_OFFICE); + add_to_notes(contact, E_CONTACT_SPOUSE); + add_to_notes(contact, E_CONTACT_BLOG_URL); + } + + contacts = g_list_prepend (contacts, contact); + } + + g_hash_table_destroy (dn_contact_hash); + + contacts = g_list_reverse (contacts); + preview = evolution_contact_importer_get_preview_widget (contacts); + + g_list_foreach (contacts, (GFunc) g_object_unref, NULL); + g_list_free (contacts); + fclose (file); + + return preview; +} + static EImportImporter ldif_importer = { E_IMPORT_TARGET_URI, 0, @@ -681,6 +733,7 @@ static EImportImporter ldif_importer = { ldif_getwidget, ldif_import, ldif_cancel, + ldif_get_preview, }; EImportImporter * diff --git a/addressbook/importers/evolution-vcard-importer.c b/addressbook/importers/evolution-vcard-importer.c index 080ef940f2..49e7bef70b 100644 --- a/addressbook/importers/evolution-vcard-importer.c +++ b/addressbook/importers/evolution-vcard-importer.c @@ -42,6 +42,8 @@ #include #include "e-util/e-import.h" +#include "e-util/e-datetime-format.h" +#include "misc/e-web-view-preview.h" #include "evolution-addressbook-importers.h" @@ -550,6 +552,61 @@ vcard_cancel(EImport *ei, EImportTarget *target, EImportImporter *im) gci->state = 1; } +static GtkWidget * +vcard_get_preview (EImport *ei, EImportTarget *target, EImportImporter *im) +{ + GtkWidget *preview; + GList *contacts; + gchar *contents; + VCardEncoding encoding; + EImportTargetURI *s = (EImportTargetURI *)target; + gchar *filename; + + filename = g_filename_from_uri (s->uri_src, NULL, NULL); + if (filename == NULL) { + g_message (G_STRLOC ": Couldn't get filename from URI '%s'", s->uri_src); + return NULL; + } + + encoding = guess_vcard_encoding (filename); + if (encoding == VCARD_ENCODING_NONE) { + g_free (filename); + return NULL; + } + + if (!g_file_get_contents (filename, &contents, NULL, NULL)) { + g_message (G_STRLOC ": Couldn't read file."); + g_free (filename); + return NULL; + } + + g_free (filename); + + if (encoding == VCARD_ENCODING_UTF16) { + gchar *tmp; + + gunichar2 *contents_utf16 = (gunichar2 *) contents; + tmp = utf16_to_utf8 (contents_utf16); + g_free (contents); + contents = tmp; + } else if (encoding == VCARD_ENCODING_LOCALE) { + gchar *tmp; + tmp = g_locale_to_utf8 (contents, -1, NULL, NULL, NULL); + g_free (contents); + contents = tmp; + } + + contacts = eab_contact_list_from_string (contents); + g_free (contents); + + preview = evolution_contact_importer_get_preview_widget (contacts); + + g_list_foreach (contacts, (GFunc) g_object_unref, NULL); + g_list_free (contacts); + + return preview; +} + static EImportImporter vcard_importer = { E_IMPORT_TARGET_URI, 0, @@ -557,6 +614,7 @@ static EImportImporter vcard_importer = { vcard_getwidget, vcard_import, vcard_cancel, + vcard_get_preview, }; EImportImporter * @@ -567,3 +625,290 @@ evolution_vcard_importer_peek(void) return &vcard_importer; } + +/* utility functions shared between all contact importers */ +static void +preview_contact (EWebViewPreview *preview, EContact *contact) +{ + gint idx; + gboolean had_value = FALSE; + + const gint fields[] = { + E_CONTACT_FILE_AS, + E_CONTACT_CATEGORIES, + + E_CONTACT_IS_LIST, + E_CONTACT_LIST_SHOW_ADDRESSES, + E_CONTACT_WANTS_HTML, + + E_CONTACT_FULL_NAME, + E_CONTACT_GIVEN_NAME, + E_CONTACT_FAMILY_NAME, + E_CONTACT_NICKNAME, + E_CONTACT_SPOUSE, + E_CONTACT_BIRTH_DATE, + E_CONTACT_ANNIVERSARY, + E_CONTACT_MAILER, + E_CONTACT_EMAIL, + + -1, + + E_CONTACT_ORG, + E_CONTACT_ORG_UNIT, + E_CONTACT_OFFICE, + E_CONTACT_TITLE, + E_CONTACT_ROLE, + E_CONTACT_MANAGER, + E_CONTACT_ASSISTANT, + + -1, + + E_CONTACT_PHONE_ASSISTANT, + E_CONTACT_PHONE_BUSINESS, + E_CONTACT_PHONE_BUSINESS_2, + E_CONTACT_PHONE_BUSINESS_FAX, + E_CONTACT_PHONE_CALLBACK, + E_CONTACT_PHONE_CAR, + E_CONTACT_PHONE_COMPANY, + E_CONTACT_PHONE_HOME, + E_CONTACT_PHONE_HOME_2, + E_CONTACT_PHONE_HOME_FAX, + E_CONTACT_PHONE_ISDN, + E_CONTACT_PHONE_MOBILE, + E_CONTACT_PHONE_OTHER, + E_CONTACT_PHONE_OTHER_FAX, + E_CONTACT_PHONE_PAGER, + E_CONTACT_PHONE_PRIMARY, + E_CONTACT_PHONE_RADIO, + E_CONTACT_PHONE_TELEX, + E_CONTACT_PHONE_TTYTDD, + + -1, + + E_CONTACT_ADDRESS_HOME, + E_CONTACT_ADDRESS_WORK, + E_CONTACT_ADDRESS_OTHER, + + -1, + + E_CONTACT_HOMEPAGE_URL, + E_CONTACT_BLOG_URL, + E_CONTACT_CALENDAR_URI, + E_CONTACT_FREEBUSY_URL, + E_CONTACT_ICS_CALENDAR, + E_CONTACT_VIDEO_URL, + + -1, + + E_CONTACT_IM_AIM, + E_CONTACT_IM_GROUPWISE, + E_CONTACT_IM_JABBER, + E_CONTACT_IM_YAHOO, + E_CONTACT_IM_MSN, + E_CONTACT_IM_ICQ, + E_CONTACT_IM_GADUGADU, + E_CONTACT_IM_SKYPE, + + -1, + + E_CONTACT_NOTE + }; + + g_return_if_fail (preview != NULL); + g_return_if_fail (contact != NULL); + + for (idx = 0; idx < G_N_ELEMENTS (fields); idx++) { + EContactField field; + + if (fields[idx] == -1) { + if (had_value) + e_web_view_preview_add_empty_line (preview); + had_value = FALSE; + continue; + } + + field = fields[idx]; + + if (field == E_CONTACT_BIRTH_DATE || field == E_CONTACT_ANNIVERSARY) { + EContactDate *dt = e_contact_get (contact, field); + if (dt) { + GDate gd = { 0 }; + struct tm tm; + gchar *value; + + g_date_set_dmy (&gd, dt->day, dt->month, dt->year); + g_date_to_struct_tm (&gd, &tm); + + value = e_datetime_format_format_tm ("addressbook", "table", DTFormatKindDate, &tm); + if (value) { + e_web_view_preview_add_section (preview, e_contact_pretty_name (field), value); + had_value = TRUE; + } + + g_free (value); + e_contact_date_free (dt); + } + } else if (field == E_CONTACT_IS_LIST || field == E_CONTACT_WANTS_HTML || field == E_CONTACT_LIST_SHOW_ADDRESSES) { + if (e_contact_get (contact, field)) { + e_web_view_preview_add_text (preview, e_contact_pretty_name (field)); + had_value = TRUE; + } + } else if (field == E_CONTACT_ADDRESS_HOME || field == E_CONTACT_ADDRESS_WORK || field == E_CONTACT_ADDRESS_OTHER) { + EContactAddress *addr = e_contact_get (contact, field); + if (addr) { + gboolean have = FALSE; + + #define add_it(_what) \ + if (addr->_what && *addr->_what) { \ + e_web_view_preview_add_section (preview, have ? NULL : e_contact_pretty_name (field), addr->_what); \ + have = TRUE; \ + had_value = TRUE; \ + } + + add_it (po); + add_it (ext); + add_it (street); + add_it (locality); + add_it (region); + add_it (code); + add_it (country); + + #undef add_it + + e_contact_address_free (addr); + } + } else if (field == E_CONTACT_IM_AIM || field == E_CONTACT_IM_GROUPWISE || + field == E_CONTACT_IM_JABBER || field == E_CONTACT_IM_YAHOO || + field == E_CONTACT_IM_MSN || field == E_CONTACT_IM_ICQ || + field == E_CONTACT_IM_GADUGADU || field == E_CONTACT_IM_SKYPE || + field == E_CONTACT_EMAIL) { + GList *attrs, *a; + gboolean have = FALSE; + + attrs = e_contact_get_attributes (contact, field); + for (a = attrs; a; a = a->next) { + EVCardAttribute *attr = a->data; + GList *value; + + if (!attr) + continue; + + for (value = e_vcard_attribute_get_values (attr); value; value = value->next) { + const gchar *str = value->data; + + if (str && *str) { + e_web_view_preview_add_section (preview, have ? NULL : e_contact_pretty_name (field), str); + have = TRUE; + had_value = TRUE; + } + } + e_vcard_attribute_free (attr); + } + + g_list_free (attrs); + } else if (field == E_CONTACT_CATEGORIES) { + gchar *value = e_contact_get (contact, field); + + if (value && *value) { + e_web_view_preview_add_section (preview, e_contact_pretty_name (field), value); + had_value = TRUE; + } + + g_free (value); + } else { + const gchar *value = e_contact_get_const (contact, field); + + if (value && *value) { + e_web_view_preview_add_section (preview, e_contact_pretty_name (field), value); + had_value = TRUE; + } + } + } +} + +static void +preview_selection_changed_cb (GtkTreeSelection *selection, EWebViewPreview *preview) +{ + GtkTreeIter iter; + GtkTreeModel *model = NULL; + + g_return_if_fail (selection != NULL); + g_return_if_fail (preview != NULL); + + e_web_view_preview_begin_update (preview); + + if (gtk_tree_selection_get_selected (selection, &model, &iter) && model) { + EContact *contact = NULL; + + gtk_tree_model_get (model, &iter, 1, &contact, -1); + + if (contact) { + preview_contact (preview, contact); + g_object_unref (contact); + } + } + + e_web_view_preview_end_update (preview); +} + +GtkWidget * +evolution_contact_importer_get_preview_widget (const GList *contacts) +{ + GtkWidget *preview; + GtkTreeView *tree_view; + GtkTreeSelection *selection; + GtkListStore *store; + GtkTreeIter iter; + const GList *c; + + if (!contacts) + return NULL; + + store = gtk_list_store_new (2, G_TYPE_STRING, E_TYPE_CONTACT); + + for (c = contacts; c; c = c->next) { + const gchar *description; + EContact *contact = (EContact *) c->data; + + if (!contact || !E_IS_CONTACT (contact)) + continue; + + description = e_contact_get_const (contact, E_CONTACT_FILE_AS); + if (!description) + description = e_contact_get_const (contact, E_CONTACT_UID); + + gtk_list_store_append (store, &iter); + gtk_list_store_set (store, &iter, + 0, description ? description : "", + 1, contact, + -1 ); + } + + if (!gtk_tree_model_get_iter_first (GTK_TREE_MODEL (store), &iter)) { + g_object_unref (store); + return NULL; + } + + preview = e_web_view_preview_new (); + gtk_widget_show (preview); + + tree_view = e_web_view_preview_get_tree_view (E_WEB_VIEW_PREVIEW (preview)); + g_return_val_if_fail (tree_view != NULL, NULL); + + gtk_tree_view_set_model (tree_view, GTK_TREE_MODEL (store)); + g_object_unref (store); + + gtk_tree_view_insert_column_with_attributes (tree_view, -1, _("Contact"), + gtk_cell_renderer_text_new (), "text", 0, NULL); + + if (gtk_tree_model_iter_n_children (GTK_TREE_MODEL (store), NULL) > 1) + e_web_view_preview_show_tree_view (E_WEB_VIEW_PREVIEW (preview)); + + selection = gtk_tree_view_get_selection (tree_view); + gtk_tree_selection_select_iter (selection, &iter); + g_signal_connect (selection, "changed", G_CALLBACK (preview_selection_changed_cb), preview); + + preview_selection_changed_cb (selection, E_WEB_VIEW_PREVIEW (preview)); + + return preview; +} -- cgit v1.2.3