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:

committed by
Damon Chaplin

parent
3c81b8f46c
commit
bf5ad102a4
@ -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
|
||||||
|
@ -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)) {
|
||||||
|
@ -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>
|
||||||
|
@ -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
|
||||||
|
@ -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
|
||||||
|
|
||||||
|
@ -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);
|
||||||
|
}
|
||||||
|
@ -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");
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user