aboutsummaryrefslogtreecommitdiffstats
path: root/calendar
diff options
context:
space:
mode:
Diffstat (limited to 'calendar')
-rw-r--r--calendar/ChangeLog27
-rw-r--r--calendar/gui/comp-util.c16
-rw-r--r--calendar/importers/GNOME_Evolution_Calendar_Importer.oaf.in24
-rw-r--r--calendar/importers/Makefile.am5
-rw-r--r--calendar/importers/evolution-calendar-importer.h3
-rw-r--r--calendar/importers/icalendar-importer.c646
-rw-r--r--calendar/importers/main.c8
7 files changed, 627 insertions, 102 deletions
diff --git a/calendar/ChangeLog b/calendar/ChangeLog
index 3885059cc3..9af5c2b585 100644
--- a/calendar/ChangeLog
+++ b/calendar/ChangeLog
@@ -1,3 +1,30 @@
+2002-02-08 Damon Chaplin <damon@ximian.com>
+
+ * importers/icalendar-importer.c: added vCalendar importer and
+ intelligent GnomeCalendar importer code here, as it shares a lot of
+ code with the iCalendar importer.
+
+ NOTE: check_folder_type() needs to be finished at some point.
+ It needs a new shell Corba call so it can decide whether to import
+ events or tasks into the folder. Currently it just imports both.
+
+ * importers/main.c (importer_factory_fn): create vCalendar importer
+ or GnomeCalendar importer if required.
+
+ * importers/evolution-calendar-importer.h: added declarations for
+ creating a vCalendar importer and intelligent Gnome Calendar importer.
+
+ * importers/Makefile.am: added -DEVOLUTION_SOUNDDIR so the importer
+ knows what filename to use for audio alarms in vCalendar files.
+ Added libicalvcal-evolution to LDADD.
+
+ * importers/GNOME_Evolution_Calendar_Importer.oaf.in: added vCalendar
+ importer and intelligent Gnome Calendar importer.
+
+ * gui/comp-util.c (cal_comp_util_compare_event_timezones): return TRUE
+ if the event uses UTC. We don't want to flag all events from Outlook,
+ which use UTC.
+
2002-02-08 JP Rosevear <jpr@ximian.com>
* gui/dialogs/task-details-page.glade: change custom widget
diff --git a/calendar/gui/comp-util.c b/calendar/gui/comp-util.c
index ec6c4fefbf..6b11322c05 100644
--- a/calendar/gui/comp-util.c
+++ b/calendar/gui/comp-util.c
@@ -114,6 +114,22 @@ cal_comp_util_compare_event_timezones (CalComponent *comp,
goto out;
}
+ /* If the event uses UTC for DTSTART & DTEND, return TRUE. Outlook
+ will send single events as UTC, so we don't want to mark all of
+ these. */
+ if (start_datetime.value->is_utc && end_datetime.value->is_utc) {
+ retval = TRUE;
+ goto out;
+ }
+
+ /* If the event uses floating time for DTSTART & DTEND, return TRUE.
+ Imported vCalendar files will use floating times, so we don't want
+ to mark all of these. */
+ if (!start_datetime.tzid && !end_datetime.tzid) {
+ retval = TRUE;
+ goto out;
+ }
+
/* FIXME: DURATION may be used instead. */
if (cal_component_compare_tzid (tzid, start_datetime.tzid)
&& cal_component_compare_tzid (tzid, end_datetime.tzid)) {
diff --git a/calendar/importers/GNOME_Evolution_Calendar_Importer.oaf.in b/calendar/importers/GNOME_Evolution_Calendar_Importer.oaf.in
index 0460bf471f..710567dbc0 100644
--- a/calendar/importers/GNOME_Evolution_Calendar_Importer.oaf.in
+++ b/calendar/importers/GNOME_Evolution_Calendar_Importer.oaf.in
@@ -24,4 +24,28 @@
_value="Imports iCalendar files into Evolution"/>
</oaf_server>
+
+<oaf_server iid="OAFIID:GNOME_Evolution_Calendar_vCalendar_Importer"
+ type="factory"
+ location="OAFIID:GNOME_Evolution_Calendar_ImporterFactory">
+
+ <oaf_attribute name="repo_ids" type="stringv">
+ <item value="IDL:GNOME/Evolution/Importer:1.0"/>
+ </oaf_attribute>
+ <oaf_attribute name="evolution:menu-name" type="string"
+ value="vCalendar files (.vcf)"/>
+ <oaf_attribute name="description" type="string"
+ _value="Imports vCalendar files into Evolution"/>
+
+</oaf_server>
+
+<oaf_server iid="OAFIID:GNOME_Evolution_Gnome_Calendar_Intelligent_Importer"
+ type="factory"
+ location="OAFIID:GNOME_Evolution_Calendar_ImporterFactory">
+
+ <oaf_attribute name="repo_ids" type="stringv">
+ <item value="IDL:GNOME/Evolution/IntelligentImporter:1.0"/>
+ </oaf_attribute>
+
+</oaf_server>
</oaf_info>
diff --git a/calendar/importers/Makefile.am b/calendar/importers/Makefile.am
index 4734bb687a..4015e12f86 100644
--- a/calendar/importers/Makefile.am
+++ b/calendar/importers/Makefile.am
@@ -1,7 +1,10 @@
bin_PROGRAMS = evolution-calendar-importer
+sounddir = $(datadir)/evolution/sounds
+
INCLUDES = \
-DEVOLUTION_LOCALEDIR=\""$(localedir)"\" \
+ -DEVOLUTION_SOUNDDIR=\""$(sounddir)"\" \
-DG_LOG_DOMAIN=\"Evolution-Importer\" \
-I$(top_srcdir) \
-I$(top_builddir)/shell \
@@ -12,6 +15,7 @@ INCLUDES = \
-I$(top_builddir)/calendar \
-I$(top_srcdir)/libical/src/libical \
-I$(top_builddir)/libical/src/libical \
+ -I$(top_srcdir)/libical/src/libicalvcal \
$(EVOLUTION_CALENDAR_CFLAGS)
evolution_calendar_importer_SOURCES = \
@@ -25,6 +29,7 @@ evolution_calendar_importer_LDADD = \
$(top_builddir)/calendar/cal-client/libcal-client.la \
$(top_builddir)/libwombat/libwombat.la \
$(top_builddir)/libical/src/libical/libical-evolution.la \
+ $(top_builddir)/libical/src/libicalvcal/libicalvcal-evolution.la \
$(EVOLUTION_CALENDAR_LIBS)
oafdir = $(datadir)/oaf
diff --git a/calendar/importers/evolution-calendar-importer.h b/calendar/importers/evolution-calendar-importer.h
index ac4d15dd8d..b4c59da340 100644
--- a/calendar/importers/evolution-calendar-importer.h
+++ b/calendar/importers/evolution-calendar-importer.h
@@ -28,6 +28,9 @@
BEGIN_GNOME_DECLS
BonoboObject *ical_importer_new (void);
+BonoboObject *vcal_importer_new (void);
+
+BonoboObject *gnome_calendar_importer_new (void);
END_GNOME_DECLS
diff --git a/calendar/importers/icalendar-importer.c b/calendar/importers/icalendar-importer.c
index 262c925b74..6a7a6f363f 100644
--- a/calendar/importers/icalendar-importer.c
+++ b/calendar/importers/icalendar-importer.c
@@ -23,17 +23,42 @@
#include <sys/types.h>
#include <fcntl.h>
#include <gtk/gtksignal.h>
+#include <gtk/gtkcheckbutton.h>
+#include <gtk/gtkhbox.h>
+#include <gtk/gtkmain.h>
+#include <libgnome/gnome-defs.h>
+#include <libgnome/gnome-util.h>
+#include <bonobo/bonobo-control.h>
+#include <gal/util/e-unicode-i18n.h>
#include <cal-client.h>
#include <importer/evolution-importer.h>
+#include <importer/evolution-intelligent-importer.h>
#include <importer/GNOME_Evolution_Importer.h>
+#include "icalvcal.h"
#include "evolution-calendar-importer.h"
+/* We timeout after 2 minutes, when opening the folders. */
+#define IMPORTER_TIMEOUT_SECONDS 120
+
+
typedef struct {
CalClient *client;
+ CalClient *tasks_client;
EvolutionImporter *importer;
icalcomponent *icalcomp;
+ gboolean folder_contains_events;
+ gboolean folder_contains_tasks;
} ICalImporter;
+typedef struct {
+ gboolean do_calendar;
+ gboolean do_tasks;
+} ICalIntelligentImporter;
+
+/*
+ * Functions shared by iCalendar & vCalendar importer.
+ */
+
static void
importer_destroy_cb (GtkObject *object, gpointer user_data)
{
@@ -42,27 +67,27 @@ importer_destroy_cb (GtkObject *object, gpointer user_data)
g_return_if_fail (ici != NULL);
gtk_object_unref (GTK_OBJECT (ici->client));
+ gtk_object_unref (GTK_OBJECT (ici->tasks_client));
if (ici->icalcomp != NULL)
icalcomponent_free (ici->icalcomp);
g_free (ici);
}
-static gboolean
-support_format_fn (EvolutionImporter *importer,
- const char *filename,
- void *closure)
+
+/* This reads in an entire file and returns it. It returns NULL on error.
+ The returned string should be freed. */
+static char*
+read_file (const char *filename)
{
- int fd;
+ int fd, n;
GString *str;
- icalcomponent *icalcomp;
- int n;
char buffer[2049];
- gboolean ret = TRUE;
+ gboolean error = FALSE;
/* read file contents */
fd = open (filename, O_RDONLY);
if (fd == -1)
- return FALSE;
+ return NULL;
str = g_string_new ("");
while (1) {
@@ -70,134 +95,159 @@ support_format_fn (EvolutionImporter *importer,
n = read (fd, buffer, sizeof (buffer) - 1);
if (n > 0) {
str = g_string_append (str, buffer);
- }
- else if (n == 0)
+ } else if (n == 0) {
break;
- else {
- ret = FALSE;
+ } else {
+ error = TRUE;
break;
}
}
close (fd);
- /* parse the file */
- if (ret) {
- icalcomp = icalparser_parse_string (str->str);
- if (icalcomp)
- icalcomponent_free (icalcomp);
+ if (error) {
+ g_string_free (str, FALSE);
+ return NULL;
+ } else {
+ gchar *retval = str->str;
+ g_string_free (str, FALSE);
+ return retval;
+ }
+}
+
+
+/* Returns the URI to load given a folder path. Currently this is just a full
+ pathname. The returned string should be freed. */
+static char*
+get_uri_from_folder_path (const char *folderpath)
+{
+ const char *name;
+ char *parent;
+
+ if (folderpath == NULL || *folderpath == '\0') {
+ return g_strdup_printf ("%s/evolution/local/Calendar/calendar.ics",
+ g_get_home_dir ());
+ }
+
+ name = strrchr (folderpath, '/');
+ if (name == NULL || name == folderpath) {
+ parent = "evolution/local/";
+ if (folderpath[0] == '/')
+ name = folderpath + 1;
else
- ret = FALSE;
+ name = folderpath;
+ } else {
+ name += 1;
+ parent = "evolution/local/Calendar/subfolders/";
}
- g_string_free (str, TRUE);
+ return g_strdup_printf ("%s/%s%s/calendar.ics", g_get_home_dir (),
+ parent, name);
+}
- return ret;
+
+/* Determine whether it is a calendar or tasks folder, or both. If it starts
+ with 'file:' we know it is a local folder so we see if it ends with
+ calendar.ics or tasks.ics. For remote folders (i.e. Exchange folders at
+ present), we import both calendar events and tasks into it. */
+static void
+check_folder_type (ICalImporter *ici,
+ const char *folderpath)
+{
+ ici->folder_contains_events = TRUE;
+ ici->folder_contains_tasks = TRUE;
+
+ /* FIXME: Finish. */
}
-static gboolean
-load_file_fn (EvolutionImporter *importer,
- const char *filename,
- const char *folderpath,
- void *closure)
+
+/* This removes all components except VEVENTs and VTIMEZONEs from the toplevel
+ icalcomponent, and returns a GList of the VTODO components. */
+static GList*
+prepare_events (icalcomponent *icalcomp)
{
- int fd;
- GString *str;
- icalcomponent *icalcomp;
- int n;
- char buffer[2049];
- char *uri_str;
- gboolean ret = TRUE;
- ICalImporter *ici = (ICalImporter *) closure;
+ icalcomponent *subcomp, *next_subcomp;
+ GList *vtodos = NULL;
- g_return_val_if_fail (ici != NULL, FALSE);
+ subcomp = icalcomponent_get_first_component (icalcomp,
+ ICAL_ANY_COMPONENT);
+ while (subcomp) {
+ icalcomponent_kind child_kind = icalcomponent_isa (subcomp);
+ next_subcomp = icalcomponent_get_next_component (icalcomp, ICAL_ANY_COMPONENT);
+ if (child_kind != ICAL_VEVENT_COMPONENT
+ && child_kind != ICAL_VTIMEZONE_COMPONENT) {
- if (folderpath == NULL || *folderpath == '\0')
- uri_str = g_strdup_printf ("%s/evolution/local/Calendar/calendar.ics",
- g_get_home_dir ());
- else {
- char *name;
- char *parent;
-
- name = strrchr (folderpath, '/');
- if (name == NULL || name == folderpath) {
- parent = g_strdup ("evolution/local/");
- if (folderpath[0] == '/')
- name = folderpath + 1;
+ icalcomponent_remove_component (icalcomp,
+ subcomp);
+ if (child_kind == ICAL_VTODO_COMPONENT)
+ vtodos = g_list_prepend (vtodos, subcomp);
else
- name = folderpath;
- }
- else {
- name += 1;
- parent = g_strdup ("evolution/local/Calendar/subfolders/");
+ icalcomponent_free (subcomp);
}
- uri_str = g_strdup_printf ("%s/%s%s/calendar.ics", g_get_home_dir (),
- parent, name);
+ subcomp = next_subcomp;
}
- /* read file contents */
- fd = open (filename, O_RDONLY);
- if (fd == -1)
- return FALSE;
+ return vtodos;
+}
- str = g_string_new ("");
- while (1) {
- memset (buffer, 0, sizeof(buffer));
- n = read (fd, buffer, sizeof (buffer) - 1);
- if (n > 0) {
- str = g_string_append (str, buffer);
- }
- else if (n == 0)
- break;
- else {
- ret = FALSE;
- break;
- }
- }
- close (fd);
+/* This removes all components except VTODOs and VTIMEZONEs from the toplevel
+ icalcomponent, and adds the given list of VTODO components. The list is
+ freed afterwards. */
+static void
+prepare_tasks (icalcomponent *icalcomp, GList *vtodos)
+{
+ icalcomponent *subcomp, *next_subcomp;
+ GList *elem;
- /* parse the file */
- if (ret) {
- icalcomp = icalparser_parse_string (str->str);
- if (icalcomp) {
- if (!cal_client_open_calendar (ici->client, uri_str, TRUE))
- ret = FALSE;
- else
- ici->icalcomp = icalcomp;
+ subcomp = icalcomponent_get_first_component (icalcomp,
+ ICAL_ANY_COMPONENT);
+ while (subcomp) {
+ icalcomponent_kind child_kind = icalcomponent_isa (subcomp);
+ next_subcomp = icalcomponent_get_next_component (icalcomp, ICAL_ANY_COMPONENT);
+ if (child_kind != ICAL_VTODO_COMPONENT
+ && child_kind != ICAL_VTIMEZONE_COMPONENT) {
+ icalcomponent_remove_component (icalcomp, subcomp);
+ icalcomponent_free (subcomp);
}
- else
- ret = FALSE;
+ subcomp = next_subcomp;
}
- g_string_free (str, TRUE);
- g_free (uri_str);
-
- return ret;
+ for (elem = vtodos; elem; elem = elem->next) {
+ icalcomponent_add_component (icalcomp, elem->data);
+ }
+ g_list_free (vtodos);
}
+
static void
process_item_fn (EvolutionImporter *importer,
CORBA_Object listener,
void *closure,
CORBA_Environment *ev)
{
- CalClientLoadState state;
+ CalClientLoadState state, tasks_state;
ICalImporter *ici = (ICalImporter *) closure;
+ GNOME_Evolution_ImporterListener_ImporterResult result;
+
+ result = GNOME_Evolution_ImporterListener_OK;
g_return_if_fail (ici != NULL);
g_return_if_fail (IS_CAL_CLIENT (ici->client));
g_return_if_fail (ici->icalcomp != NULL);
state = cal_client_get_load_state (ici->client);
- if (state == CAL_CLIENT_LOAD_LOADING) {
+ tasks_state = cal_client_get_load_state (ici->tasks_client);
+ if (state == CAL_CLIENT_LOAD_LOADING
+ || tasks_state == CAL_CLIENT_LOAD_LOADING) {
GNOME_Evolution_ImporterListener_notifyResult (
listener,
GNOME_Evolution_ImporterListener_NOT_READY,
TRUE, ev);
return;
}
- else if (state != CAL_CLIENT_LOAD_LOADED) {
+ else if (state != CAL_CLIENT_LOAD_LOADED
+ || tasks_state != CAL_CLIENT_LOAD_LOADED) {
GNOME_Evolution_ImporterListener_notifyResult (
listener,
GNOME_Evolution_ImporterListener_UNSUPPORTED_OPERATION,
@@ -205,20 +255,98 @@ process_item_fn (EvolutionImporter *importer,
return;
}
- /* import objects into the given client */
- if (!cal_client_update_objects (ici->client, ici->icalcomp)) {
- g_warning ("Could not update objects");
- GNOME_Evolution_ImporterListener_notifyResult (
- listener,
- GNOME_Evolution_ImporterListener_BAD_DATA,
- FALSE, ev);
+ /* If the folder contains events & tasks we can just import everything
+ into it. If it contains just events, we have to strip out the
+ VTODOs and import them into the default tasks folder. If the folder
+ contains just tasks, we strip out the VEVENTs, which do not get
+ imported at all. */
+ if (ici->folder_contains_events && ici->folder_contains_tasks) {
+ if (!cal_client_update_objects (ici->client, ici->icalcomp))
+ result = GNOME_Evolution_ImporterListener_BAD_DATA;
+ } else if (ici->folder_contains_events) {
+ GList *vtodos = prepare_events (ici->icalcomp);
+ if (!cal_client_update_objects (ici->client, ici->icalcomp))
+ result = GNOME_Evolution_ImporterListener_BAD_DATA;
+
+ prepare_tasks (ici->icalcomp, vtodos);
+ if (!cal_client_update_objects (ici->tasks_client,
+ ici->icalcomp))
+ result = GNOME_Evolution_ImporterListener_BAD_DATA;
+ } else {
+ prepare_tasks (ici->icalcomp, NULL);
+ if (!cal_client_update_objects (ici->client, ici->icalcomp))
+ result = GNOME_Evolution_ImporterListener_BAD_DATA;
}
- else {
- GNOME_Evolution_ImporterListener_notifyResult (
- listener,
- GNOME_Evolution_ImporterListener_OK,
- FALSE, ev);
+
+ GNOME_Evolution_ImporterListener_notifyResult (listener, result, FALSE,
+ ev);
+}
+
+
+/*
+ * iCalendar importer functions.
+ */
+
+static gboolean
+support_format_fn (EvolutionImporter *importer,
+ const char *filename,
+ void *closure)
+{
+ char *contents;
+ icalcomponent *icalcomp;
+ gboolean ret = FALSE;
+
+ contents = read_file (filename);
+
+ /* parse the file */
+ if (contents) {
+ icalcomp = icalparser_parse_string (contents);
+ if (icalcomp) {
+ icalcomponent_free (icalcomp);
+ ret = TRUE;
+ }
+ }
+
+ g_free (contents);
+
+ return ret;
+}
+
+static gboolean
+load_file_fn (EvolutionImporter *importer,
+ const char *filename,
+ const char *folderpath,
+ void *closure)
+{
+ char *uri_str, *contents;
+ gboolean ret = FALSE;
+ ICalImporter *ici = (ICalImporter *) closure;
+
+ g_return_val_if_fail (ici != NULL, FALSE);
+
+ uri_str = get_uri_from_folder_path (folderpath);
+ check_folder_type (ici, folderpath);
+
+ contents = read_file (filename);
+
+ /* parse the file */
+ if (contents) {
+ icalcomponent *icalcomp;
+
+ icalcomp = icalparser_parse_string (contents);
+ if (icalcomp) {
+ if (cal_client_open_calendar (ici->client, uri_str, TRUE)
+ && cal_client_open_default_tasks (ici->tasks_client, FALSE)) {
+ ici->icalcomp = icalcomp;
+ ret = TRUE;
+ }
+ }
}
+
+ g_free (contents);
+ g_free (uri_str);
+
+ return ret;
}
BonoboObject *
@@ -228,6 +356,7 @@ ical_importer_new (void)
ici = g_new0 (ICalImporter, 1);
ici->client = cal_client_new ();
+ ici->tasks_client = cal_client_new ();
ici->icalcomp = NULL;
ici->importer = evolution_importer_new (support_format_fn,
load_file_fn,
@@ -239,3 +368,316 @@ ical_importer_new (void)
return BONOBO_OBJECT (ici->importer);
}
+
+
+
+/*
+ * vCalendar importer functions.
+ */
+
+static gboolean
+vcal_support_format_fn (EvolutionImporter *importer,
+ const char *filename,
+ void *closure)
+{
+ char *contents;
+ gboolean ret = FALSE;
+
+ contents = read_file (filename);
+
+ /* parse the file */
+ if (contents) {
+ VObject *vcal;
+
+ vcal = Parse_MIME (contents, strlen (contents));
+
+ if (vcal) {
+ icalcomponent *icalcomp;
+
+ icalcomp = icalvcal_convert (vcal);
+
+ if (icalcomp) {
+ icalcomponent_free (icalcomp);
+ ret = TRUE;
+ }
+
+ cleanVObject (vcal);
+ }
+ }
+
+ g_free (contents);
+
+ return ret;
+}
+
+/* This tries to load in a vCalendar file and convert it to an icalcomponent.
+ It returns NULL on failure. */
+static icalcomponent*
+load_vcalendar_file (const char *filename)
+{
+ icalvcal_defaults defaults = { 0 };
+ icalcomponent *icalcomp = NULL;
+ char *contents;
+
+ defaults.alarm_audio_url = "file://" EVOLUTION_SOUNDDIR "/default_alarm.wav";
+ defaults.alarm_audio_fmttype = "audio/x-wav";
+ defaults.alarm_description = (char*) U_("Reminder!!");
+
+ contents = read_file (filename);
+
+ /* parse the file */
+ if (contents) {
+ VObject *vcal;
+
+ vcal = Parse_MIME (contents, strlen (contents));
+
+ if (vcal) {
+ icalcomp = icalvcal_convert_with_defaults (vcal,
+ &defaults);
+ cleanVObject (vcal);
+ }
+ }
+
+ g_free (contents);
+
+ return icalcomp;
+}
+
+static gboolean
+vcal_load_file_fn (EvolutionImporter *importer,
+ const char *filename,
+ const char *folderpath,
+ void *closure)
+{
+ char *uri_str;
+ gboolean ret = FALSE;
+ ICalImporter *ici = (ICalImporter *) closure;
+ icalcomponent *icalcomp;
+
+ g_return_val_if_fail (ici != NULL, FALSE);
+
+ uri_str = get_uri_from_folder_path (folderpath);
+ check_folder_type (ici, folderpath);
+
+ icalcomp = load_vcalendar_file (filename);
+ if (icalcomp) {
+ if (cal_client_open_calendar (ici->client, uri_str, TRUE)
+ && cal_client_open_default_tasks (ici->tasks_client, FALSE)) {
+ ici->icalcomp = icalcomp;
+ ret = TRUE;
+ }
+ }
+
+ g_free (uri_str);
+
+ return ret;
+}
+
+BonoboObject *
+vcal_importer_new (void)
+{
+ ICalImporter *ici;
+
+ ici = g_new0 (ICalImporter, 1);
+ ici->client = cal_client_new ();
+ ici->tasks_client = cal_client_new ();
+ ici->icalcomp = NULL;
+ ici->importer = evolution_importer_new (vcal_support_format_fn,
+ vcal_load_file_fn,
+ process_item_fn,
+ NULL,
+ ici);
+ gtk_signal_connect (GTK_OBJECT (ici->importer), "destroy",
+ GTK_SIGNAL_FUNC (importer_destroy_cb), ici);
+
+ return BONOBO_OBJECT (ici->importer);
+}
+
+
+
+
+
+
+static void
+gnome_calendar_importer_destroy_cb (GtkObject *object, gpointer user_data)
+{
+ ICalIntelligentImporter *ici = (ICalIntelligentImporter *) user_data;
+
+ g_return_if_fail (ici != NULL);
+
+ g_free (ici);
+}
+
+
+
+static gboolean
+gnome_calendar_can_import_fn (EvolutionIntelligentImporter *ii,
+ void *closure)
+{
+ char *filename;
+ gboolean gnome_calendar_exists;
+
+ filename = gnome_util_home_file ("user-cal.vcf");
+ gnome_calendar_exists = g_file_exists (filename);
+ g_free (filename);
+
+ return gnome_calendar_exists;
+}
+
+
+static void
+gnome_calendar_import_data_fn (EvolutionIntelligentImporter *ii,
+ void *closure)
+{
+ ICalIntelligentImporter *ici = closure;
+ icalcomponent *icalcomp = NULL;
+ char *filename;
+ GList *vtodos;
+ CalClient *calendar_client = NULL, *tasks_client = NULL;
+ int t;
+
+ /* If neither is selected, just return. */
+ if (!ici->do_calendar && !ici->do_tasks) {
+ return;
+ }
+
+ /* Try to open the default calendar & tasks folders. */
+ if (ici->do_calendar) {
+ calendar_client = cal_client_new ();
+ if (!cal_client_open_default_calendar (calendar_client, FALSE))
+ goto out;
+ }
+
+ if (ici->do_tasks) {
+ tasks_client = cal_client_new ();
+ if (!cal_client_open_default_tasks (tasks_client, FALSE))
+ goto out;
+ }
+
+ /* Load the Gnome Calendar file and convert to iCalendar. */
+ filename = gnome_util_home_file ("user-cal.vcf");
+ icalcomp = load_vcalendar_file (filename);
+ g_free (filename);
+
+ /* If we couldn't load the file, just return. FIXME: Error message? */
+ if (!icalcomp)
+ goto out;
+
+ /*
+ * Import the calendar events into the default calendar folder.
+ */
+ vtodos = prepare_events (icalcomp);
+
+ /* Wait for client to finish opening the calendar & tasks folders. */
+ for (t = 0; t < IMPORTER_TIMEOUT_SECONDS; t++) {
+ CalClientLoadState calendar_state, tasks_state;
+
+ calendar_state = tasks_state = CAL_CLIENT_LOAD_LOADED;
+
+ /* We need this so the CalClient gets notified that the
+ folder is opened, via Corba. */
+ while (gtk_events_pending ())
+ gtk_main_iteration ();
+
+ if (ici->do_calendar)
+ calendar_state = cal_client_get_load_state (calendar_client);
+
+ if (ici->do_tasks)
+ tasks_state = cal_client_get_load_state (tasks_client);
+
+ if (calendar_state == CAL_CLIENT_LOAD_LOADED
+ && tasks_state == CAL_CLIENT_LOAD_LOADED)
+ break;
+
+ sleep (1);
+ }
+
+ /* If we timed out, just return. */
+ if (t == IMPORTER_TIMEOUT_SECONDS)
+ goto out;
+
+ /* Import the calendar events. */
+ /* FIXME: What do intelligent importers do about errors? */
+ if (ici->do_calendar)
+ cal_client_update_objects (calendar_client, icalcomp);
+
+
+ /*
+ * Import the tasks into the default tasks folder.
+ */
+ prepare_tasks (icalcomp, vtodos);
+ if (ici->do_tasks)
+ cal_client_update_objects (tasks_client, icalcomp);
+
+ out:
+ if (icalcomp)
+ icalcomponent_free (icalcomp);
+ if (calendar_client)
+ gtk_object_unref (GTK_OBJECT (calendar_client));
+ if (tasks_client)
+ gtk_object_unref (GTK_OBJECT (tasks_client));
+}
+
+
+/* Fun with aggregation */
+static void
+checkbox_toggle_cb (GtkToggleButton *tb,
+ gboolean *do_item)
+{
+ *do_item = gtk_toggle_button_get_active (tb);
+}
+
+static BonoboControl *
+create_checkboxes_control (ICalIntelligentImporter *ici)
+{
+ GtkWidget *hbox, *calendar_checkbox, *tasks_checkbox;
+ BonoboControl *control;
+
+ hbox = gtk_hbox_new (FALSE, 2);
+
+ calendar_checkbox = gtk_check_button_new_with_label (_("Calendar Events"));
+ gtk_signal_connect (GTK_OBJECT (calendar_checkbox), "toggled",
+ GTK_SIGNAL_FUNC (checkbox_toggle_cb),
+ &ici->do_calendar);
+ gtk_box_pack_start (GTK_BOX (hbox), calendar_checkbox,
+ FALSE, FALSE, 0);
+
+ tasks_checkbox = gtk_check_button_new_with_label (_("Tasks"));
+ gtk_signal_connect (GTK_OBJECT (tasks_checkbox), "toggled",
+ GTK_SIGNAL_FUNC (checkbox_toggle_cb),
+ &ici->do_tasks);
+ gtk_box_pack_start (GTK_BOX (hbox), tasks_checkbox,
+ FALSE, FALSE, 0);
+
+ gtk_widget_show_all (hbox);
+ control = bonobo_control_new (hbox);
+ return control;
+}
+
+BonoboObject *
+gnome_calendar_importer_new (void)
+{
+ EvolutionIntelligentImporter *importer;
+ ICalIntelligentImporter *ici;
+ BonoboControl *control;
+ char *message = N_("Evolution has found Gnome Calendar files.\n"
+ "Would you like to import them into Evolution?");
+
+ ici = g_new0 (ICalIntelligentImporter, 1);
+
+ importer = evolution_intelligent_importer_new (gnome_calendar_can_import_fn,
+ gnome_calendar_import_data_fn,
+ _("Gnome Calendar"),
+ _(message),
+ ici);
+
+
+ gtk_signal_connect (GTK_OBJECT (importer), "destroy",
+ GTK_SIGNAL_FUNC (gnome_calendar_importer_destroy_cb), ici);
+
+ control = create_checkboxes_control (ici);
+ bonobo_object_add_interface (BONOBO_OBJECT (importer),
+ BONOBO_OBJECT (control));
+
+ return BONOBO_OBJECT (importer);
+}
diff --git a/calendar/importers/main.c b/calendar/importers/main.c
index aaf4ced23a..f6d5788d93 100644
--- a/calendar/importers/main.c
+++ b/calendar/importers/main.c
@@ -24,10 +24,14 @@
#include <config.h>
#endif
#include <bonobo/bonobo-generic-factory.h>
+#include <bonobo/bonobo-context.h>
+#include <bonobo/bonobo-main.h>
#include "evolution-calendar-importer.h"
#define IMPORTER_FACTORY_ID "OAFIID:GNOME_Evolution_Calendar_ImporterFactory"
#define ICALENDAR_IMPORTER_ID "OAFIID:GNOME_Evolution_Calendar_iCalendar_Importer"
+#define VCALENDAR_IMPORTER_ID "OAFIID:GNOME_Evolution_Calendar_vCalendar_Importer"
+#define GNOME_CALENDAR_IMPORTER_ID "OAFIID:GNOME_Evolution_Gnome_Calendar_Intelligent_Importer"
static BonoboObject *
importer_factory_fn (BonoboGenericFactory *factory, const char *id, void *closure)
@@ -38,6 +42,10 @@ importer_factory_fn (BonoboGenericFactory *factory, const char *id, void *closur
if (!strcmp (id, ICALENDAR_IMPORTER_ID))
object = ical_importer_new ();
+ else if (!strcmp (id, VCALENDAR_IMPORTER_ID))
+ object = vcal_importer_new ();
+ else if (!strcmp (id, GNOME_CALENDAR_IMPORTER_ID))
+ object = gnome_calendar_importer_new ();
else
g_warning ("Component not supporte by this factory");