[evolution-patches] [Calendar] ICS-Importer EPlugin



Hi

A EPlugin for importing ICS files in mail attachments into 'calendar'
or 'tasks lists'

Please review .

Thanks
Johnny
Index: ChangeLog
===================================================================
RCS file: /cvs/gnome/evolution/ChangeLog,v
retrieving revision 1.1551
diff -u -p -r1.1551 ChangeLog
--- ChangeLog	2 Jan 2006 16:35:41 -0000	1.1551
+++ ChangeLog	3 Jan 2006 16:10:34 -0000
@@ -1,3 +1,8 @@
+2006-01-02  Johnny Jacob  <johnnyjacob gmail com>
+
+	* configure.in: Added the plugin for importing ICS files into
+	calendar from mail attachments.
+
 2006-01-02  Harish Krishnaswamy  <kharish novell com>
 
 	* NEWS, configure.in: Release updates, version bump.
Index: configure.in
===================================================================
RCS file: /cvs/gnome/evolution/configure.in,v
retrieving revision 1.864
diff -u -p -r1.864 configure.in
--- configure.in	19 Dec 2005 11:23:08 -0000	1.864
+++ configure.in	3 Jan 2006 16:11:14 -0000
@@ -1403,7 +1403,7 @@ plugins_standard="$plugins_standard_alwa
 all_plugins_standard="$plugins_standard"
 
 plugins_experimental_always="backup-restore folder-unsubscribe mail-to-meeting mail-remote prefer-plain save-attachments"
-plugins_experimental="$plugins_experimental $IPOD_SYNC"
+plugins_experimental="$plugins_experimental $IPOD_SYNC import-ics-attachments"
 all_plugins_experimental="$plugins_experimental_always ipod-sync"
 
 case x"$enable_plugins" in
@@ -1703,6 +1703,7 @@ plugins/mail-account-disable/Makefile
 plugins/sa-junk-plugin/Makefile
 plugins/ipod-sync/Makefile
 plugins/publish-calendar/Makefile
+plugins/import-ics-attachments/Makefile
 smime/Makefile
 smime/lib/Makefile
 smime/gui/Makefile
--- /dev/null	2006-01-03 09:06:01.188250250 +0530
+++ plugins/import-ics-attachments/icsimporter.c	2006-01-03 20:00:59.000000000 +0530
@@ -0,0 +1,390 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
+ *
+ *  Authors: Srinivasa Ragavan <sragavan novell com>
+ *
+ *  Copyright 2005 Novell, Inc. (www.novell.com)
+ *
+ *  This program is free software; you can redistribute it and/or
+ *  modify it under the terms of version 2 of the GNU General Public
+ *  License as published by the Free Software Foundation.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Street #330, Boston, MA 02111-1307, USA.
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+#include <string.h>
+#include <glib.h>
+#include <gtk/gtk.h>
+#include <libgnome/gnome-i18n.h>
+#include <e-util/e-config.h>
+#include <e-util/e-popup.h>
+#include <mail/em-popup.h>
+#include <mail/em-menu.h>
+#include <mail/mail-ops.h>
+#include <mail/mail-mt.h>
+#include <mail/em-folder-view.h>
+#include <mail/em-format-html-display.h>
+#include "e-attachment-bar.h"
+#include <camel/camel-vee-folder.h>
+#include "e-util/e-error.h"
+#include "e-util/e-icon-factory.h"
+#include <libgnomevfs/gnome-vfs-utils.h>
+#include <libgnomevfs/gnome-vfs-mime.h>
+#include <libgnomevfs/gnome-vfs-mime-utils.h>
+#include <libgnomevfs/gnome-vfs-mime-handlers.h>
+#include <libedataserverui/e-source-selector.h>
+#include <libecal/e-cal.h>
+#include <libical/icalvcal.h>
+
+typedef struct {
+	ECal *client;
+	int source_type;
+	icalcomponent *icalcomp;
+	GtkWidget *window;
+	GtkWidget *selector;
+} ICalImporterData;
+
+
+static void import_ics (EPlugin *ep, EPopupTarget *t, void *data);
+static icalcomponent* get_icalcomponent_from_file(char *filename);
+static void prepare_events (icalcomponent *icalcomp, GList **vtodos);
+static void prepare_tasks (icalcomponent *icalcomp, GList *vtodos);
+static void import_items(ICalImporterData *icidata);
+static gboolean update_objects (ECal *client, icalcomponent *icalcomp);
+static void dialog_response_cb (GtkDialog *dialog, gint response_id, ICalImporterData *icidata);
+static void dialog_close_cb (GtkDialog *dialog, ICalImporterData *icidata);
+static void ical_import_done(ICalImporterData *icidata);
+static void init_widgets (char *path);
+
+void org_gnome_evolution_import_ics_attachments (EPlugin *ep, EMPopupTargetAttachments *t);
+void org_gnome_evolution_import_ics_part (EPlugin *ep, EMPopupTargetPart *t);
+
+static void 
+popup_free (EPopup *ep, GSList *items, void *data)
+{
+	g_slist_free (items);
+}
+
+static EPopupItem popup_items[] = {
+	{ E_POPUP_BAR, "25.display.00"},
+	{ E_POPUP_ITEM, "25.display.01", N_("_Import to Calendar"), import_ics, NULL, "stock_mail-import"}
+};
+
+void org_gnome_evolution_import_ics_attachments (EPlugin *ep, EMPopupTargetAttachments *t) 
+{
+	GSList *menus = NULL;
+	int len;
+	int i = 0;
+
+	len = g_slist_length(t->attachments);
+	if (!camel_content_type_is(((CamelDataWrapper *) ((EAttachment *) t->attachments->data)->body)->mime_type, "text", "calendar") || len >1)
+		return;
+	
+	for (i = 0; i < sizeof (popup_items) / sizeof (popup_items[0]); i++)
+		menus = g_slist_prepend (menus, &popup_items[i]);
+	
+	e_popup_add_items (t->target.popup, menus, NULL, popup_free, t);
+
+}
+
+void org_gnome_evolution_import_ics_part (EPlugin*ep, EMPopupTargetPart *t) 
+{
+	GSList *menus = NULL;
+	int i = 0;
+
+	if (!camel_content_type_is(((CamelDataWrapper *) t->part)->mime_type, "text", "calendar"))
+		return;
+	
+	for (i = 0; i < sizeof (popup_items) / sizeof (popup_items[0]); i++)
+		menus = g_slist_prepend (menus, &popup_items[i]);
+	
+	e_popup_add_items (t->target.popup, menus, NULL, popup_free, t);
+
+}
+
+static void
+import_ics (EPlugin *ep, EPopupTarget *t, void *data)
+{
+	CamelMimePart *part;
+	char *path;
+	EPopupTarget *target = (EPopupTarget *) data;	
+
+	if (target->type == EM_POPUP_TARGET_ATTACHMENTS)
+		part = ((EAttachment *) ((EMPopupTargetAttachments *) target)->attachments->data)->body;
+	else
+		part = ((EMPopupTargetPart *) target)->part;
+
+	path = em_utils_temp_save_part (NULL, part);
+	init_widgets(path);
+}
+
+static void
+init_widgets(char *path)
+{
+	
+	GtkWidget *vbox, *hbox, *dialog;
+	icalcomponent_kind kind;
+	icalcomponent *subcomp;
+	GtkWidget *selector, *label;
+	ESourceList *source_list;
+	ESource *primary;
+	GtkWidget *scrolled;
+	ICalImporterData *icidata = g_malloc0(sizeof(*icidata));
+
+	g_return_if_fail ( path != NULL);
+	dialog = gtk_dialog_new_with_buttons (_("Import ICS"), 
+						NULL, GTK_DIALOG_DESTROY_WITH_PARENT, 
+						GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
+						NULL);
+	icidata->window = dialog;
+	g_signal_connect (dialog,
+			  "response",
+			  G_CALLBACK (dialog_response_cb),
+			  icidata);
+	g_signal_connect (dialog,
+			  "close",
+			  G_CALLBACK (dialog_close_cb),
+			  icidata);
+
+	vbox = GTK_DIALOG(dialog)->vbox;
+	hbox = gtk_hbox_new (FALSE, FALSE);
+	label = gtk_label_new(NULL);
+
+	gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, TRUE, 6);
+
+	icidata->icalcomp = get_icalcomponent_from_file (path);
+
+	subcomp = icalcomponent_get_inner(icidata->icalcomp);
+	kind = icalcomponent_isa (subcomp);
+
+	char *label_str;
+	if (kind == ICAL_VTODO_COMPONENT ) {
+		e_cal_get_sources (&source_list, E_CAL_SOURCE_TYPE_TODO, NULL);
+		label_str = _("Select Task List");
+		icidata->source_type = E_CAL_SOURCE_TYPE_TODO;
+	} else if ( kind == ICAL_VEVENT_COMPONENT) {
+		e_cal_get_sources (&source_list, E_CAL_SOURCE_TYPE_EVENT, NULL);
+		label_str = _("Select Calendar");
+		icidata->source_type = E_CAL_SOURCE_TYPE_EVENT;
+	}
+
+	char *markup;
+	markup = g_markup_printf_escaped ("<b>%s</b>", label_str);
+	gtk_label_set_markup (label, markup);
+	hbox = gtk_hbox_new (FALSE, FALSE);
+	gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 6);
+	gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 6);
+
+	selector = e_source_selector_new (source_list);
+	e_source_selector_show_selection (E_SOURCE_SELECTOR (selector), FALSE);
+	scrolled = gtk_scrolled_window_new(NULL, NULL);
+	gtk_scrolled_window_set_policy((GtkScrolledWindow *)scrolled, GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
+	gtk_container_add((GtkContainer *)scrolled, selector);
+	gtk_scrolled_window_set_shadow_type (scrolled, GTK_SHADOW_IN);
+	hbox = gtk_hbox_new (FALSE, FALSE);
+	gtk_box_pack_start (GTK_BOX (hbox), scrolled, TRUE, TRUE, 6);
+	gtk_box_pack_start (GTK_BOX (vbox), hbox, TRUE, TRUE, 6);
+	icidata->selector = selector;
+	
+
+	/* FIXME What if no sources? */
+	primary = e_source_list_peek_source_any (source_list);
+	e_source_selector_set_primary_selection (E_SOURCE_SELECTOR (selector), primary);
+
+	g_object_unref (source_list);
+	hbox = gtk_hbox_new (FALSE, FALSE);
+	GtkWidget *icon = e_icon_factory_get_image ("stock_mail-import", E_ICON_SIZE_MENU);
+	gtk_box_pack_start (GTK_BOX(hbox), icon, FALSE, FALSE, 6);
+	label = gtk_label_new_with_mnemonic (_("_Import"));
+	gtk_box_pack_start (GTK_BOX(hbox), label, FALSE, FALSE, 6);
+	gtk_widget_show(label);
+	GtkWidget *button = gtk_button_new ();
+	gtk_container_add (button, hbox);
+	gtk_dialog_add_action_widget (dialog, button, GTK_RESPONSE_OK);
+	gtk_widget_grab_focus (button); 
+
+	gtk_window_set_default_size (dialog, 210,340);
+	gtk_widget_show_all (dialog);
+	gtk_dialog_run (dialog);
+}
+
+static void
+dialog_response_cb (GtkDialog *dialog, gint response_id, ICalImporterData *icidata)
+{
+	switch (response_id) {
+	case GTK_RESPONSE_OK :
+		import_items(icidata);
+	break;
+
+	case GTK_RESPONSE_CANCEL :
+	case GTK_RESPONSE_DELETE_EVENT :
+		gtk_signal_emit_by_name (dialog, "close");	
+	break;
+	}
+}
+
+static void 
+dialog_close_cb (GtkDialog *dialog, ICalImporterData *icidata)
+{
+	gtk_widget_destroy (dialog);
+}
+
+/* This removes all components except VEVENTs and VTIMEZONEs from the toplevel */
+static void
+prepare_events (icalcomponent *icalcomp, GList **vtodos)
+{
+	icalcomponent *subcomp;
+	icalcompiter iter;
+
+	if (vtodos)
+		*vtodos = NULL;
+	
+	iter = icalcomponent_begin_component (icalcomp, ICAL_ANY_COMPONENT);
+	while ((subcomp = icalcompiter_deref (&iter)) != NULL) {
+		icalcomponent_kind child_kind = icalcomponent_isa (subcomp);
+		if (child_kind != ICAL_VEVENT_COMPONENT
+		    && child_kind != ICAL_VTIMEZONE_COMPONENT) {
+
+			icalcompiter_next (&iter);
+
+			icalcomponent_remove_component (icalcomp, subcomp);
+			if (child_kind == ICAL_VTODO_COMPONENT && vtodos)
+				*vtodos = g_list_prepend (*vtodos, subcomp);
+			else
+                                icalcomponent_free (subcomp);
+		}
+
+		icalcompiter_next (&iter);
+	}
+}
+
+/* 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;
+	GList *elem;
+	icalcompiter iter;
+
+	iter = icalcomponent_begin_component (icalcomp, ICAL_ANY_COMPONENT);
+	while ((subcomp = icalcompiter_deref (&iter)) != NULL) {
+		icalcomponent_kind child_kind = icalcomponent_isa (subcomp);
+		if (child_kind != ICAL_VTODO_COMPONENT
+		    && child_kind != ICAL_VTIMEZONE_COMPONENT) {
+			icalcompiter_next (&iter);
+			icalcomponent_remove_component (icalcomp, subcomp);
+			icalcomponent_free (subcomp);
+		}
+
+		icalcompiter_next (&iter);
+	}
+
+	for (elem = vtodos; elem; elem = elem->next) {
+		icalcomponent_add_component (icalcomp, elem->data);
+	}
+	g_list_free (vtodos);
+}
+
+static void 
+import_items(ICalImporterData *icidata)
+{
+	ESource *source;
+	g_return_if_fail (icidata != NULL);
+
+	source = e_source_selector_peek_primary_selection ((ESourceSelector *)icidata->selector);
+	g_return_if_fail ( source != NULL);
+
+	icidata->client = auth_new_cal_from_source (source, icidata->source_type);
+	e_cal_open (icidata->client, FALSE, NULL);
+
+	switch (icidata->source_type) {
+	case E_CAL_SOURCE_TYPE_EVENT:
+		prepare_events (icidata->icalcomp, NULL);
+		if (!update_objects (icidata->client, icidata->icalcomp))
+			/* FIXME: e_error ... */;
+		break;
+	case E_CAL_SOURCE_TYPE_TODO:
+		prepare_tasks (icidata->icalcomp, NULL);
+		if (!update_objects (icidata->client, icidata->icalcomp))
+			/* FIXME: e_error ... */;
+		break;
+	default:
+		g_assert_not_reached ();
+	}
+	ical_import_done (icidata);
+}
+
+static gboolean
+update_objects (ECal *client, icalcomponent *icalcomp)
+{
+	icalcomponent_kind kind;
+	icalcomponent *vcal;
+	gboolean success = TRUE;
+
+	kind = icalcomponent_isa (icalcomp);
+
+	if (kind == ICAL_VTODO_COMPONENT || kind == ICAL_VEVENT_COMPONENT) {
+		vcal = e_cal_util_new_top_level ();
+		if (icalcomponent_get_method (icalcomp) == ICAL_METHOD_CANCEL)
+			icalcomponent_set_method (vcal, ICAL_METHOD_CANCEL);
+		else
+			icalcomponent_set_method (vcal, ICAL_METHOD_PUBLISH);
+		icalcomponent_add_component (vcal, icalcomponent_new_clone (icalcomp));
+	} else if (kind == ICAL_VCALENDAR_COMPONENT) {
+		vcal = icalcomponent_new_clone (icalcomp);
+		if (!icalcomponent_get_first_property (vcal, ICAL_METHOD_PROPERTY))
+			icalcomponent_set_method (vcal, ICAL_METHOD_PUBLISH);
+	} else
+		return FALSE;
+
+	if (!e_cal_receive_objects (client, vcal, NULL))
+		success = FALSE;
+
+	icalcomponent_free (vcal);
+
+	return success;
+}
+
+static void
+ical_import_done(ICalImporterData *icidata)
+{
+	g_object_unref (icidata->client);
+	icalcomponent_free (icidata->icalcomp);
+	gtk_signal_emit_by_name (GTK_DIALOG(icidata->window), "close");
+	g_free (icidata);
+}
+
+static icalcomponent *
+get_icalcomponent_from_file(char *filename)
+{
+	char *contents;
+	icalcomponent *icalcomp;
+
+	g_return_if_fail (filename != NULL);
+
+	if (!g_file_get_contents (filename, &contents, NULL, NULL)) {
+		g_free (filename);
+		return;
+	}
+	g_free (filename);
+
+	icalcomp = e_cal_util_parse_ics_string (contents);
+	g_free (contents);
+
+	if (icalcomp) {
+		return icalcomp;
+	}
+	return NULL;
+}
--- /dev/null	2006-01-03 09:06:01.188250250 +0530
+++ plugins/import-ics-attachments/Makefile.am	2005-10-06 16:59:14.000000000 +0530
@@ -0,0 +1,32 @@
+INCLUDES =						\
+	-I$(top_srcdir)\
+	-I$(top_srcdir)/camel                           \
+	-I$(top_srcdir)/widgets/misc			\
+	$(EVOLUTION_MAIL_CFLAGS)			\
+	-DEVOLUTION_DATADIR=\""$(datadir)"\"		\
+	-DEVOLUTION_PRIVDATADIR=\""$(privdatadir)"\"	\
+	-DEVOLUTION_GLADEDIR=\""$(gladedir)"\"		\
+	-DEVOLUTION_ETSPECDIR=\""$(etspecdir)"\"	\
+	-DEVOLUTION_ICONSDIR=\""$(imagesdir)"\"		\
+	-DEVOLUTION_IMAGES=\""$(imagesdir)"\"		\
+	-DEVOLUTION_GALVIEWSDIR=\""$(viewsdir)"\"	\
+	-DEVOLUTION_BUTTONSDIR=\""$(buttonsdir)"\"	\
+	-DEVOLUTION_LOCALEDIR=\""$(localedir)"\"	\
+	-DEVOLUTION_UIDIR=\""$(evolutionuidir)"\"	\
+	-DCAMEL_PROVIDERDIR=\""$(camel_providerdir)"\"	\
+	-DPLUGINDIR=\""$(plugindir)"\"			\
+	-DPREFIX=\""$(prefix)"\"			
+
+ EVO_PLUGIN_RULE@
+
+plugin_DATA = org-gnome-evolution-mail-attachments-import-ics.eplug
+plugin_LTLIBRARIES = liborg-gnome-evolution-mail-attachments-import-ics.la
+
+liborg_gnome_evolution_mail_attachments_import_ics_la_SOURCES = icsimporter.c
+liborg_gnome_evolution_mail_attachments_import_ics_la_LDFLAGS = -module -avoid-version $(NO_UNDEFINED)
+liborg_gnome_evolution_mail_attachments_import_ics_la_LIBADD = 			\
+	$(top_builddir)/e-util/libeutil.la		\
+	$(top_builddir)/mail/libevolution-mail.la	\
+	$(EVOLUTION_MAIL_LIBS)
+
+EXTRA_DIST = org-gnome-evolution-mail-attachments-import-ics.eplug.xml
--- /dev/null	2006-01-03 09:06:01.188250250 +0530
+++ plugins/import-ics-attachments/org-gnome-evolution-mail-attachments-import-ics.eplug.xml	2006-01-03 22:55:30.000000000 +0530
@@ -0,0 +1,26 @@
+<?xml version="1.0"?>
+<e-plugin-list>
+  <!-- the path to the shared library -->
+  <e-plugin
+    id="org.gnome.evolution.mail.attachments.import.ics"
+    type="shlib"
+    location="@PLUGINDIR@/liborg-gnome-evolution-mail-attachments-import-ics SOEXT@"
+    name="Import to Calendar">
+    
+    <author name="Johnny Jacob" email="johnnyjacob gmail com"/>
+    <description>Imports ICS attachments to calendar.</description>
+
+    	<hook class="org.gnome.evolution.mail.popup:1.0">
+		<menu id="org.gnome.evolution.mail.formathtmldisplay.popup" target="part" factory="org_gnome_evolution_import_ics_part">
+		</menu>
+	</hook>
+    	<hook class="org.gnome.evolution.mail.popup:1.0">
+		<menu id="org.gnome.evolution.mail.attachments.popup" target="attachments" factory="org_gnome_evolution_import_ics_attachments">
+		</menu>
+	</hook>
+	<hook class="org.gnome.evolution.mail.popup:1.0">
+		<menu target="attachments" id="org.gnome.evolution.mail.composer.attachmentbar.popup" factory="org_gnome_evolution_import_ics_attachments">
+		</menu>
+	</hook>
+  </e-plugin>
+</e-plugin-list>




[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]