added vCalendar importer and intelligent GnomeCalendar importer code here,

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.

svn path=/trunk/; revision=15628
This commit is contained in:
Damon Chaplin
2002-02-09 01:03:32 +00:00
committed by Damon Chaplin
parent 3c81b8f46c
commit bf5ad102a4
7 changed files with 649 additions and 124 deletions

View File

@ -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> 2002-02-08 JP Rosevear <jpr@ximian.com>
* gui/dialogs/task-details-page.glade: change custom widget * gui/dialogs/task-details-page.glade: change custom widget

View File

@ -114,6 +114,22 @@ cal_comp_util_compare_event_timezones (CalComponent *comp,
goto out; 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. */ /* FIXME: DURATION may be used instead. */
if (cal_component_compare_tzid (tzid, start_datetime.tzid) if (cal_component_compare_tzid (tzid, start_datetime.tzid)
&& cal_component_compare_tzid (tzid, end_datetime.tzid)) { && cal_component_compare_tzid (tzid, end_datetime.tzid)) {

View File

@ -23,5 +23,29 @@
<oaf_attribute name="description" type="string" <oaf_attribute name="description" type="string"
_value="Imports iCalendar files into Evolution"/> _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_server>
</oaf_info> </oaf_info>

View File

@ -1,7 +1,10 @@
bin_PROGRAMS = evolution-calendar-importer bin_PROGRAMS = evolution-calendar-importer
sounddir = $(datadir)/evolution/sounds
INCLUDES = \ INCLUDES = \
-DEVOLUTION_LOCALEDIR=\""$(localedir)"\" \ -DEVOLUTION_LOCALEDIR=\""$(localedir)"\" \
-DEVOLUTION_SOUNDDIR=\""$(sounddir)"\" \
-DG_LOG_DOMAIN=\"Evolution-Importer\" \ -DG_LOG_DOMAIN=\"Evolution-Importer\" \
-I$(top_srcdir) \ -I$(top_srcdir) \
-I$(top_builddir)/shell \ -I$(top_builddir)/shell \
@ -12,6 +15,7 @@ INCLUDES = \
-I$(top_builddir)/calendar \ -I$(top_builddir)/calendar \
-I$(top_srcdir)/libical/src/libical \ -I$(top_srcdir)/libical/src/libical \
-I$(top_builddir)/libical/src/libical \ -I$(top_builddir)/libical/src/libical \
-I$(top_srcdir)/libical/src/libicalvcal \
$(EVOLUTION_CALENDAR_CFLAGS) $(EVOLUTION_CALENDAR_CFLAGS)
evolution_calendar_importer_SOURCES = \ evolution_calendar_importer_SOURCES = \
@ -25,6 +29,7 @@ evolution_calendar_importer_LDADD = \
$(top_builddir)/calendar/cal-client/libcal-client.la \ $(top_builddir)/calendar/cal-client/libcal-client.la \
$(top_builddir)/libwombat/libwombat.la \ $(top_builddir)/libwombat/libwombat.la \
$(top_builddir)/libical/src/libical/libical-evolution.la \ $(top_builddir)/libical/src/libical/libical-evolution.la \
$(top_builddir)/libical/src/libicalvcal/libicalvcal-evolution.la \
$(EVOLUTION_CALENDAR_LIBS) $(EVOLUTION_CALENDAR_LIBS)
oafdir = $(datadir)/oaf oafdir = $(datadir)/oaf

View File

@ -28,6 +28,9 @@
BEGIN_GNOME_DECLS BEGIN_GNOME_DECLS
BonoboObject *ical_importer_new (void); BonoboObject *ical_importer_new (void);
BonoboObject *vcal_importer_new (void);
BonoboObject *gnome_calendar_importer_new (void);
END_GNOME_DECLS END_GNOME_DECLS

View File

@ -23,17 +23,42 @@
#include <sys/types.h> #include <sys/types.h>
#include <fcntl.h> #include <fcntl.h>
#include <gtk/gtksignal.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 <cal-client.h>
#include <importer/evolution-importer.h> #include <importer/evolution-importer.h>
#include <importer/evolution-intelligent-importer.h>
#include <importer/GNOME_Evolution_Importer.h> #include <importer/GNOME_Evolution_Importer.h>
#include "icalvcal.h"
#include "evolution-calendar-importer.h" #include "evolution-calendar-importer.h"
/* We timeout after 2 minutes, when opening the folders. */
#define IMPORTER_TIMEOUT_SECONDS 120
typedef struct { typedef struct {
CalClient *client; CalClient *client;
CalClient *tasks_client;
EvolutionImporter *importer; EvolutionImporter *importer;
icalcomponent *icalcomp; icalcomponent *icalcomp;
gboolean folder_contains_events;
gboolean folder_contains_tasks;
} ICalImporter; } ICalImporter;
typedef struct {
gboolean do_calendar;
gboolean do_tasks;
} ICalIntelligentImporter;
/*
* Functions shared by iCalendar & vCalendar importer.
*/
static void static void
importer_destroy_cb (GtkObject *object, gpointer user_data) 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); g_return_if_fail (ici != NULL);
gtk_object_unref (GTK_OBJECT (ici->client)); gtk_object_unref (GTK_OBJECT (ici->client));
gtk_object_unref (GTK_OBJECT (ici->tasks_client));
if (ici->icalcomp != NULL) if (ici->icalcomp != NULL)
icalcomponent_free (ici->icalcomp); icalcomponent_free (ici->icalcomp);
g_free (ici); g_free (ici);
} }
static gboolean
support_format_fn (EvolutionImporter *importer, /* This reads in an entire file and returns it. It returns NULL on error.
const char *filename, The returned string should be freed. */
void *closure) static char*
read_file (const char *filename)
{ {
int fd; int fd, n;
GString *str; GString *str;
icalcomponent *icalcomp;
int n;
char buffer[2049]; char buffer[2049];
gboolean ret = TRUE; gboolean error = FALSE;
/* read file contents */ /* read file contents */
fd = open (filename, O_RDONLY); fd = open (filename, O_RDONLY);
if (fd == -1) if (fd == -1)
return FALSE; return NULL;
str = g_string_new (""); str = g_string_new ("");
while (1) { while (1) {
@ -70,27 +95,219 @@ support_format_fn (EvolutionImporter *importer,
n = read (fd, buffer, sizeof (buffer) - 1); n = read (fd, buffer, sizeof (buffer) - 1);
if (n > 0) { if (n > 0) {
str = g_string_append (str, buffer); str = g_string_append (str, buffer);
} } else if (n == 0) {
else if (n == 0)
break; break;
else { } else {
ret = FALSE; error = TRUE;
break; break;
} }
} }
close (fd); close (fd);
/* parse the file */ if (error) {
if (ret) { g_string_free (str, FALSE);
icalcomp = icalparser_parse_string (str->str); return NULL;
if (icalcomp) } else {
icalcomponent_free (icalcomp); gchar *retval = str->str;
else g_string_free (str, FALSE);
ret = FALSE; return retval;
}
} }
g_string_free (str, TRUE);
/* 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
name = folderpath;
} else {
name += 1;
parent = "evolution/local/Calendar/subfolders/";
}
return g_strdup_printf ("%s/%s%s/calendar.ics", g_get_home_dir (),
parent, name);
}
/* 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. */
}
/* 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)
{
icalcomponent *subcomp, *next_subcomp;
GList *vtodos = NULL;
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) {
icalcomponent_remove_component (icalcomp,
subcomp);
if (child_kind == ICAL_VTODO_COMPONENT)
vtodos = g_list_prepend (vtodos, subcomp);
else
icalcomponent_free (subcomp);
}
subcomp = next_subcomp;
}
return vtodos;
}
/* 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;
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);
}
subcomp = next_subcomp;
}
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, 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);
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
|| tasks_state != CAL_CLIENT_LOAD_LOADED) {
GNOME_Evolution_ImporterListener_notifyResult (
listener,
GNOME_Evolution_ImporterListener_UNSUPPORTED_OPERATION,
FALSE, ev);
return;
}
/* 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;
}
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; return ret;
} }
@ -101,126 +318,37 @@ load_file_fn (EvolutionImporter *importer,
const char *folderpath, const char *folderpath,
void *closure) void *closure)
{ {
int fd; char *uri_str, *contents;
GString *str; gboolean ret = FALSE;
icalcomponent *icalcomp;
int n;
char buffer[2049];
char *uri_str;
gboolean ret = TRUE;
ICalImporter *ici = (ICalImporter *) closure; ICalImporter *ici = (ICalImporter *) closure;
g_return_val_if_fail (ici != NULL, FALSE); g_return_val_if_fail (ici != NULL, FALSE);
if (folderpath == NULL || *folderpath == '\0') uri_str = get_uri_from_folder_path (folderpath);
uri_str = g_strdup_printf ("%s/evolution/local/Calendar/calendar.ics", check_folder_type (ici, folderpath);
g_get_home_dir ());
else {
char *name;
char *parent;
name = strrchr (folderpath, '/'); contents = read_file (filename);
if (name == NULL || name == folderpath) {
parent = g_strdup ("evolution/local/");
if (folderpath[0] == '/')
name = folderpath + 1;
else
name = folderpath;
}
else {
name += 1;
parent = g_strdup ("evolution/local/Calendar/subfolders/");
}
uri_str = g_strdup_printf ("%s/%s%s/calendar.ics", g_get_home_dir (),
parent, name);
}
/* read file contents */
fd = open (filename, O_RDONLY);
if (fd == -1)
return FALSE;
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);
/* parse the file */ /* parse the file */
if (ret) { if (contents) {
icalcomp = icalparser_parse_string (str->str); icalcomponent *icalcomp;
icalcomp = icalparser_parse_string (contents);
if (icalcomp) { if (icalcomp) {
if (!cal_client_open_calendar (ici->client, uri_str, TRUE)) if (cal_client_open_calendar (ici->client, uri_str, TRUE)
ret = FALSE; && cal_client_open_default_tasks (ici->tasks_client, FALSE)) {
else
ici->icalcomp = icalcomp; ici->icalcomp = icalcomp;
ret = TRUE;
}
} }
else
ret = FALSE;
} }
g_string_free (str, TRUE); g_free (contents);
g_free (uri_str); g_free (uri_str);
return ret; return ret;
} }
static void
process_item_fn (EvolutionImporter *importer,
CORBA_Object listener,
void *closure,
CORBA_Environment *ev)
{
CalClientLoadState state;
ICalImporter *ici = (ICalImporter *) closure;
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) {
GNOME_Evolution_ImporterListener_notifyResult (
listener,
GNOME_Evolution_ImporterListener_NOT_READY,
TRUE, ev);
return;
}
else if (state != CAL_CLIENT_LOAD_LOADED) {
GNOME_Evolution_ImporterListener_notifyResult (
listener,
GNOME_Evolution_ImporterListener_UNSUPPORTED_OPERATION,
FALSE, ev);
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);
}
else {
GNOME_Evolution_ImporterListener_notifyResult (
listener,
GNOME_Evolution_ImporterListener_OK,
FALSE, ev);
}
}
BonoboObject * BonoboObject *
ical_importer_new (void) ical_importer_new (void)
{ {
@ -228,6 +356,7 @@ ical_importer_new (void)
ici = g_new0 (ICalImporter, 1); ici = g_new0 (ICalImporter, 1);
ici->client = cal_client_new (); ici->client = cal_client_new ();
ici->tasks_client = cal_client_new ();
ici->icalcomp = NULL; ici->icalcomp = NULL;
ici->importer = evolution_importer_new (support_format_fn, ici->importer = evolution_importer_new (support_format_fn,
load_file_fn, load_file_fn,
@ -239,3 +368,316 @@ ical_importer_new (void)
return BONOBO_OBJECT (ici->importer); 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);
}

View File

@ -24,10 +24,14 @@
#include <config.h> #include <config.h>
#endif #endif
#include <bonobo/bonobo-generic-factory.h> #include <bonobo/bonobo-generic-factory.h>
#include <bonobo/bonobo-context.h>
#include <bonobo/bonobo-main.h>
#include "evolution-calendar-importer.h" #include "evolution-calendar-importer.h"
#define IMPORTER_FACTORY_ID "OAFIID:GNOME_Evolution_Calendar_ImporterFactory" #define IMPORTER_FACTORY_ID "OAFIID:GNOME_Evolution_Calendar_ImporterFactory"
#define ICALENDAR_IMPORTER_ID "OAFIID:GNOME_Evolution_Calendar_iCalendar_Importer" #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 * static BonoboObject *
importer_factory_fn (BonoboGenericFactory *factory, const char *id, void *closure) 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)) if (!strcmp (id, ICALENDAR_IMPORTER_ID))
object = ical_importer_new (); 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 else
g_warning ("Component not supporte by this factory"); g_warning ("Component not supporte by this factory");