[evolution-patches] Unified Attachment Bar Patch



Hi,

I have modified the code of composer and calendar to use single copy of attachment bar.

I have moved the widget part of bar to widgets/misc. I have left the pop-up menu handling with the    
respective callers.

I have attached 4 patches.

attachmentbar.diff (widgets/misc) New attachment bar
composer.diff - new composer part of the code using e-attachment-bar.
calendar.diff - new calendar part of the code using e-attachment-bar.
configure.diff - added libgnomevfsmodule-2.0 to E_WIDGETS_CFLAGS.

Please review and give your comments.

Thanks
Srini.
Index: Makefile.am
===================================================================
RCS file: /cvs/gnome/evolution/widgets/misc/Makefile.am,v
retrieving revision 1.65
diff -u -p -r1.65 Makefile.am
--- Makefile.am	23 Jun 2005 09:11:10 -0000	1.65
+++ Makefile.am	6 Jul 2005 10:53:41 -0000
@@ -27,7 +27,8 @@ pilot_headers =
 endif
 
 glade_DATA = e-send-options.glade \
-	     gal-categories.glade
+	     gal-categories.glade \
+	     e-attachment.glade
 
 libemiscwidgets_la_LDFLAGS = $(ICONV_LIBS)
 
@@ -35,6 +36,8 @@ libemiscwidgets_la_LDFLAGS = $(ICONV_LIB
 widgetsinclude_HEADERS =			\
 	$(pilot_headers)			\
 	e-activity-handler.h			\
+	e-attachment.h				\
+	e-attachment-bar.h			\
 	e-calendar.h				\
 	e-calendar-item.h			\
 	e-cell-date-edit.h			\
@@ -82,6 +85,8 @@ libemiscwidgets_la_SOURCES =			\
 	$(pilot_sources)			\
 	e-activity-handler.c			\
 	e-calendar.c				\
+	e-attachment.c				\
+	e-attachment-bar.c			\
 	e-calendar-item.c			\
 	e-cell-date-edit.c			\
 	e-cell-percent.c			\
--- /dev/null	2005-03-20 01:06:14.000000000 +0530
+++ e-attachment.h	2005-07-06 16:30:41.000000000 +0530
@@ -0,0 +1,94 @@
+/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
+/* e-attachment.h
+ *
+ * Copyright (C) 2005  Novell, Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2 of the GNU General Public
+ * published by the Free Software Foundation; either version 2 of the
+ * 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 Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Author: Ettore Perazzoli
+ * 	   Srinivasa Ragavan
+ */
+
+#ifndef __E_ATTACHMENT_H__
+#define __E_ATTACHMENT_H__
+
+#include <gdk-pixbuf/gdk-pixbuf.h>
+#include <glade/glade-xml.h>
+#include <camel/camel-mime-part.h>
+#include <camel/camel-exception.h>
+#include <libgnomevfs/gnome-vfs.h>
+
+#ifdef __cplusplus
+extern "C" {
+#pragma }
+#endif /* __cplusplus */
+
+#define E_TYPE_ATTACHMENT				(e_attachment_get_type ())
+#define E_ATTACHMENT(obj)				(G_TYPE_CHECK_INSTANCE_CAST ((obj), E_TYPE_ATTACHMENT, EAttachment))
+#define E_ATTACHMENT_CLASS(klass)			(G_TYPE_CHECK_CLASS_CAST ((klass), E_TYPE_ATTACHMENT, EAttachmentClass))
+#define E_IS_ATTACHMENT(obj)				(G_TYPE_CHECK_INSTANCE_TYPE ((obj), E_TYPE_ATTACHMENT))
+#define E_IS_ATTACHMENT_CLASS(klass)			(G_TYPE_CHECK_CLASS_TYPE ((obj), E_TYPE_ATTACHMENT))
+
+
+typedef struct _EAttachment       EAttachment;
+typedef struct _EAttachmentClass  EAttachmentClass;
+
+struct _EAttachment {
+	GObject parent;
+
+	GladeXML *editor_gui;
+
+	CamelMimePart *body;
+	gboolean guessed_type;
+	gulong size;
+
+	GdkPixbuf *pixbuf_cache;
+	
+	GnomeVFSAsyncHandle *handle;
+	gboolean is_available_local;
+	char *file_name;
+	char *description;
+	gboolean disposition;
+	int index;
+};
+
+struct _EAttachmentClass {
+	GObjectClass parent_class;
+
+	void (*changed)	(EAttachment *attachment);
+};
+
+GType e_attachment_get_type (void);
+EAttachment *e_attachment_new (const char *file_name,
+			       const char *disposition,
+			       CamelException *ex);
+EAttachment * e_attachment_new_remote_file (const char *file_name,
+			       		    const char *disposition,
+	  	   			    CamelException *ex);
+void e_attachment_build_remote_file (const char *filename,
+				     EAttachment *attachment,
+		 	   	     const char *disposition,
+				     CamelException *ex);
+EAttachment *e_attachment_new_from_mime_part (CamelMimePart *part);
+void e_attachment_edit (EAttachment *attachment,
+			GtkWidget *parent);
+				     
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* __E_ATTACHMENT_H__ */
--- /dev/null	2005-03-20 01:06:14.000000000 +0530
+++ e-attachment.c	2005-07-06 16:09:13.000000000 +0530
@@ -0,0 +1,636 @@
+/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
+/*
+ *  Authors: Ettore Perazzoli <ettore ximian com>
+ *           Jeffrey Stedfast <fejj ximian com>
+ *	     Srinivasa Ragavan <sragavan novell com>
+ *
+ *  Copyright 1999-2005 Novell, Inc. (www.novell.com)
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  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 <sys/stat.h>
+#include <string.h>
+#include <errno.h>
+
+#include <camel/camel.h>
+#include <gtk/gtk.h>
+#include <gtk/gtknotebook.h>
+#include <gtk/gtktogglebutton.h>
+#include <gtk/gtkdialog.h>
+#include <libgnomevfs/gnome-vfs-mime.h>
+#include <libgnome/gnome-i18n.h>
+
+#include "e-util/e-mktemp.h"
+
+#include "e-attachment.h"
+
+enum {
+	CHANGED,
+	LAST_SIGNAL
+};
+static guint signals[LAST_SIGNAL] = { 0 };
+
+static GObjectClass *parent_class = NULL;
+
+static void
+changed (EAttachment *attachment)
+{
+	g_signal_emit (attachment, signals[CHANGED], 0);
+}
+
+
+/* GtkObject methods.  */
+
+static void
+finalise(GObject *object)
+{
+	EAttachment *attachment;
+	
+	attachment = E_ATTACHMENT (object);
+
+	if (attachment->is_available_local) {
+		camel_object_unref (attachment->body);
+		if (attachment->pixbuf_cache != NULL)
+			g_object_unref (attachment->pixbuf_cache);
+	} else {
+		if (attachment->handle)
+			gnome_vfs_async_cancel(attachment->handle);
+		if (attachment->file_name)
+			g_free (attachment->file_name);
+		if (attachment->description)
+			g_free (attachment->description);
+	}
+
+	G_OBJECT_CLASS (parent_class)->finalize (object);
+}
+
+
+/* Signals.  */
+
+static void
+real_changed (EAttachment *attachment)
+{
+	g_return_if_fail (E_IS_ATTACHMENT (attachment));
+}
+
+
+static void
+class_init (EAttachmentClass *klass)
+{
+	GObjectClass *object_class;
+	
+	object_class = (GObjectClass*) klass;
+	parent_class = g_type_class_ref (G_TYPE_OBJECT);
+	
+	object_class->finalize = finalise;
+	klass->changed = real_changed;
+	
+	signals[CHANGED] = g_signal_new ("changed",
+					 E_TYPE_ATTACHMENT,
+					 G_SIGNAL_RUN_FIRST,
+					 G_STRUCT_OFFSET (EAttachmentClass, changed),
+					 NULL,
+					 NULL,
+					 g_cclosure_marshal_VOID__VOID,
+					 G_TYPE_NONE, 0);
+}
+
+static void
+init (EAttachment *attachment)
+{
+	attachment->editor_gui = NULL;
+	attachment->body = NULL;
+	attachment->size = 0;
+	attachment->pixbuf_cache = NULL;
+	attachment->index = -1;
+	attachment->file_name = NULL;
+	attachment->description = NULL;
+	attachment->disposition = FALSE;
+}
+
+GType
+e_attachment_get_type (void)
+{
+	static GType type = 0;
+	
+	if (type == 0) {
+		static const GTypeInfo info = {
+			sizeof (EAttachmentClass),
+			NULL,
+			NULL,
+			(GClassInitFunc) class_init,
+			NULL,
+			NULL,
+			sizeof (EAttachment),
+			0,
+			(GInstanceInitFunc) init,
+		};
+		
+		type = g_type_register_static (G_TYPE_OBJECT, "EAttachment", &info, 0);
+	}
+	
+	return type;
+}
+
+static char *
+attachment_guess_mime_type (const char *file_name)
+{
+	GnomeVFSFileInfo *info;
+	GnomeVFSResult result;
+	char *type = NULL;
+
+	info = gnome_vfs_file_info_new ();
+	result = gnome_vfs_get_file_info (file_name, info,
+					  GNOME_VFS_FILE_INFO_GET_MIME_TYPE |
+					  GNOME_VFS_FILE_INFO_FORCE_SLOW_MIME_TYPE |
+					  GNOME_VFS_FILE_INFO_FOLLOW_LINKS);
+	if (result == GNOME_VFS_OK)
+		type = g_strdup (gnome_vfs_file_info_get_mime_type (info));
+
+	gnome_vfs_file_info_unref (info);
+
+	return type;
+}
+
+
+/**
+ * e_attachment_new:
+ * @file_name: filename to attach
+ * @disposition: Content-Disposition of the attachment
+ * @ex: exception
+ *
+ * Return value: the new attachment, or %NULL on error
+ **/
+EAttachment *
+e_attachment_new (const char *file_name,
+			       const char *disposition,
+			       CamelException *ex)
+{
+	EAttachment *new;
+	CamelMimePart *part;
+	CamelDataWrapper *wrapper;
+	CamelStream *stream;
+	struct stat statbuf;
+	char *mime_type;
+	char *filename;
+	
+	g_return_val_if_fail (file_name != NULL, NULL);
+	
+	if (stat (file_name, &statbuf) < 0) {
+		camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM,
+				      _("Cannot attach file %s: %s"),
+				      file_name, g_strerror (errno));
+		return NULL;
+	}
+	
+	/* return if it's not a regular file */
+	if (!S_ISREG (statbuf.st_mode)) {
+		camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM,
+				      _("Cannot attach file %s: not a regular file"),
+				      file_name);
+		return NULL;
+	}
+	
+	stream = camel_stream_fs_new_with_name (file_name, O_RDONLY, 0);
+	if (!stream) {
+		camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM,
+				      _("Cannot attach file %s: %s"),
+				      file_name, g_strerror (errno));
+		return NULL;
+	}
+	
+	mime_type = attachment_guess_mime_type (file_name);
+	if (mime_type) {
+		if (!g_ascii_strcasecmp (mime_type, "message/rfc822")) {
+			wrapper = (CamelDataWrapper *) camel_mime_message_new ();
+		} else {
+			wrapper = camel_data_wrapper_new ();
+		}
+		
+		camel_data_wrapper_construct_from_stream (wrapper, stream);
+		camel_data_wrapper_set_mime_type (wrapper, mime_type);
+		g_free (mime_type);
+	} else {
+		wrapper = camel_data_wrapper_new ();
+		camel_data_wrapper_construct_from_stream (wrapper, stream);
+		camel_data_wrapper_set_mime_type (wrapper, "application/octet-stream");
+	}
+	
+	camel_object_unref (stream);
+	
+	part = camel_mime_part_new ();
+	camel_medium_set_content_object (CAMEL_MEDIUM (part), wrapper);
+	camel_object_unref (wrapper);
+	
+	camel_mime_part_set_disposition (part, disposition);
+	filename = g_path_get_basename (file_name);
+	camel_mime_part_set_filename (part, filename);
+	g_free (filename);
+	
+#if 0
+	/* Note: Outlook 2002 is broken with respect to Content-Ids on
+           non-multipart/related parts, so as an interoperability
+           workaround, don't set a Content-Id on these parts. Fixes
+           bug #10032 */
+	/* set the Content-Id */
+	content_id = camel_header_msgid_generate ();
+	camel_mime_part_set_content_id (part, content_id);
+	g_free (content_id);
+#endif
+	
+	new = g_object_new (E_TYPE_ATTACHMENT, NULL);
+	new->editor_gui = NULL;
+	new->body = part;
+	new->size = statbuf.st_size;
+	new->guessed_type = TRUE;
+	new->handle = NULL;
+	new->is_available_local = TRUE;
+	
+	return new;
+}
+
+
+EAttachment *
+e_attachment_new_remote_file (const char *file_name,
+			       		   const char *disposition,
+			       		   CamelException *ex)
+{
+	EAttachment *new;
+	
+	g_return_val_if_fail (file_name != NULL, NULL);
+	
+	new = g_object_new (E_TYPE_ATTACHMENT, NULL);
+	new->editor_gui = NULL;
+	new->body = NULL;
+	new->size = 0;
+	new->guessed_type = FALSE;
+	new->handle = NULL;
+	new->is_available_local = FALSE;
+	new->file_name = g_path_get_basename(file_name);
+	
+	return new;
+}
+
+void
+e_attachment_build_remote_file (const char *file_name,
+					     EAttachment *attachment,
+					     const char *disposition,
+					     CamelException *ex)
+{
+	CamelMimePart *part;
+	CamelDataWrapper *wrapper;
+	CamelStream *stream;
+	struct stat statbuf;
+	char *mime_type;
+	char *filename;
+	
+	g_return_if_fail (file_name != NULL);
+	
+	if (stat (file_name, &statbuf) < 0) {
+		camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM,
+				      _("Cannot attach file %s: %s"),
+				      file_name, g_strerror (errno));
+		return;
+	}
+	
+	/* return if it's not a regular file */
+	if (!S_ISREG (statbuf.st_mode)) {
+		camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM,
+				      _("Cannot attach file %s: not a regular file"),
+				      file_name);
+		return;
+	}
+	
+	stream = camel_stream_fs_new_with_name (file_name, O_RDONLY, 0);
+	if (!stream) {
+		camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM,
+				      _("Cannot attach file %s: %s"),
+				      file_name, g_strerror (errno));
+		return;
+	}
+	
+	mime_type = attachment_guess_mime_type (file_name);
+	if (mime_type) {
+		if (!g_ascii_strcasecmp (mime_type, "message/rfc822")) {
+			wrapper = (CamelDataWrapper *) camel_mime_message_new ();
+		} else {
+			wrapper = camel_data_wrapper_new ();
+		}
+		
+		camel_data_wrapper_construct_from_stream (wrapper, stream);
+		camel_data_wrapper_set_mime_type (wrapper, mime_type);
+		g_free (mime_type);
+	} else {
+		wrapper = camel_data_wrapper_new ();
+		camel_data_wrapper_construct_from_stream (wrapper, stream);
+		camel_data_wrapper_set_mime_type (wrapper, "application/octet-stream");
+	}
+	
+	camel_object_unref (stream);
+	
+	part = camel_mime_part_new ();
+	camel_medium_set_content_object (CAMEL_MEDIUM (part), wrapper);
+	camel_object_unref (wrapper);
+
+	if (attachment->disposition)
+		camel_mime_part_set_disposition (part, "inline");
+	else
+		camel_mime_part_set_disposition (part, "attachment");
+		
+	if (!attachment->file_name)
+		filename = g_path_get_basename (file_name);
+	else
+		filename = g_path_get_basename (attachment->file_name);
+		
+	camel_mime_part_set_filename (part, filename);
+	g_free (filename);
+
+	if (attachment->description) {
+		camel_mime_part_set_description (part, attachment->description);
+		g_free (attachment->description);
+		attachment->description = NULL;
+	}
+	
+	attachment->editor_gui = NULL;
+	attachment->body = part;
+	attachment->size = statbuf.st_size;
+	attachment->guessed_type = TRUE;
+	if (attachment->file_name) {
+		g_free (attachment->file_name);
+		attachment->file_name = NULL;
+	}
+}
+
+/**
+ * e_attachment_new_from_mime_part:
+ * @part: a CamelMimePart
+ * 
+ * Return value: a new EAttachment based on the mime part
+ **/
+EAttachment *
+e_attachment_new_from_mime_part (CamelMimePart *part)
+{
+	EAttachment *new;
+	CamelMimePart *mime_part;
+	CamelStream *stream;
+	
+	g_return_val_if_fail (CAMEL_IS_MIME_PART (part), NULL);
+	
+	stream = camel_stream_mem_new ();
+	if (camel_data_wrapper_write_to_stream (CAMEL_DATA_WRAPPER (part), stream) == -1) {
+		camel_object_unref (stream);
+		return NULL;
+	}
+	
+	camel_stream_reset (stream);
+	mime_part = camel_mime_part_new ();
+	
+	if (camel_data_wrapper_construct_from_stream (CAMEL_DATA_WRAPPER (mime_part), stream) == -1) {
+		camel_object_unref (mime_part);
+		camel_object_unref (stream);
+		return NULL;
+	}
+	
+	camel_object_unref (stream);
+	
+	new = g_object_new (E_TYPE_ATTACHMENT, NULL);
+	new->editor_gui = NULL;
+	new->body = mime_part;
+	new->guessed_type = FALSE;
+	new->is_available_local = TRUE;
+	new->size = 0;
+	
+	return new;
+}
+
+
+/* The attachment property dialog.  */
+
+typedef struct {
+	GtkWidget *dialog;
+	GtkEntry *file_name_entry;
+	GtkEntry *description_entry;
+	GtkEntry *mime_type_entry;
+	GtkToggleButton *disposition_checkbox;
+	EAttachment *attachment;
+} DialogData;
+
+static void
+destroy_dialog_data (DialogData *data)
+{
+	g_free (data);
+}
+
+/*
+ * fixme: I am converting EVERYTHING to/from UTF-8, although mime types
+ * are in ASCII. This is not strictly necessary, but we want to be
+ * consistent and possibly check for errors somewhere.
+ */
+
+static void
+set_entry (GladeXML *xml, const char *widget_name, const char *value)
+{
+	GtkEntry *entry;
+	
+	entry = GTK_ENTRY (glade_xml_get_widget (xml, widget_name));
+	if (entry == NULL)
+		g_warning ("Entry for `%s' not found.", widget_name);
+	else
+		gtk_entry_set_text (entry, value ? value : "");
+}
+
+static void
+connect_widget (GladeXML *gui, const char *name, const char *signal_name,
+		GCallback func, gpointer data)
+{
+	GtkWidget *widget;
+	
+	widget = glade_xml_get_widget (gui, name);
+	g_signal_connect (widget, signal_name, func, data);
+}
+
+static void
+close_cb (GtkWidget *widget, gpointer data)
+{
+	EAttachment *attachment;
+	DialogData *dialog_data;
+	
+	dialog_data = (DialogData *) data;
+	attachment = dialog_data->attachment;
+	
+	gtk_widget_destroy (dialog_data->dialog);
+	g_object_unref (attachment->editor_gui);
+	attachment->editor_gui = NULL;
+	
+	g_object_unref (attachment);
+	
+	destroy_dialog_data (dialog_data);
+}
+
+static void
+ok_cb (GtkWidget *widget, gpointer data)
+{
+	DialogData *dialog_data;
+	EAttachment *attachment;
+	const char *str;
+	
+	dialog_data = (DialogData *) data;
+	attachment = dialog_data->attachment;
+	
+	str = gtk_entry_get_text (dialog_data->file_name_entry);
+	if (attachment->is_available_local) {
+		camel_mime_part_set_filename (attachment->body, str);
+	} else {
+		if (attachment->file_name) 
+			g_free (attachment->file_name);	
+		attachment->file_name = g_strdup (str);
+	}
+	
+	str = gtk_entry_get_text (dialog_data->description_entry);
+	if (attachment->is_available_local) {
+		camel_mime_part_set_description (attachment->body, str);
+	} else {
+		if (attachment->description)
+			g_free (attachment->description);
+		attachment->description = g_strdup (str);
+	}
+	
+	str = gtk_entry_get_text (dialog_data->mime_type_entry);
+	if (attachment->is_available_local) {
+		camel_mime_part_set_content_type (attachment->body, str);
+		camel_data_wrapper_set_mime_type(camel_medium_get_content_object(CAMEL_MEDIUM (attachment->body)), str);
+	}
+
+	if (attachment->is_available_local) {
+		switch (gtk_toggle_button_get_active (dialog_data->disposition_checkbox)) {
+		case 0:
+			camel_mime_part_set_disposition (attachment->body, "attachment");
+			break;
+		case 1:
+			camel_mime_part_set_disposition (attachment->body, "inline");
+			break;
+		default:
+			/* Hmmmm? */
+			break;
+		}
+	} else {
+		attachment->disposition = gtk_toggle_button_get_active (dialog_data->disposition_checkbox);
+	}
+	
+	changed (attachment);
+	close_cb (widget, data);
+}
+
+static void
+response_cb (GtkWidget *widget, gint response, gpointer data)
+{
+	if (response == GTK_RESPONSE_OK)
+		ok_cb (widget, data);
+	else
+		close_cb (widget, data);
+}
+
+void
+e_attachment_edit (EAttachment *attachment, GtkWidget *parent)
+{
+	CamelContentType *content_type;
+	const char *disposition;
+	DialogData *dialog_data;
+	GladeXML *editor_gui;
+	char *type;
+	
+	g_return_if_fail (attachment != NULL);
+	g_return_if_fail (E_IS_ATTACHMENT (attachment));
+	
+	if (attachment->editor_gui != NULL) {
+		GtkWidget *window;
+		
+		window = glade_xml_get_widget (attachment->editor_gui,
+					       "dialog");
+		gdk_window_show (window->window);
+		return;
+	}
+	
+	editor_gui = glade_xml_new (EVOLUTION_GLADEDIR "/e-attachment.glade",
+				    NULL, NULL);
+	if (editor_gui == NULL) {
+		g_warning ("Cannot load `e-attachment.glade'");
+		return;
+	}
+	
+	attachment->editor_gui = editor_gui;
+	
+	gtk_window_set_transient_for
+		(GTK_WINDOW (glade_xml_get_widget (editor_gui, "dialog")),
+		 GTK_WINDOW (gtk_widget_get_toplevel (parent)));
+	
+	dialog_data = g_new (DialogData, 1);
+	g_object_ref (attachment);
+	dialog_data->attachment = attachment;
+	dialog_data->dialog = glade_xml_get_widget (editor_gui, "dialog");
+	dialog_data->file_name_entry = GTK_ENTRY (
+		glade_xml_get_widget (editor_gui, "file_name_entry"));
+	dialog_data->description_entry = GTK_ENTRY (
+		glade_xml_get_widget (editor_gui, "description_entry"));
+	dialog_data->mime_type_entry = GTK_ENTRY (
+		glade_xml_get_widget (editor_gui, "mime_type_entry"));
+	dialog_data->disposition_checkbox = GTK_TOGGLE_BUTTON (
+		glade_xml_get_widget (editor_gui, "disposition_checkbox"));
+
+	if (attachment->is_available_local)	{
+		set_entry (editor_gui, "file_name_entry",
+			   camel_mime_part_get_filename (attachment->body));
+		set_entry (editor_gui, "description_entry",
+			   camel_mime_part_get_description (attachment->body));
+		content_type = camel_mime_part_get_content_type (attachment->body);
+		type = camel_content_type_simple (content_type);
+		set_entry (editor_gui, "mime_type_entry", type);
+		g_free (type);
+	
+		disposition = camel_mime_part_get_disposition (attachment->body);
+		gtk_toggle_button_set_active (dialog_data->disposition_checkbox,
+					      disposition && !g_ascii_strcasecmp (disposition, "inline"));
+	} else {
+		set_entry (editor_gui, "file_name_entry",
+			   attachment->file_name);
+		set_entry (editor_gui, "description_entry",
+			   attachment->description);
+		type = attachment_guess_mime_type (attachment->file_name);
+		if (type) {
+			set_entry (editor_gui, "mime_type_entry", type);
+			g_free (type);
+		} else {
+			set_entry (editor_gui, "mime_type_entry", "");
+		}
+	
+		gtk_toggle_button_set_active (dialog_data->disposition_checkbox, attachment->disposition);
+		
+	}
+	
+	connect_widget (editor_gui, "dialog", "response", (GCallback)response_cb, dialog_data);
+#warning "signal connect while alive"	
+	/* make sure that when the parent gets hidden/closed that our windows also close */
+	parent = gtk_widget_get_toplevel (parent);
+	gtk_signal_connect_while_alive (GTK_OBJECT (parent), "destroy", (GCallback)close_cb, dialog_data,
+					GTK_OBJECT (dialog_data->dialog));
+	gtk_signal_connect_while_alive (GTK_OBJECT (parent), "hide", (GCallback)close_cb, dialog_data,
+					GTK_OBJECT (dialog_data->dialog));
+}
--- /dev/null	2005-03-20 01:06:14.000000000 +0530
+++ e-attachment-bar.h	2005-07-06 16:13:43.000000000 +0530
@@ -0,0 +1,85 @@
+/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
+/* e-attachment-bar.h
+ *
+ * Copyright (C) 2005  Novell, Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2 of the GNU General Public
+ * published by the Free Software Foundation; either version 2 of the
+ * 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 Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Author: Ettore Perazzoli
+ * 	   Srinivasa Ragavan
+ */
+
+#ifndef __E_ATTACHMENT_BAR_H__
+#define __E_ATTACHMENT_BAR_H__
+
+#include <libgnomeui/gnome-icon-list.h>
+
+#include <camel/camel-multipart.h>
+
+#ifdef __cplusplus
+extern "C" {
+#pragma }
+#endif /* __cplusplus */
+
+#define E_TYPE_ATTACHMENT_BAR \
+	(e_attachment_bar_get_type ())
+#define E_ATTACHMENT_BAR(obj) \
+	(G_TYPE_CHECK_INSTANCE_CAST ((obj), E_TYPE_ATTACHMENT_BAR, EAttachmentBar))
+#define E_ATTACHMENT_BAR_CLASS(klass) \
+	(G_TYPE_CHECK_CLASS_CAST ((klass), E_TYPE_ATTACHMENT_BAR, EAttachmentBarClass))
+#define E_IS_ATTACHMENT_BAR(obj) \
+	(G_TYPE_CHECK_INSTANCE_TYPE ((obj), E_TYPE_ATTACHMENT_BAR))
+#define E_IS_ATTACHMENT_BAR_CLASS(klass) \
+	(G_TYPE_CHECK_CLASS_TYPE ((obj), E_TYPE_ATTACHMENT_BAR))
+
+typedef struct _EAttachmentBar EAttachmentBar;
+typedef struct _EAttachmentBarClass EAttachmentBarClass;
+typedef struct _EAttachmentBarPrivate EAttachmentBarPrivate;
+
+struct _EAttachmentBar {
+	GnomeIconList parent;
+	
+	EAttachmentBarPrivate *priv;
+};
+
+struct _EAttachmentBarClass {
+	GnomeIconListClass parent_class;
+	
+	void (* changed) (EAttachmentBar *bar);
+};
+
+
+GtkType e_attachment_bar_get_type (void);
+
+GtkWidget *e_attachment_bar_new (GtkAdjustment *adj);
+void e_attachment_bar_to_multipart (EAttachmentBar *bar, CamelMultipart *multipart,
+						 const char *default_charset);
+guint e_attachment_bar_get_num_attachments (EAttachmentBar *bar);
+void e_attachment_bar_attach (EAttachmentBar *bar, const char *file_name, char *disposition);
+void e_attachment_bar_attach_mime_part (EAttachmentBar *bar, CamelMimePart *part);
+int e_attachment_bar_get_download_count (EAttachmentBar *bar);
+void e_attachment_bar_attach_remote_file (EAttachmentBar *bar,const gchar *url);
+GSList *e_attachment_bar_get_attachment (EAttachmentBar *bar, int id);
+void e_attachment_bar_edit_selected (EAttachmentBar *bar);
+void e_attachment_bar_remove_selected (EAttachmentBar *bar);
+GtkWidget ** e_attachment_bar_get_selector(EAttachmentBar *bar);
+GSList *e_attachment_bar_get_attachment_part_list (EAttachmentBar *bar);
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* __E_ATTACHMENT_BAR_H__ */
--- /dev/null	2005-03-20 01:06:14.000000000 +0530
+++ e-attachment-bar.c	2005-07-06 16:10:44.000000000 +0530
@@ -0,0 +1,897 @@
+/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
+/*
+ *  Authors: Ettore Perazzoli <ettore ximian com>
+ *           Jeffrey Stedfast <fejj ximian com>
+ *	     Srinivasa Ragavan <sragavan novell com>
+ *
+ *  Copyright 1999-2005 Novell, Inc. (www.novell.com)
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  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 <gtk/gtk.h>
+#include <glade/glade.h>
+#include <gconf/gconf.h>
+#include <gconf/gconf-client.h>
+#include <gdk/gdkkeysyms.h>
+#include <libgnomevfs/gnome-vfs-mime-handlers.h>
+#include <libgnome/gnome-i18n.h>
+
+#include "e-attachment.h"
+#include "e-attachment-bar.h"
+
+#include <libedataserver/e-iconv.h>
+
+#include <camel/camel-data-wrapper.h>
+#include <camel/camel-mime-message.h>
+#include <camel/camel-stream-fs.h>
+#include <camel/camel-stream-null.h>
+#include <camel/camel-stream-mem.h>
+#include <camel/camel-stream-filter.h>
+#include <camel/camel-mime-filter-bestenc.h>
+#include <camel/camel-mime-part.h>
+
+#include "e-util/e-gui-utils.h"
+#include "e-util/e-icon-factory.h"
+#include "e-util/e-error.h"
+#include "e-util/e-mktemp.h"
+
+#define ICON_WIDTH 64
+#define ICON_SEPARATORS " /-_"
+#define ICON_SPACING 2
+#define ICON_ROW_SPACING ICON_SPACING
+#define ICON_COL_SPACING ICON_SPACING
+#define ICON_BORDER 2
+#define ICON_TEXT_SPACING 2
+
+
+static GnomeIconListClass *parent_class = NULL;
+
+struct _EAttachmentBarPrivate {
+	GtkWidget *attach;	/* attachment file dialogue, if active */
+
+	GList *attachments;
+	guint num_attachments;
+	gchar *path;
+};
+
+
+enum {
+	CHANGED,
+	LAST_SIGNAL
+};
+
+static guint signals[LAST_SIGNAL] = { 0 };
+
+
+static void update (EAttachmentBar *bar);
+
+
+static char *
+size_to_string (gulong size)
+{
+	char *size_string;
+	
+	/* FIXME: The following should probably go into a separate module, as
+           we might have to do the same thing in other places as well.  Also,
+	   I am not sure this will be OK for all the languages.  */
+	
+	if (size < 1e3L) {
+		size_string = NULL;
+	} else {
+		gdouble displayed_size;
+		
+		if (size < 1e6L) {
+			displayed_size = (gdouble) size / 1.0e3;
+			size_string = g_strdup_printf (_("%.0fK"), displayed_size);
+		} else if (size < 1e9L) {
+			displayed_size = (gdouble) size / 1.0e6;
+			size_string = g_strdup_printf (_("%.0fM"), displayed_size);
+		} else {
+			displayed_size = (gdouble) size / 1.0e9;
+			size_string = g_strdup_printf (_("%.0fG"), displayed_size);
+		}
+	}
+	
+	return size_string;
+}
+
+/* Attachment handling functions.  */
+
+static void
+free_attachment_list (EAttachmentBar *bar)
+{
+	EAttachmentBarPrivate *priv;
+	GList *p;
+	
+	priv = bar->priv;
+	
+	for (p = priv->attachments; p != NULL; p = p->next)
+		g_object_unref (p->data);
+	
+	priv->attachments = NULL;
+}
+
+static void
+attachment_changed_cb (EAttachment *attachment,
+		       gpointer data)
+{
+	update (E_ATTACHMENT_BAR (data));
+}
+
+static void
+add_common (EAttachmentBar *bar,
+	    EAttachment *attachment)
+{
+	g_return_if_fail (attachment != NULL);
+	
+	g_signal_connect (attachment, "changed",
+			  G_CALLBACK (attachment_changed_cb),
+			  bar);
+	
+	bar->priv->attachments = g_list_append (bar->priv->attachments,
+						attachment);
+	bar->priv->num_attachments++;
+	
+	update (bar);
+	
+	g_signal_emit (bar, signals[CHANGED], 0);
+}
+
+static void
+add_from_mime_part (EAttachmentBar *bar,
+		    CamelMimePart *part)
+{
+	add_common (bar, e_attachment_new_from_mime_part (part));
+}
+
+static void
+add_from_file (EAttachmentBar *bar,
+	       const char *file_name,
+	       const char *disposition)
+{
+	EAttachment *attachment;
+	CamelException ex;
+	
+	camel_exception_init (&ex);
+	attachment = e_attachment_new (file_name, disposition, &ex);
+	if (attachment) {
+		add_common (bar, attachment);
+	} else {
+		/* FIXME: Avoid using error from mailer */
+		e_error_run((GtkWindow *)gtk_widget_get_toplevel((GtkWidget *)bar), "mail-composer:no-attach",
+			    file_name, camel_exception_get_description(&ex), NULL);
+		camel_exception_clear (&ex);
+	}
+}
+
+static void
+remove_attachment (EAttachmentBar *bar,
+		   EAttachment *attachment)
+{
+	g_return_if_fail (E_IS_ATTACHMENT_BAR (bar));
+	g_return_if_fail (g_list_find (bar->priv->attachments, attachment) != NULL);
+
+	bar->priv->attachments = g_list_remove (bar->priv->attachments,
+						attachment);
+	bar->priv->num_attachments--;
+	if (attachment->editor_gui != NULL) {
+		GtkWidget *dialog = glade_xml_get_widget (attachment->editor_gui, "dialog");
+		g_signal_emit_by_name (dialog, "response", GTK_RESPONSE_CLOSE);
+	}
+	
+	g_object_unref(attachment);
+	
+	g_signal_emit (bar, signals[CHANGED], 0);
+}
+
+
+/* Icon list contents handling.  */
+
+static void
+update (EAttachmentBar *bar)
+{
+	EAttachmentBarPrivate *priv;
+	GnomeIconList *icon_list;
+	GList *p;
+	
+	priv = bar->priv;
+	icon_list = GNOME_ICON_LIST (bar);
+	
+	gnome_icon_list_freeze (icon_list);
+	
+	gnome_icon_list_clear (icon_list);
+	
+	/* FIXME could be faster, but we don't care.  */
+	for (p = priv->attachments; p != NULL; p = p->next) {
+		EAttachment *attachment;
+		CamelContentType *content_type;
+		char *size_string, *label;
+		GdkPixbuf *pixbuf=NULL;
+		const char *desc;
+		
+		attachment = p->data;
+
+		if (!attachment->is_available_local) {
+			/* stock_attach would be better, but its fugly scaled up */
+			pixbuf = e_icon_factory_get_icon("stock_unknown", E_ICON_SIZE_DIALOG);
+			if (pixbuf) {
+				attachment->index = gnome_icon_list_append_pixbuf (icon_list, pixbuf, NULL, "");
+				g_object_unref(pixbuf);
+			}
+			continue;
+		}
+		content_type = camel_mime_part_get_content_type (attachment->body);
+		/* Get the image out of the attachment 
+		   and create a thumbnail for it */
+		pixbuf = attachment->pixbuf_cache;
+		if (pixbuf) {
+			g_object_ref(pixbuf);
+		} else if (camel_content_type_is(content_type, "image", "*")) {
+			CamelDataWrapper *wrapper;
+			CamelStreamMem *mstream;
+			GdkPixbufLoader *loader;
+			gboolean error = TRUE;
+			
+			wrapper = camel_medium_get_content_object (CAMEL_MEDIUM (attachment->body));
+			mstream = (CamelStreamMem *) camel_stream_mem_new ();
+			
+			camel_data_wrapper_decode_to_stream (wrapper, (CamelStream *) mstream);
+			
+			/* Stream image into pixbuf loader */
+			loader = gdk_pixbuf_loader_new ();
+			error = !gdk_pixbuf_loader_write (loader, mstream->buffer->data, mstream->buffer->len, NULL);
+			gdk_pixbuf_loader_close (loader, NULL);
+			
+			if (!error) {
+				int ratio, width, height;
+				
+				/* Shrink pixbuf */
+				pixbuf = gdk_pixbuf_loader_get_pixbuf (loader);
+				width = gdk_pixbuf_get_width (pixbuf);
+				height = gdk_pixbuf_get_height (pixbuf);
+				if (width >= height) {
+					if (width > 48) {
+						ratio = width / 48;
+						width = 48;
+						height = height / ratio;
+					}
+				} else {
+					if (height > 48) {
+						ratio = height / 48;
+						height = 48;
+						width = width / ratio;
+					}
+				}
+				
+				attachment->pixbuf_cache = gdk_pixbuf_scale_simple 
+					(pixbuf,
+					 width,
+					 height,
+					 GDK_INTERP_BILINEAR);
+				pixbuf = attachment->pixbuf_cache;
+				g_object_ref(pixbuf);
+			} else {
+				pixbuf = NULL;
+				g_warning ("GdkPixbufLoader Error");
+			}
+			
+			/* Destroy everything */
+			g_object_unref (loader);
+			camel_object_unref (mstream);
+		}
+		
+		desc = camel_mime_part_get_description (attachment->body);
+		if (!desc || *desc == '\0')
+			desc = camel_mime_part_get_filename (attachment->body);
+		
+		if (!desc)
+			desc = _("attachment");
+		
+		if (attachment->size
+		    && (size_string = size_to_string (attachment->size))) {
+			label = g_strdup_printf ("%s (%s)", desc, size_string);
+			g_free (size_string);
+		} else
+			label = g_strdup (desc);
+		
+		if (pixbuf == NULL) {
+			char *mime_type;
+			
+			mime_type = camel_content_type_simple (content_type);
+			pixbuf = e_icon_for_mime_type (mime_type, 48);
+			if (pixbuf == NULL) {
+				g_warning("cannot find icon for mime type %s (installation problem?)", mime_type);
+				/* stock_attach would be better, but its fugly scaled up */
+				pixbuf = e_icon_factory_get_icon("stock_unknown", E_ICON_SIZE_DIALOG);
+			}
+			g_free (mime_type);
+		}
+
+		if (pixbuf) {
+			gnome_icon_list_append_pixbuf (icon_list, pixbuf, NULL, label);
+			g_object_unref(pixbuf);
+		}
+		
+		g_free (label);
+	}
+	
+	gnome_icon_list_thaw (icon_list);
+}
+
+static void
+update_remote_file (EAttachmentBar *bar, EAttachment *attachment, char *msg)
+{
+	EAttachmentBarPrivate *priv;
+	GnomeIconList *icon_list;
+	GnomeIconTextItem *item;
+	
+	priv = bar->priv;
+	icon_list = GNOME_ICON_LIST (bar);
+	
+	gnome_icon_list_freeze (icon_list);
+
+	item = gnome_icon_list_get_icon_text_item (icon_list, attachment->index);
+	if (!item->is_text_allocated)
+		g_free (item->text);
+		
+	gnome_icon_text_item_configure (item, item->x, item->y, item->width, item->fontname, msg, item->is_editable, TRUE);
+
+	gnome_icon_list_thaw (icon_list);
+}
+
+void
+e_attachment_bar_remove_selected (EAttachmentBar *bar)
+{
+	GnomeIconList *icon_list;
+	EAttachment *attachment;
+	GList *attachment_list, *p;
+	int num = 0, left, dlen;
+	
+	icon_list = GNOME_ICON_LIST (bar);
+	
+	/* Weee!  I am especially proud of this piece of cheesy code: it is
+           truly awful.  But unless one attaches a huge number of files, it
+           will not be as greedy as intended.  FIXME of course.  */
+	
+	attachment_list = NULL;
+	p = gnome_icon_list_get_selection (icon_list);
+	dlen = g_list_length (p);
+	for ( ; p != NULL; p = p->next) {
+		num = GPOINTER_TO_INT (p->data);
+		attachment = E_ATTACHMENT (g_list_nth_data (bar->priv->attachments, num));
+
+		/* We need to check if there are duplicated index in the return list of 
+		   gnome_icon_list_get_selection() because of gnome bugzilla bug #122356.
+		   FIXME in the future. */
+
+		if (g_list_find (attachment_list, attachment) == NULL) {
+			attachment_list = g_list_prepend (attachment_list, attachment);
+		}
+	}
+	
+	for (p = attachment_list; p != NULL; p = p->next)
+		remove_attachment (bar, E_ATTACHMENT (p->data));
+	
+	g_list_free (attachment_list);
+	
+	update (bar);
+	
+	left = gnome_icon_list_get_num_icons (icon_list);
+	num = num - dlen + 1;
+	if (left > 0)
+		gnome_icon_list_focus_icon (icon_list, left > num ? num : left - 1);
+}
+
+void
+e_attachment_bar_edit_selected (EAttachmentBar *bar)
+{
+	GnomeIconList *icon_list;
+	GList *selection, *attach;
+	int num;
+	
+	icon_list = GNOME_ICON_LIST (bar);
+	
+	selection = gnome_icon_list_get_selection (icon_list);
+	if (selection) {
+		num = GPOINTER_TO_INT (selection->data);
+		attach = g_list_nth (bar->priv->attachments, num);
+		if (attach)
+			e_attachment_edit ((EAttachment *)attach->data, GTK_WIDGET (bar));
+	}
+}
+
+GtkWidget **
+e_attachment_bar_get_selector(EAttachmentBar *bar)
+{
+	return &bar->priv->attach;
+}
+
+/* if id != -1, then use it as an index for target of the popup */
+GSList *
+e_attachment_bar_get_attachment (EAttachmentBar *bar, int id)
+{
+	GSList *attachments = NULL;
+	GList *p;
+	EAttachment *attachment;
+
+	/* We need to check if there are duplicated index in the return list of 
+	   gnome_icon_list_get_selection() because of gnome bugzilla bug #122356.
+	   FIXME in the future. */
+
+	if (id == -1
+	    || (attachment = g_list_nth_data(bar->priv->attachments, id)) == NULL) {
+		p = gnome_icon_list_get_selection((GnomeIconList *)bar);
+		for ( ; p != NULL; p = p->next) {
+			int num = GPOINTER_TO_INT(p->data);
+			EAttachment *attachment = g_list_nth_data(bar->priv->attachments, num);
+			
+			if (attachment && g_slist_find(attachments, attachment) == NULL) {
+				g_object_ref(attachment);
+				attachments = g_slist_prepend(attachments, attachment);
+			}
+		}
+		attachments = g_slist_reverse(attachments);
+	} else {
+		g_object_ref(attachment);
+		attachments = g_slist_prepend(attachments, attachment);
+	}
+	
+	return attachments;
+}
+
+/* Just the GSList has to be freed by the caller */
+GSList *
+e_attachment_bar_get_attachment_part_list (EAttachmentBar *bar)
+{
+        EAttachment *attachment;
+        GList *p = NULL, *part_list = NULL;
+
+        for ( p = bar->priv->attachments; p!= NULL; p = p->next) {
+                attachment = p->data;
+
+                if (attachment && attachment->is_available_local) {
+                        part_list = g_slist_prepend(part_list, attachment->body);
+                }
+        }
+        return part_list;
+}
+
+/* GtkObject methods.  */
+
+static void
+destroy (GtkObject *object)
+{
+	EAttachmentBar *bar;
+	
+	bar = E_ATTACHMENT_BAR (object);
+	
+	if (bar->priv) {
+		free_attachment_list (bar);
+
+		if (bar->priv->attach)
+			gtk_widget_destroy(bar->priv->attach);
+
+		if (bar->priv->path)
+			g_free (bar->priv->path);
+
+		g_free (bar->priv);
+		bar->priv = NULL;
+	}
+	
+	if (GTK_OBJECT_CLASS (parent_class)->destroy != NULL)
+		(* GTK_OBJECT_CLASS (parent_class)->destroy) (object);
+}
+
+/* Initialization.  */
+
+static void
+class_init (EAttachmentBarClass *klass)
+{
+	GtkObjectClass *object_class;
+	GtkWidgetClass *widget_class;
+	GnomeIconListClass *icon_list_class;
+	
+	object_class = GTK_OBJECT_CLASS (klass);
+	widget_class = GTK_WIDGET_CLASS (klass);
+	icon_list_class = GNOME_ICON_LIST_CLASS (klass);
+	
+	parent_class = g_type_class_ref (gnome_icon_list_get_type ());
+	
+	object_class->destroy = destroy;
+	
+	/* Setup signals.  */
+	
+	signals[CHANGED] =
+		g_signal_new ("changed",
+			      E_TYPE_ATTACHMENT_BAR,
+			      G_SIGNAL_RUN_LAST,
+			      G_STRUCT_OFFSET (EAttachmentBarClass, changed),
+			      NULL, NULL,
+			      g_cclosure_marshal_VOID__VOID,
+			      G_TYPE_NONE, 0);
+}
+
+static void
+init (EAttachmentBar *bar)
+{
+	EAttachmentBarPrivate *priv;
+	
+	priv = g_new (EAttachmentBarPrivate, 1);
+	
+	priv->attach = NULL;
+	priv->attachments = NULL;
+	priv->num_attachments = 0;
+	priv->path = NULL;
+	
+	bar->priv = priv;
+}
+
+
+GType
+e_attachment_bar_get_type (void)
+{
+	static GType type = 0;
+	
+	if (type == 0) {
+		static const GTypeInfo info = {
+			sizeof (EAttachmentBarClass),
+			NULL, NULL,
+			(GClassInitFunc) class_init,
+			NULL, NULL,
+			sizeof (EAttachmentBar),
+			0,
+			(GInstanceInitFunc) init,
+		};
+		
+		type = g_type_register_static (GNOME_TYPE_ICON_LIST, "EAttachmentBar", &info, 0);
+	}
+	
+	return type;
+}
+
+GtkWidget *
+e_attachment_bar_new (GtkAdjustment *adj)
+{
+	EAttachmentBar *new;
+	GnomeIconList *icon_list;
+	int width, height, icon_width, window_height;
+	PangoFontMetrics *metrics;
+	PangoContext *context;
+	
+	new = g_object_new (e_attachment_bar_get_type (), NULL);
+	
+	icon_list = GNOME_ICON_LIST (new);
+	
+	context = gtk_widget_get_pango_context ((GtkWidget *) new);
+	metrics = pango_context_get_metrics (context, ((GtkWidget *) new)->style->font_desc, pango_context_get_language (context));
+	width = PANGO_PIXELS (pango_font_metrics_get_approximate_char_width (metrics)) * 15;
+	/* This should be *2, but the icon list creates too much space above ... */
+	height = PANGO_PIXELS (pango_font_metrics_get_ascent (metrics) + pango_font_metrics_get_descent (metrics)) * 3;
+	pango_font_metrics_unref (metrics);
+	
+	icon_width = ICON_WIDTH + ICON_SPACING + ICON_BORDER + ICON_TEXT_SPACING;
+	icon_width = MAX (icon_width, width);
+	
+	gnome_icon_list_construct (icon_list, icon_width, adj, 0);
+	
+	window_height = ICON_WIDTH + ICON_SPACING + ICON_BORDER + ICON_TEXT_SPACING + height;
+	gtk_widget_set_size_request (GTK_WIDGET (new), icon_width * 4, window_height);
+	
+	gnome_icon_list_set_separators (icon_list, ICON_SEPARATORS);
+	gnome_icon_list_set_row_spacing (icon_list, ICON_ROW_SPACING);
+	gnome_icon_list_set_col_spacing (icon_list, ICON_COL_SPACING);
+	gnome_icon_list_set_icon_border (icon_list, ICON_BORDER);
+	gnome_icon_list_set_text_spacing (icon_list, ICON_TEXT_SPACING);
+	gnome_icon_list_set_selection_mode (icon_list, GTK_SELECTION_MULTIPLE);
+
+	atk_object_set_name (gtk_widget_get_accessible (GTK_WIDGET (new)), 
+			_("Attachment Bar"));
+	
+	return GTK_WIDGET (new);
+}
+
+static char *
+get_default_charset (void)
+{
+	GConfClient *gconf;
+	const char *locale;
+	char *charset;
+	
+	gconf = gconf_client_get_default ();
+	charset = gconf_client_get_string (gconf, "/apps/evolution/mail/composer/charset", NULL);
+	
+	if (!charset || charset[0] == '\0') {
+		g_free (charset);
+		charset = gconf_client_get_string (gconf, "/apps/evolution/mail/format/charset", NULL);
+		if (charset && charset[0] == '\0') {
+			g_free (charset);
+			charset = NULL;
+		}
+	}
+	
+	g_object_unref (gconf);
+	
+	if (!charset && (locale = e_iconv_locale_charset ()))
+		charset = g_strdup (locale);
+	
+	return charset ? charset : g_strdup ("us-ascii");
+}
+
+static void
+attach_to_multipart (CamelMultipart *multipart,
+		     EAttachment *attachment,
+		     const char *default_charset)
+{
+	CamelContentType *content_type;
+	CamelDataWrapper *content;
+	
+	content_type = camel_mime_part_get_content_type (attachment->body);
+	content = camel_medium_get_content_object (CAMEL_MEDIUM (attachment->body));
+	
+	if (!CAMEL_IS_MULTIPART (content)) {
+		if (camel_content_type_is (content_type, "text", "*")) {
+			CamelTransferEncoding encoding;
+			CamelStreamFilter *filter_stream;
+			CamelMimeFilterBestenc *bestenc;
+			CamelStream *stream;
+			const char *charset;
+			char *buf = NULL;
+			char *type;
+			
+			charset = camel_content_type_param (content_type, "charset");
+			
+			stream = camel_stream_null_new ();
+			filter_stream = camel_stream_filter_new_with_stream (stream);
+			bestenc = camel_mime_filter_bestenc_new (CAMEL_BESTENC_GET_ENCODING);
+			camel_stream_filter_add (filter_stream, CAMEL_MIME_FILTER (bestenc));
+			camel_object_unref (stream);
+			
+			camel_data_wrapper_decode_to_stream (content, CAMEL_STREAM (filter_stream));
+			camel_object_unref (filter_stream);
+			
+			encoding = camel_mime_filter_bestenc_get_best_encoding (bestenc, CAMEL_BESTENC_8BIT);
+			camel_mime_part_set_encoding (attachment->body, encoding);
+			
+			if (encoding == CAMEL_TRANSFER_ENCODING_7BIT) {
+				/* the text fits within us-ascii so this is safe */
+				/* FIXME: check that this isn't iso-2022-jp? */
+				default_charset = "us-ascii";
+			} else if (!charset) {
+				if (!default_charset)
+					default_charset = buf = get_default_charset ();
+				
+				/* FIXME: We should really check that this fits within the
+                                   default_charset and if not find one that does and/or
+				   allow the user to specify? */
+			}
+			
+			if (!charset) {
+				/* looks kinda nasty, but this is how ya have to do it */
+				camel_content_type_set_param (content_type, "charset", default_charset);
+				type = camel_content_type_format (content_type);
+				camel_mime_part_set_content_type (attachment->body, type);
+				g_free (type);
+				g_free (buf);
+			}
+			
+			camel_object_unref (bestenc);
+		} else if (!CAMEL_IS_MIME_MESSAGE (content)) {
+			camel_mime_part_set_encoding (attachment->body, CAMEL_TRANSFER_ENCODING_BASE64);
+		}
+	}
+	
+	camel_multipart_add_part (multipart, attachment->body);
+}
+
+void
+e_attachment_bar_to_multipart (EAttachmentBar *bar,
+			       CamelMultipart *multipart,
+			       const char *default_charset)
+{
+	EAttachmentBarPrivate *priv;
+	GList *p;
+	
+	g_return_if_fail (E_IS_ATTACHMENT_BAR (bar));
+	g_return_if_fail (CAMEL_IS_MULTIPART (multipart));
+	
+	priv = bar->priv;
+	
+	for (p = priv->attachments; p != NULL; p = p->next) {
+		EAttachment *attachment;
+		
+		attachment = E_ATTACHMENT (p->data);
+		if (attachment->is_available_local)
+			attach_to_multipart (multipart, attachment, default_charset);
+	}
+}
+
+
+guint
+e_attachment_bar_get_num_attachments (EAttachmentBar *bar)
+{
+	g_return_val_if_fail (bar != NULL, 0);
+	g_return_val_if_fail (E_IS_ATTACHMENT_BAR (bar), 0);
+	
+	return bar->priv->num_attachments;
+}
+
+
+void
+e_attachment_bar_attach (EAttachmentBar *bar,
+			 const gchar *file_name,
+			 char *disposition)
+{
+	g_return_if_fail (E_IS_ATTACHMENT_BAR (bar));
+	g_return_if_fail ( file_name != NULL && disposition != NULL);
+	
+	add_from_file (bar, file_name, disposition);
+}
+
+typedef struct DownloadInfo {
+	EAttachment *attachment;
+	EAttachmentBar *bar;
+	gchar *file_name;
+}DownloadInfo;
+
+static int
+async_progress_update_cb (GnomeVFSAsyncHandle      *handle,
+			  GnomeVFSXferProgressInfo *info,
+			  DownloadInfo *download_info)
+{
+	int percent=0;
+	switch (info->status) {
+	case GNOME_VFS_XFER_PROGRESS_STATUS_OK:
+	{
+		gchar *base_path =  g_path_get_basename(download_info->attachment->file_name);
+		if (info->file_size) {
+			percent = info->bytes_copied*100/info->file_size;
+			update_remote_file (download_info->bar, 
+					    download_info->attachment, 
+					    g_strdup_printf("%s (%d\%)", base_path, percent));
+		} else {
+			update_remote_file (download_info->bar, 
+					    download_info->attachment, 
+					    g_strdup_printf("%s (%d\%)", base_path, percent));	
+		}
+		g_free (base_path);
+		
+		if (info->phase == GNOME_VFS_XFER_PHASE_COMPLETED) {
+			CamelException ex;
+			
+			download_info->attachment->is_available_local = TRUE;
+			download_info->attachment->handle = NULL;
+			camel_exception_init (&ex);
+			e_attachment_build_remote_file (download_info->file_name, download_info->attachment, "attachment", &ex);
+			update(download_info->bar);
+			g_free (download_info->file_name);
+			g_free (download_info);
+		}
+		return TRUE;
+		break;
+	}
+	case GNOME_VFS_XFER_PROGRESS_STATUS_VFSERROR:
+		gnome_vfs_async_cancel (handle);
+		g_free (download_info->file_name);
+		g_free (download_info);
+		return FALSE;
+		break;
+
+	default:
+		break;
+	}
+
+	return TRUE;
+}
+
+static void
+download_to_local_path (GnomeVFSURI  *source_uri, GnomeVFSURI  *target_uri, DownloadInfo *download_info)
+			
+{
+	GnomeVFSResult       result;
+	GList               *source_uri_list = NULL;
+	GList               *target_uri_list = NULL;
+
+	source_uri_list = g_list_prepend (source_uri_list, source_uri);
+	target_uri_list = g_list_prepend (target_uri_list, target_uri);
+
+	/* Callback info */
+	result = gnome_vfs_async_xfer (&download_info->attachment->handle,                        /* handle_return   */
+				       source_uri_list,                       /* source_uri_list */
+				       target_uri_list,                       /* target_uri_list */
+				       GNOME_VFS_XFER_DEFAULT,                /* xfer_options    */
+				       GNOME_VFS_XFER_ERROR_MODE_ABORT,       /* error_mode      */ 
+				       GNOME_VFS_XFER_OVERWRITE_MODE_REPLACE, /* overwrite_mode  */ 
+				       GNOME_VFS_PRIORITY_DEFAULT,            /* priority        */
+				       async_progress_update_cb,              /* progress_update_callback */
+				       download_info,                         /* update_callback_data     */
+				       NULL,                                  /* progress_sync_callback   */
+				       NULL);                                 /* sync_callback_data       */
+}
+
+
+int 
+e_attachment_bar_get_download_count (EAttachmentBar *bar)
+{
+	EAttachmentBarPrivate *priv;
+	GList *p;
+	int count=0;
+	
+	priv = bar->priv;
+	
+	for (p = priv->attachments; p != NULL; p = p->next) {
+		EAttachment *attachment;
+		
+		attachment = p->data;
+		if (!attachment->is_available_local)
+			count++;
+	}
+
+	return count;
+}
+
+void 
+e_attachment_bar_attach_remote_file (EAttachmentBar *bar,
+				     const gchar *url)
+{
+	EAttachment *attachment;
+	CamelException ex;
+	gchar *tmpfile;
+	gchar *base;
+
+	if (!bar->priv->path)
+		bar->priv->path = e_mkdtemp("attach-XXXXXX");
+	base = g_path_get_basename (url);
+	
+	g_return_if_fail (E_IS_ATTACHMENT_BAR (bar));
+	tmpfile = g_build_filename (bar->priv->path, base, NULL);
+
+	g_free (base);
+
+	camel_exception_init (&ex);
+	attachment = e_attachment_new_remote_file (tmpfile, "attachment", &ex);
+	if (attachment) {
+		DownloadInfo *download_info;
+		download_info = g_new (DownloadInfo, 1);
+		download_info->attachment = attachment;
+		download_info->bar =bar;
+		download_info->file_name = g_strdup (tmpfile);
+		add_common (bar, attachment);
+		download_to_local_path (gnome_vfs_uri_new(url), gnome_vfs_uri_new(tmpfile), download_info);
+
+	} else {
+		e_error_run((GtkWindow *)gtk_widget_get_toplevel((GtkWidget *)bar), "mail-composer:no-attach",
+			    attachment->file_name, camel_exception_get_description(&ex), NULL);
+		camel_exception_clear (&ex);
+	}
+
+	g_free (tmpfile);
+	
+}
+
+void
+e_attachment_bar_attach_mime_part (EAttachmentBar *bar,
+				   CamelMimePart *part)
+{
+	g_return_if_fail (E_IS_ATTACHMENT_BAR (bar));
+	
+	add_from_mime_part (bar, part);
+}
Index: itip-utils.c
===================================================================
RCS file: /cvs/gnome/evolution/calendar/gui/itip-utils.c,v
retrieving revision 1.100
diff -u -p -r1.100 itip-utils.c
--- itip-utils.c	20 Jun 2005 17:16:25 -0000	1.100
+++ itip-utils.c	6 Jul 2005 11:06:30 -0000
@@ -41,7 +41,6 @@
 #include <libsoup/soup-uri.h>
 #include "calendar-config.h"
 #include "itip-utils.h"
-#include "dialogs/cal-attachment.h"
 
 #define GNOME_EVOLUTION_COMPOSER_OAFIID "OAFIID:GNOME_Evolution_Mail_Composer:" BASE_VERSION
 
Index: itip-utils.h
===================================================================
RCS file: /cvs/gnome/evolution/calendar/gui/itip-utils.h,v
retrieving revision 1.18
diff -u -p -r1.18 itip-utils.h
--- itip-utils.h	20 Jun 2005 17:16:25 -0000	1.18
+++ itip-utils.h	6 Jul 2005 11:06:30 -0000
@@ -20,6 +20,14 @@ typedef enum {
 	E_CAL_COMPONENT_METHOD_DECLINECOUNTER
 } ECalComponentItipMethod;
 
+struct CalMimeAttach {
+	char *filename;
+	char *content_type;
+	char *description;
+	char *encoded_data;
+	guint length;
+};
+
 EAccountList *itip_addresses_get (void);
 EAccount *itip_addresses_get_default (void);
 
Index: dialogs/Makefile.am
===================================================================
RCS file: /cvs/gnome/evolution/calendar/gui/dialogs/Makefile.am,v
retrieving revision 1.71
diff -u -p -r1.71 Makefile.am
--- dialogs/Makefile.am	27 Jun 2005 00:43:08 -0000	1.71
+++ dialogs/Makefile.am	6 Jul 2005 11:06:30 -0000
@@ -21,12 +21,8 @@ libcal_dialogs_la_SOURCES =	\
 	alarm-dialog.h		\
 	alarm-list-dialog.c	\
 	alarm-list-dialog.h	\
-	cal-attachment-bar.c    \
-	cal-attachment-bar.h    \
 	cal-attachment-select-file.c \
 	cal-attachment-select-file.h \
-	cal-attachment.c        \
-	cal-attachment.h        \
 	cal-prefs-dialog.c	\
 	cal-prefs-dialog.h	\
 	calendar-setup.c	\
@@ -81,7 +77,6 @@ libcal_dialogs_la_SOURCES =	\
 glade_DATA =				\
 	alarm-dialog.glade		\
 	alarm-list-dialog.glade		\
-	cal-attachment.glade            \
 	cal-prefs-dialog.glade		\
 	e-delegate-dialog.glade		\
 	event-page.glade		\
Index: dialogs/comp-editor.c
===================================================================
RCS file: /cvs/gnome/evolution/calendar/gui/dialogs/comp-editor.c,v
retrieving revision 1.138
diff -u -p -r1.138 comp-editor.c
--- dialogs/comp-editor.c	6 Jul 2005 07:13:44 -0000	1.138
+++ dialogs/comp-editor.c	6 Jul 2005 11:06:30 -0000
@@ -25,12 +25,15 @@
 #include <stdio.h>
 #include <sys/types.h>
 #include <sys/stat.h>
+#include <fcntl.h>
 #include <unistd.h>
 #include <glib.h>
 #include <gdk/gdkkeysyms.h>
 #include <gtk/gtkstock.h>
 #include <libgnome/libgnome.h>
 #include <libgnome/gnome-i18n.h>
+#include <libgnomevfs/gnome-vfs-mime.h>
+#include <libgnomevfs/gnome-vfs.h>
 #include <libgnomeui/gnome-uidefs.h>
 #include <libgnomeui/gnome-dialog.h>
 #include <libgnomeui/gnome-dialog-util.h>
@@ -46,7 +49,6 @@
 #include <camel/camel-mime-message.h>
 
 #include "mail/mail-tools.h"
-#include "mail/em-popup.h"
 
 #include "../print.h"
 #include "../comp-util.h"
@@ -59,7 +61,7 @@
 #include "comp-editor.h"
 #include "../e-cal-popup.h"
 
-#include "cal-attachment-bar.h"
+#include "e-attachment-bar.h"
 #include "misc/e-expander.h"
 #include "e-util/e-error.h"
 
@@ -191,7 +193,7 @@ attach_message(CompEditor *editor, Camel
 
 	camel_medium_set_content_object((CamelMedium *)mime_part, (CamelDataWrapper *)msg);
 	camel_mime_part_set_content_type(mime_part, "message/rfc822");
-	cal_attachment_bar_attach_mime_part(CAL_ATTACHMENT_BAR(editor->priv->attachment_bar), mime_part);
+	e_attachment_bar_attach_mime_part(E_ATTACHMENT_BAR(editor->priv->attachment_bar), mime_part);
 	camel_object_unref(mime_part);
 }
 
@@ -266,12 +268,13 @@ drop_action(CompEditor *editor, GdkDragC
 				}
 
 				if (!g_ascii_strcasecmp (url->protocol, "file"))
-					cal_attachment_bar_attach
-						(CAL_ATTACHMENT_BAR (editor->priv->attachment_bar),
-					 	url->path);
+					e_attachment_bar_attach
+						(E_ATTACHMENT_BAR (editor->priv->attachment_bar),
+					 	url->path,
+						"attachment");
 				else
-					cal_attachment_bar_attach_remote_file
-						(CAL_ATTACHMENT_BAR (editor->priv->attachment_bar),
+					e_attachment_bar_attach_remote_file
+						(E_ATTACHMENT_BAR (editor->priv->attachment_bar),
 					 	str);
 
 				camel_url_free (url);
@@ -291,8 +294,8 @@ drop_action(CompEditor *editor, GdkDragC
 		camel_mime_part_set_content (mime_part, selection->data, selection->length, content_type);
 		camel_mime_part_set_disposition (mime_part, "inline");
 		
-		cal_attachment_bar_attach_mime_part
-			(CAL_ATTACHMENT_BAR (editor->priv->attachment_bar),
+		e_attachment_bar_attach_mime_part
+			(E_ATTACHMENT_BAR (editor->priv->attachment_bar),
 			 mime_part);
 		
 		camel_object_unref (mime_part);
@@ -359,8 +362,8 @@ drop_action(CompEditor *editor, GdkDragC
 					desc = g_strdup_printf(ngettext("Attached message", "%d attached messages", uids->len), uids->len);
 					camel_mime_part_set_description(mime_part, desc);
 					g_free(desc);
-					cal_attachment_bar_attach_mime_part
-						(CAL_ATTACHMENT_BAR(editor->priv->attachment_bar), mime_part);
+					e_attachment_bar_attach_mime_part
+						(E_ATTACHMENT_BAR(editor->priv->attachment_bar), mime_part);
 					camel_object_unref(mime_part);
 					camel_object_unref(mp);
 				}
@@ -592,6 +595,62 @@ send_timezone (gpointer key, gpointer va
 	e_cal_add_timezone (editor->priv->client, zone, NULL);
 }
 
+static GSList *
+get_attachment_list (CompEditor *editor)
+{
+	GSList *parts = NULL, *list = NULL, *p = NULL;
+	const char *comp_uid = NULL;
+	const char *local_store = e_cal_get_local_attachment_store (editor->priv->client);
+
+	e_cal_component_get_uid (editor->priv->comp, &comp_uid);
+
+	parts = e_attachment_bar_get_attachment_part_list((EAttachmentBar *)editor->priv->attachment_bar);
+
+	for (p = parts; p!=NULL ; p = p->next) {
+		CamelDataWrapper *wrapper;
+		CamelStreamMem *mstream;
+		unsigned char *buffer = NULL;
+		int fd;
+		char *attach_file_url;
+	
+		wrapper = camel_medium_get_content_object (CAMEL_MEDIUM (p->data));
+		mstream = (CamelStreamMem *) camel_stream_mem_new ();
+			
+		camel_data_wrapper_decode_to_stream (wrapper, (CamelStream *) mstream);
+		buffer = g_memdup (mstream->buffer->data, mstream->buffer->len);
+
+
+		/* Extract the content from the stream and write it down
+		 * as a mime part file into the directory denoting the
+		 * calendar source */
+		attach_file_url = g_strconcat (local_store,
+					       comp_uid,  "-",
+			 		       camel_file_util_safe_filename
+		   			       (camel_mime_part_get_filename ((CamelMimePart *)p->data)), NULL); 
+
+		fd = open (attach_file_url+7, O_RDWR|O_CREAT|O_TRUNC, 0600);
+		if (fd == -1) {
+			/* TODO handle error conditions */
+			g_message ("DEBUG: could not open the file descriptor\n");
+			continue;
+		}
+
+		/* write the camel mime part  (attachment->body) into the file*/
+		if (camel_write (fd, buffer, mstream->buffer->len) == -1) {
+			/* TODO handle error condition */
+			g_message ("DEBUG: camel write failed.\n");
+			continue;
+		}
+		list = g_slist_append (list, g_strdup (attach_file_url));
+		/* do i need to close the fd */
+		g_free (attach_file_url);
+	}
+
+	if (parts)
+		g_slist_free (parts);
+	return list;
+}
+
 static gboolean
 save_comp (CompEditor *editor)
 {
@@ -654,7 +713,7 @@ save_comp (CompEditor *editor)
 	/* Attachments*/
 	
 	e_cal_component_set_attachment_list (priv->comp,
-			cal_attachment_bar_get_attachment_list ((CalAttachmentBar *) priv->attachment_bar)); 
+					     get_attachment_list (editor)); 
 	icalcomp = e_cal_component_get_icalcomponent (priv->comp);
 	/* send the component to the server */
 	if (!cal_comp_is_on_server (priv->comp, priv->client)) {
@@ -814,7 +873,7 @@ response_cb (GtkWidget *widget, int resp
 	switch (response) {
 	case GTK_RESPONSE_OK:
 		/* Check whether the downloads are completed */
-		if (cal_attachment_bar_get_download_count (CAL_ATTACHMENT_BAR (editor->priv->attachment_bar)) ){
+		if (e_attachment_bar_get_download_count (E_ATTACHMENT_BAR (editor->priv->attachment_bar)) ){
 			ECalComponentVType vtype = e_cal_component_get_vtype(editor->priv->comp);
 			gboolean response;
 	
@@ -880,13 +939,13 @@ delete_event_cb (GtkWidget *widget, GdkE
 }
 
 static void
-attachment_bar_changed_cb (CalAttachmentBar *bar,
+attachment_bar_changed_cb (EAttachmentBar *bar,
 			   void *data)
 {
 	CompEditor *editor = COMP_EDITOR (data);
 	
-	guint attachment_num = cal_attachment_bar_get_num_attachments (
-		CAL_ATTACHMENT_BAR (editor->priv->attachment_bar));
+	guint attachment_num = e_attachment_bar_get_num_attachments (
+		E_ATTACHMENT_BAR (editor->priv->attachment_bar));
 	if (attachment_num) {
 		gchar *num_text = g_strdup_printf (
 			ngettext ("<b>%d</b> Attachment", "<b>%d</b> Attachments", attachment_num),
@@ -910,7 +969,7 @@ attachment_bar_changed_cb (CalAttachment
 }
 
 static	gboolean 
-attachment_bar_icon_clicked_cb (CalAttachmentBar *bar, GdkEvent *event, void *data)
+attachment_bar_icon_clicked_cb (EAttachmentBar *bar, GdkEvent *event, void *data)
 {
 	GnomeIconList *icon_list;
 	GList *p;
@@ -918,12 +977,12 @@ attachment_bar_icon_clicked_cb (CalAttac
 	char *attach_file_url;
 	GError *error = NULL;
 	
-	if (E_IS_CAL_ATTACHMENT_BAR (bar) && event->type == GDK_2BUTTON_PRESS) {
+	if (E_IS_ATTACHMENT_BAR (bar) && event->type == GDK_2BUTTON_PRESS) {
 		icon_list = GNOME_ICON_LIST (bar);
 		p = gnome_icon_list_get_selection (icon_list);
 		if (p) {
 			num = GPOINTER_TO_INT (p->data);
-			attach_file_url = cal_attachment_bar_get_nth_attachment_filename (bar, num);	
+			attach_file_url = e_attachment_bar_get_nth_attachment_filename (bar, num);	
 			/* launch the url now */
 			/* TODO should send GError and handle error conditions
 			 * here */
@@ -936,6 +995,161 @@ attachment_bar_icon_clicked_cb (CalAttac
 		return FALSE;
 }
 
+/* Callbacks.  */
+
+static void
+cab_add(EPopup *ep, EPopupItem *item, void *data)
+{
+	EAttachmentBar *bar = data;
+        CompEditor *editor = COMP_EDITOR (gtk_widget_get_toplevel (GTK_WIDGET (bar)));
+	GPtrArray *file_list;
+	gboolean is_inline = FALSE;
+	int i;
+
+	file_list = comp_editor_select_file_attachments (editor, &is_inline);
+	/*TODO add a good implementation here */
+	if (!file_list)
+		return;
+	for (i = 0; i < file_list->len; i++) {
+		e_attachment_bar_attach (bar, file_list->pdata[i], is_inline ? "inline" : "attachment");
+		g_free (file_list->pdata[i]);
+	}
+	
+	g_ptr_array_free (file_list, TRUE);	
+}
+
+static void
+cab_properties(EPopup *ep, EPopupItem *item, void *data)
+{
+	EAttachmentBar *bar = data;
+	
+	e_attachment_bar_edit_selected(bar);
+}
+
+static void
+cab_remove(EPopup *ep, EPopupItem *item, void *data)
+{
+	EAttachmentBar *bar = data;
+
+	e_attachment_bar_remove_selected(bar);
+}
+
+/* Popup menu handling.  */
+static EPopupItem cab_popups[] = {
+	{ E_POPUP_ITEM, "10.attach", N_("_Remove"), cab_remove, NULL, GTK_STOCK_REMOVE, E_CAL_POPUP_ATTACHMENTS_MANY },
+	{ E_POPUP_ITEM, "20.attach", N_("_Properties"), cab_properties, NULL, GTK_STOCK_PROPERTIES, E_CAL_POPUP_ATTACHMENTS_ONE },
+	{ E_POPUP_BAR, "30.attach.00", NULL, NULL, NULL, NULL, E_CAL_POPUP_ATTACHMENTS_MANY|E_CAL_POPUP_ATTACHMENTS_ONE },
+	{ E_POPUP_ITEM, "30.attach.01", N_("_Add attachment..."), cab_add, NULL, GTK_STOCK_ADD, 0 },
+};
+
+static void
+cab_popup_position(GtkMenu *menu, int *x, int *y, gboolean *push_in, gpointer user_data)
+{
+	EAttachmentBar *bar = user_data;
+	GnomeIconList *icon_list = user_data;
+	GList *selection;
+	GnomeCanvasPixbuf *image;
+	
+	gdk_window_get_origin (((GtkWidget*) bar)->window, x, y);
+	
+	selection = gnome_icon_list_get_selection (icon_list);
+	if (selection == NULL)
+		return;
+	
+	image = gnome_icon_list_get_icon_pixbuf_item (icon_list, (gint)selection->data);
+	if (image == NULL)
+		return;
+	
+	/* Put menu to the center of icon. */
+	*x += (int)(image->item.x1 + image->item.x2) / 2;
+	*y += (int)(image->item.y1 + image->item.y2) / 2;
+}
+
+static void
+cab_popups_free(EPopup *ep, GSList *l, void *data)
+{
+	g_slist_free(l);
+}
+
+/* if id != -1, then use it as an index for target of the popup */
+static void
+cab_popup(EAttachmentBar *bar, GdkEventButton *event, int id)
+{
+	GList *p;
+	GSList *attachments = NULL, *menus = NULL;
+	int i;
+	ECalPopup *ecp;
+	ECalPopupTargetAttachments *t;
+	GtkMenu *menu;
+
+        attachments = e_attachment_bar_get_attachment(bar, id);
+
+	for (i=0;i<sizeof(cab_popups)/sizeof(cab_popups[0]);i++)
+		menus = g_slist_prepend(menus, &cab_popups[i]);
+
+	/** @HookPoint-ECalPopup: Calendar Attachment Bar Context Menu
+	 * @Id: org.gnome.evolution.calendar.attachmentbar.popup
+	 * @Class: org.gnome.evolution.mail.popup:1.0
+	 * @Target: ECalPopupTargetAttachments
+	 *
+	 * This is the context menu on the calendar attachment bar.
+	 */
+	ecp = e_cal_popup_new("org.gnome.evolution.calendar.attachmentbar.popup");
+	e_popup_add_items((EPopup *)ecp, menus, NULL, cab_popups_free, bar);
+	t = e_cal_popup_target_new_attachments(ecp, attachments);
+	t->target.widget = (GtkWidget *)bar;
+	menu = e_popup_create_menu_once((EPopup *)ecp, (EPopupTarget *)t, 0);
+
+	if (event == NULL)
+		gtk_menu_popup(menu, NULL, NULL, cab_popup_position, bar, 0, gtk_get_current_event_time());
+	else
+		gtk_menu_popup(menu, NULL, NULL, NULL, NULL, event->button, event->time);
+}
+
+/* GtkWidget methods.  */
+
+static gboolean 
+popup_menu_event (GtkWidget *widget)
+{
+	cab_popup((EAttachmentBar *)widget, NULL, -1);
+	return TRUE;
+}
+
+
+static int
+button_press_event (GtkWidget *widget, GdkEventButton *event)
+{
+	EAttachmentBar *bar = (EAttachmentBar *)widget;
+	GnomeIconList *icon_list = GNOME_ICON_LIST(widget);
+	int icon_number;
+	printf("dd\n");
+	if (event->button != 3)
+		return FALSE;
+	
+	icon_number = gnome_icon_list_get_icon_at (icon_list, event->x, event->y);
+	if (icon_number >= 0) {
+		gnome_icon_list_unselect_all(icon_list);
+		gnome_icon_list_select_icon (icon_list, icon_number);
+	}
+
+	cab_popup(bar, event, icon_number);
+	
+	return TRUE;
+}
+
+static gint
+key_press_event(GtkWidget *widget, GdkEventKey *event)
+{
+        EAttachmentBar *bar = E_ATTACHMENT_BAR (widget);
+
+        if (event->keyval == GDK_Delete) {
+                e_attachment_bar_remove_selected (bar);
+                return TRUE;
+        }
+                                                                                
+        return FALSE;
+}
+
 /* Creates the basic in the editor */
 static void
 setup_widgets (CompEditor *editor)
@@ -974,7 +1188,12 @@ setup_widgets (CompEditor *editor)
 	gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (priv->attachment_scrolled_window),
 					GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
 	
-	priv->attachment_bar = cal_attachment_bar_new (NULL);
+	priv->attachment_bar = e_attachment_bar_new (NULL);
+
+	g_signal_connect (priv->attachment_bar, "button_press_event", G_CALLBACK (button_press_event), NULL);
+        g_signal_connect (priv->attachment_bar, "key_press_event", G_CALLBACK (key_press_event), NULL);
+        g_signal_connect (priv->attachment_bar, "popup-menu", G_CALLBACK (popup_menu_event), NULL);
+
 	GTK_WIDGET_SET_FLAGS (priv->attachment_bar, GTK_CAN_FOCUS);
 	gtk_container_add (GTK_CONTAINER (priv->attachment_scrolled_window),
 			   priv->attachment_bar);
@@ -1734,6 +1953,110 @@ set_icon_from_comp (CompEditor *editor)
 	}
 }
 
+static char *
+attachment_guess_mime_type (const char *file_name)
+{
+	GnomeVFSFileInfo *info;
+	GnomeVFSResult result;
+	char *type = NULL;
+
+	info = gnome_vfs_file_info_new ();
+	result = gnome_vfs_get_file_info (file_name, info,
+					  GNOME_VFS_FILE_INFO_GET_MIME_TYPE |
+					  GNOME_VFS_FILE_INFO_FORCE_SLOW_MIME_TYPE |
+					  GNOME_VFS_FILE_INFO_FOLLOW_LINKS);
+	if (result == GNOME_VFS_OK)
+		type = g_strdup (gnome_vfs_file_info_get_mime_type (info));
+
+	gnome_vfs_file_info_unref (info);
+
+	return type;
+}
+
+static void 
+set_attachment_list (CompEditor *editor, GSList *attach_list)
+{
+	GSList *parts = NULL, *attachment_list = NULL, *p = NULL;
+	const char *comp_uid= NULL;
+	const char *local_store = e_cal_get_local_attachment_store (editor->priv->client);
+
+	e_cal_component_get_uid (editor->priv->comp, &comp_uid);
+
+	if (e_attachment_bar_get_num_attachments (editor->priv->attachment_bar)) {
+		/* To prevent repopulating the
+		 * bar due to redraw functions in fill_widget. 
+		 * Assumes it can be set only once.
+		 */		
+		return; 		
+	}
+
+	for (p = attach_list; p != NULL; p = p->next) {
+		char *attach_filename;
+		CamelMimePart *part;
+		CamelDataWrapper *wrapper;
+		CamelStream *stream;
+		struct stat statbuf;
+		char *mime_type, *file_name;		
+
+		attach_filename = (char *) p->data;
+		/* should we assert if g_str_has_prefix (attach_filename, "file://")) 
+		 * here
+		*/
+		/* get url sans protocol and add it to the bar.
+		 * how to set the filename properly */		
+		file_name = attach_filename +7;
+		
+		if (stat (file_name, &statbuf) < 0) {
+			g_warning ("Cannot attach file %s: %s", file_name, g_strerror (errno));
+			continue;
+		}
+	
+		/* return if it's not a regular file */
+		if (!S_ISREG (statbuf.st_mode)) {
+			g_warning ("Cannot attach file %s: not a regular file", file_name);
+			return NULL;
+		}
+		
+		stream = camel_stream_fs_new_with_name (file_name, O_RDONLY, 0);
+		if (!stream) {
+			g_warning ("Cannot attach file %s: %s", file_name, g_strerror (errno));
+			return NULL;
+		}
+
+		mime_type = attachment_guess_mime_type (file_name);
+		if (mime_type) {
+			if (!g_ascii_strcasecmp (mime_type, "message/rfc822")) {
+				wrapper = (CamelDataWrapper *) camel_mime_message_new ();
+			} else {
+				wrapper = camel_data_wrapper_new ();
+			}
+			
+			camel_data_wrapper_construct_from_stream (wrapper, stream);
+			camel_data_wrapper_set_mime_type (wrapper, mime_type);
+			g_free (mime_type);
+		} else {
+			wrapper = camel_data_wrapper_new ();
+			camel_data_wrapper_construct_from_stream (wrapper, stream);
+			camel_data_wrapper_set_mime_type (wrapper, "application/octet-stream");
+		}
+		
+		camel_object_unref (stream);
+		
+		part = camel_mime_part_new ();
+		camel_medium_set_content_object (CAMEL_MEDIUM (part), wrapper);
+		camel_object_unref (wrapper);
+	
+		camel_mime_part_set_disposition (part, "attachment");
+
+		camel_mime_part_set_filename (part,
+					      attach_filename + strlen (local_store)+ 
+						strlen (comp_uid) + 1); 
+		e_attachment_bar_attach_mime_part ((EAttachmentBar *) editor->priv->attachment_bar, part);
+
+		camel_object_unref (part);
+	}	
+}
+
 static void
 fill_widgets (CompEditor *editor)
 {
@@ -1746,8 +2069,7 @@ fill_widgets (CompEditor *editor)
 	if (e_cal_component_has_attachments (priv->comp)) {
 		GSList *attachment_list = NULL;
 		e_cal_component_get_attachment_list (priv->comp, &attachment_list);
-		cal_attachment_bar_set_attachment_list
-			((CalAttachmentBar *)priv->attachment_bar, attachment_list);
+		set_attachment_list (editor, attachment_list);
 	}	
 
 	for (l = priv->pages; l != NULL; l = l->next)
@@ -1813,9 +2135,6 @@ real_edit_comp (CompEditor *editor, ECal
 	set_title_from_comp (editor);
 	set_icon_from_comp (editor);
 	e_cal_component_get_uid (comp, &uid);
-	cal_attachment_bar_set_local_attachment_store ((CalAttachmentBar *) priv->attachment_bar, 
-			e_cal_get_local_attachment_store (priv->client)); 
-	cal_attachment_bar_set_comp_uid (priv->attachment_bar, g_strdup	(uid));
 
 	fill_widgets (editor);
 
@@ -2057,11 +2376,42 @@ GSList *
 comp_editor_get_mime_attach_list (CompEditor *editor) 
 {
 	GSList *mime_attach_list;
+	struct CalMimeAttach *cal_mime_attach;
+	GSList *attach_list = NULL, *l, *parts;
+
+	/* TODO assert sanity of bar */
+	parts = e_attachment_bar_get_attachment_part_list (editor->priv->attachment_bar);
+	for (l = parts; l ; l = l->next) {
+		
+		CamelDataWrapper *wrapper;
+		CamelStreamMem *mstream;
+		unsigned char *buffer = NULL;
+		char *desc;
+
+		cal_mime_attach = g_malloc0 (sizeof (struct CalMimeAttach));
+		wrapper = camel_medium_get_content_object (CAMEL_MEDIUM (l->data));
+		mstream = (CamelStreamMem *) camel_stream_mem_new ();
+			
+		camel_data_wrapper_decode_to_stream (wrapper, (CamelStream *) mstream);
+		buffer = g_memdup (mstream->buffer->data, mstream->buffer->len);
+		
+		cal_mime_attach->encoded_data = buffer;
+		cal_mime_attach->length = mstream->buffer->len;
+		cal_mime_attach->filename = g_strdup (camel_mime_part_get_filename
+			((CamelMimePart *) l->data));
+		desc = camel_mime_part_get_description ((CamelMimePart *) l->data);
+		if (!desc || *desc == '\0')
+			desc = _("attachment");
+		cal_mime_attach->description = g_strdup (desc);
+		cal_mime_attach->content_type = g_strdup (camel_data_wrapper_get_mime_type (wrapper));
+		
+		attach_list = g_slist_append (attach_list, cal_mime_attach);
+		
+	}
 
-	mime_attach_list = cal_attachment_bar_get_mime_attach_list
-		((CalAttachmentBar *)editor->priv->attachment_bar);
+	g_slist_free (parts);
 
-	return mime_attach_list;
+	return attach_list;
 }
 
 /* Brings attention to a window by raising it and giving it focus */
Index: dialogs/comp-editor.h
===================================================================
RCS file: /cvs/gnome/evolution/calendar/gui/dialogs/comp-editor.h,v
retrieving revision 1.27
diff -u -p -r1.27 comp-editor.h
--- dialogs/comp-editor.h	6 Jun 2005 21:05:18 -0000	1.27
+++ dialogs/comp-editor.h	6 Jul 2005 11:06:30 -0000
@@ -26,7 +26,6 @@
 #include "../itip-utils.h"
 #include "comp-editor-page.h"
 #include "evolution-shell-component-utils.h"
-#include "cal-attachment-bar.h"
 
 G_BEGIN_DECLS
 
Index: Makefile.am
===================================================================
RCS file: /cvs/gnome/evolution/composer/Makefile.am,v
retrieving revision 1.74
diff -u -p -r1.74 Makefile.am
--- Makefile.am	6 May 2005 11:26:06 -0000	1.74
+++ Makefile.am	6 Jul 2005 10:59:32 -0000
@@ -35,9 +35,6 @@ errordir = $(privdatadir)/errors
 
 idl_DATA = $(IDLS)
 
-glade_DATA =					\
-	e-msg-composer-attachment.glade
-
 noinst_LTLIBRARIES = libcomposer.la
 
 INCLUDES =								\
@@ -64,10 +61,6 @@ INCLUDES =								\
 libcomposer_la_SOURCES = 			\
 	$(IDL_GENERATED)			\
 	$(HTML_EDITOR_GENERATED)		\
-	e-msg-composer-attachment-bar.c		\
-	e-msg-composer-attachment-bar.h		\
-	e-msg-composer-attachment.c		\
-	e-msg-composer-attachment.h		\
 	e-msg-composer-hdrs.c			\
 	e-msg-composer-hdrs.h			\
 	e-msg-composer-select-file.c		\
@@ -81,7 +74,6 @@ libcomposer_la_SOURCES = 			\
 
 EXTRA_DIST =					\
 	mail-composer.error.xml			\
-	$(glade_DATA)				\
 	$(IDLS)					\
 	ChangeLog.pre-1-4
 
Index: e-msg-composer.c
===================================================================
RCS file: /cvs/gnome/evolution/composer/e-msg-composer.c,v
retrieving revision 1.512
diff -u -p -r1.512 e-msg-composer.c
--- e-msg-composer.c	23 Jun 2005 09:11:06 -0000	1.512
+++ e-msg-composer.c	6 Jul 2005 10:59:34 -0000
@@ -120,7 +120,8 @@
 #include "mail/em-menu.h"
 
 #include "e-msg-composer.h"
-#include "e-msg-composer-attachment-bar.h"
+#include "e-attachment.h"
+#include "e-attachment-bar.h"
 #include "e-msg-composer-hdrs.h"
 #include "e-msg-composer-select-file.h"
 
@@ -427,8 +428,8 @@ add_inlined_images (EMsgComposer *compos
 static CamelMimeMessage *
 build_message (EMsgComposer *composer, gboolean save_html_object_data)
 {
-	EMsgComposerAttachmentBar *attachment_bar =
-		E_MSG_COMPOSER_ATTACHMENT_BAR (composer->attachment_bar);
+	EAttachmentBar *attachment_bar =
+		E_ATTACHMENT_BAR (composer->attachment_bar);
 	EMsgComposerHdrs *hdrs = E_MSG_COMPOSER_HDRS (composer->hdrs);
 	CamelDataWrapper *plain, *html, *current;
 	CamelTransferEncoding plain_encoding;
@@ -599,7 +600,7 @@ build_message (EMsgComposer *composer, g
 	} else
 		current = plain;
 	
-	if (e_msg_composer_attachment_bar_get_num_attachments (attachment_bar)) {
+	if (e_attachment_bar_get_num_attachments (attachment_bar)) {
 		CamelMultipart *multipart = camel_multipart_new ();
 		
 		if (composer->is_alternative) {
@@ -618,7 +619,7 @@ build_message (EMsgComposer *composer, g
 		camel_multipart_add_part (multipart, part);
 		camel_object_unref (part);
 		
-		e_msg_composer_attachment_bar_to_multipart (attachment_bar, multipart, composer->charset);
+		e_attachment_bar_to_multipart (attachment_bar, multipart, composer->charset);
 		
 		if (composer->is_alternative) {
 			int i;
@@ -1654,19 +1655,26 @@ menu_file_close_cb (BonoboUIComponent *u
 	composer = E_MSG_COMPOSER (data);
 	do_exit (composer);
 }
+
+static void
+add_to_bar (GtkWidget *composer, GSList *names, int is_inline)
+{
+	while (names) {
+		e_attachment_bar_attach((EAttachmentBar *)((EMsgComposer *)composer)->attachment_bar, names->data, is_inline ? "inline" : "attachment");
+		names = g_slist_next(names);
+	}
+}
 	
 static void
 menu_file_add_attachment_cb (BonoboUIComponent *uic,
 			     void *data,
 			     const char *path)
 {
-	EMsgComposer *composer;
-	
-	composer = E_MSG_COMPOSER (data);
-	
-	e_msg_composer_attachment_bar_attach
-		(E_MSG_COMPOSER_ATTACHMENT_BAR (composer->attachment_bar),
-		 NULL);
+	EMsgComposer *composer = E_MSG_COMPOSER (data);
+	GtkWindow *toplevel = E_MSG_COMPOSER (gtk_widget_get_toplevel (GTK_WIDGET (composer->attachment_bar)));
+	GtkWidget **attachment_selector = e_attachment_bar_get_selector(E_ATTACHMENT_BAR(composer->attachment_bar));
+
+	e_msg_composer_select_file_attachments (toplevel, attachment_selector, add_to_bar);
 }
 
 static void
@@ -2296,13 +2304,13 @@ setup_ui (EMsgComposer *composer)
 /* Miscellaneous callbacks.  */
 
 static void
-attachment_bar_changed_cb (EMsgComposerAttachmentBar *bar,
+attachment_bar_changed_cb (EAttachmentBar *bar,
 			   void *data)
 {
 	EMsgComposer *composer = E_MSG_COMPOSER (data);
 
-	guint attachment_num = e_msg_composer_attachment_bar_get_num_attachments (
-		E_MSG_COMPOSER_ATTACHMENT_BAR (composer->attachment_bar));
+	guint attachment_num = e_attachment_bar_get_num_attachments (
+		E_ATTACHMENT_BAR (composer->attachment_bar));
 	if (attachment_num) {
 		gchar *num_text = g_strdup_printf (
 			ngettext ("<b>%d</b> Attachment", "<b>%d</b> Attachments", attachment_num),
@@ -2326,6 +2334,7 @@ attachment_bar_changed_cb (EMsgComposerA
 }
 
 static void
+#include "e-attachment-bar.h"
 subject_changed_cb (EMsgComposerHdrs *hdrs,
 		    gchar *subject,
 		    void *data)
@@ -2660,7 +2669,7 @@ attach_message(EMsgComposer *composer, C
 
 	camel_medium_set_content_object((CamelMedium *)mime_part, (CamelDataWrapper *)msg);
 	camel_mime_part_set_content_type(mime_part, "message/rfc822");
-	e_msg_composer_attachment_bar_attach_mime_part(E_MSG_COMPOSER_ATTACHMENT_BAR(composer->attachment_bar), mime_part);
+	e_attachment_bar_attach_mime_part(E_ATTACHMENT_BAR(composer->attachment_bar), mime_part);
 	camel_object_unref(mime_part);
 }
 
@@ -2683,8 +2692,8 @@ struct _drop_data {
 int
 e_msg_composer_get_remote_download_count (EMsgComposer *composer)
 {
-	return e_msg_composer_attachment_bar_get_download_count 
-				(E_MSG_COMPOSER_ATTACHMENT_BAR (composer->attachment_bar));
+	return e_attachment_bar_get_download_count 
+				(E_ATTACHMENT_BAR (composer->attachment_bar));
 }
 
 static void
@@ -2742,12 +2751,13 @@ drop_action(EMsgComposer *composer, GdkD
 				}
 
 				if (!g_ascii_strcasecmp (url->protocol, "file"))
-					e_msg_composer_attachment_bar_attach
-						(E_MSG_COMPOSER_ATTACHMENT_BAR (composer->attachment_bar),
-					 	url->path);
+					e_attachment_bar_attach
+						(E_ATTACHMENT_BAR (composer->attachment_bar),
+					 	url->path,
+						"attachment");
 				else	{
-					e_msg_composer_attachment_bar_attach_remote_file 
-						(E_MSG_COMPOSER_ATTACHMENT_BAR (composer->attachment_bar),
+					e_attachment_bar_attach_remote_file 
+						(E_ATTACHMENT_BAR (composer->attachment_bar),
 						str);
 				}
 				g_free (str);
@@ -2767,8 +2777,8 @@ drop_action(EMsgComposer *composer, GdkD
 		camel_mime_part_set_content (mime_part, selection->data, selection->length, content_type);
 		camel_mime_part_set_disposition (mime_part, "inline");
 		
-		e_msg_composer_attachment_bar_attach_mime_part
-			(E_MSG_COMPOSER_ATTACHMENT_BAR (composer->attachment_bar),
+		e_attachment_bar_attach_mime_part
+			(E_ATTACHMENT_BAR (composer->attachment_bar),
 			 mime_part);
 		
 		camel_object_unref (mime_part);
@@ -2835,7 +2845,7 @@ drop_action(EMsgComposer *composer, GdkD
 					desc = g_strdup_printf(ngettext("Attached message", "%d attached messages", uids->len), uids->len);
 					camel_mime_part_set_description(mime_part, desc);
 					g_free(desc);
-					e_msg_composer_attachment_bar_attach_mime_part(E_MSG_COMPOSER_ATTACHMENT_BAR(composer->attachment_bar), mime_part);
+					e_attachment_bar_attach_mime_part(E_ATTACHMENT_BAR(composer->attachment_bar), mime_part);
 					camel_object_unref(mime_part);
 					camel_object_unref(mp);
 				}
@@ -3355,6 +3365,150 @@ e_msg_composer_unrealize (GtkWidget *wid
 	g_object_unref (gconf);
 }
 
+/* Callbacks.  */
+
+static void
+emcab_add(EPopup *ep, EPopupItem *item, void *data)
+{
+	EAttachmentBar *bar = data;
+	GtkWindow *toplevel = E_MSG_COMPOSER (gtk_widget_get_toplevel (GTK_WIDGET (bar)));
+	GtkWidget **attachment_selector = e_attachment_bar_get_selector(E_ATTACHMENT_BAR(bar));
+
+	e_msg_composer_select_file_attachments (toplevel, attachment_selector, add_to_bar);
+}
+
+static void
+emcab_properties(EPopup *ep, EPopupItem *item, void *data)
+{
+	EAttachmentBar *bar = data;
+	
+	e_attachment_bar_edit_selected(bar);
+}
+
+static void
+emcab_remove(EPopup *ep, EPopupItem *item, void *data)
+{
+	EAttachmentBar *bar = data;
+
+	e_attachment_bar_remove_selected(bar);
+}
+
+/* Popup menu handling.  */
+static EPopupItem emcab_popups[] = {
+	{ E_POPUP_ITEM, "10.attach", N_("_Remove"), emcab_remove, NULL, GTK_STOCK_REMOVE, EM_POPUP_ATTACHMENTS_MANY },
+	{ E_POPUP_ITEM, "20.attach", N_("_Properties"), emcab_properties, NULL, GTK_STOCK_PROPERTIES, EM_POPUP_ATTACHMENTS_ONE },
+	{ E_POPUP_BAR, "30.attach.00", NULL, NULL, NULL, NULL, EM_POPUP_ATTACHMENTS_MANY|EM_POPUP_ATTACHMENTS_ONE },
+	{ E_POPUP_ITEM, "30.attach.01", N_("_Add attachment..."), emcab_add, NULL, GTK_STOCK_ADD, 0 },
+};
+
+static void
+emcab_popup_position(GtkMenu *menu, int *x, int *y, gboolean *push_in, gpointer user_data)
+{
+	EAttachmentBar *bar = user_data;
+	GnomeIconList *icon_list = user_data;
+	GList *selection;
+	GnomeCanvasPixbuf *image;
+	
+	gdk_window_get_origin (((GtkWidget*) bar)->window, x, y);
+	
+	selection = gnome_icon_list_get_selection (icon_list);
+	if (selection == NULL)
+		return;
+	
+	image = gnome_icon_list_get_icon_pixbuf_item (icon_list, (gint)selection->data);
+	if (image == NULL)
+		return;
+	
+	/* Put menu to the center of icon. */
+	*x += (int)(image->item.x1 + image->item.x2) / 2;
+	*y += (int)(image->item.y1 + image->item.y2) / 2;
+}
+
+static void
+emcab_popups_free(EPopup *ep, GSList *l, void *data)
+{
+	g_slist_free(l);
+}
+
+/* if id != -1, then use it as an index for target of the popup */
+
+static void
+emcab_popup(EAttachmentBar *bar, GdkEventButton *event, int id)
+{
+	GList *p;
+	GSList *attachments = NULL, *menus = NULL;
+	int i;
+	EMPopup *emp;
+	EMPopupTargetAttachments *t;
+	GtkMenu *menu;
+	EAttachment *attachment;
+
+	attachments = e_attachment_bar_get_attachment(bar, id);
+	
+	for (i=0;i<sizeof(emcab_popups)/sizeof(emcab_popups[0]);i++)
+		menus = g_slist_prepend(menus, &emcab_popups[i]);
+
+	/** @HookPoint-EMPopup: Composer Attachment Bar Context Menu
+	 * @Id: org.gnome.evolution.mail.composer.attachmentbar.popup
+	 * @Class: org.gnome.evolution.mail.popup:1.0
+	 * @Target: EMPopupTargetAttachments
+	 *
+	 * This is the context menu on the composer attachment bar.
+	 */
+	emp = em_popup_new("org.gnome.evolution.mail.composer.attachmentbar.popup");
+	e_popup_add_items((EPopup *)emp, menus, NULL,emcab_popups_free, bar);
+	t = em_popup_target_new_attachments(emp, attachments);
+	t->target.widget = (GtkWidget *)bar;
+	menu = e_popup_create_menu_once((EPopup *)emp, (EPopupTarget *)t, 0);
+
+	if (event == NULL)
+		gtk_menu_popup(menu, NULL, NULL, emcab_popup_position, bar, 0, gtk_get_current_event_time());
+	else
+		gtk_menu_popup(menu, NULL, NULL, NULL, NULL, event->button, event->time);
+}
+
+static gboolean 
+popup_menu_event (GtkWidget *widget)
+{
+	emcab_popup((EAttachmentBar *)widget, NULL, -1);
+	return TRUE;
+}
+
+
+static int
+button_press_event (GtkWidget *widget, GdkEventButton *event)
+{
+	EAttachmentBar *bar = (EAttachmentBar *)widget;
+	GnomeIconList *icon_list = GNOME_ICON_LIST(widget);
+	int icon_number;
+	
+	if (event->button != 3)
+		return FALSE;
+	
+	icon_number = gnome_icon_list_get_icon_at (icon_list, event->x, event->y);
+	if (icon_number >= 0) {
+		gnome_icon_list_unselect_all(icon_list);
+		gnome_icon_list_select_icon (icon_list, icon_number);
+	}
+
+	emcab_popup(bar, event, icon_number);
+	
+	return TRUE;
+}
+
+static gint
+key_press_event(GtkWidget *widget, GdkEventKey *event)
+{
+        EAttachmentBar *bar = E_ATTACHMENT_BAR(widget);
+
+        if (event->keyval == GDK_Delete) {
+                e_attachment_bar_remove_selected (bar);
+                return TRUE;
+        }
+                                                                                
+        return FALSE;
+}
+
 static EMsgComposer *
 create_composer (int visible_mask)
 {
@@ -3472,7 +3626,12 @@ create_composer (int visible_mask)
 	gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (composer->attachment_scrolled_window),
 					GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
 	
-	composer->attachment_bar = e_msg_composer_attachment_bar_new (NULL);
+	composer->attachment_bar = e_attachment_bar_new (NULL);
+
+	g_signal_connect (composer->attachment_bar, "button_press_event", G_CALLBACK (button_press_event), NULL);
+	g_signal_connect (composer->attachment_bar, "key_press_event", G_CALLBACK (key_press_event), NULL);
+	g_signal_connect (composer->attachment_bar, "popup-menu", G_CALLBACK (popup_menu_event), NULL);
+	
 	GTK_WIDGET_SET_FLAGS (composer->attachment_bar, GTK_CAN_FOCUS);
 	gtk_container_add (GTK_CONTAINER (composer->attachment_scrolled_window),
 			   composer->attachment_bar);
@@ -4405,12 +4564,14 @@ handle_mailto (EMsgComposer *composer, c
 				/* Change file url to absolute path */
 				if (!g_ascii_strncasecmp (content, "file:", 5)) {
 					url = camel_url_new (content, NULL);
-					e_msg_composer_attachment_bar_attach (E_MSG_COMPOSER_ATTACHMENT_BAR (composer->attachment_bar),
-									      url->path);
+					e_attachment_bar_attach (E_ATTACHMENT_BAR (composer->attachment_bar),
+							 	 url->path,
+								 "attachment");
 					camel_url_free (url);
 				} else {
-					e_msg_composer_attachment_bar_attach (E_MSG_COMPOSER_ATTACHMENT_BAR (composer->attachment_bar),
-									      content);
+					e_attachment_bar_attach (E_ATTACHMENT_BAR (composer->attachment_bar),
+								 content,
+								 "attachment");
 				}
 			} else if (!g_ascii_strcasecmp (header, "from")) {
 				/* Ignore */
@@ -4604,13 +4765,13 @@ e_msg_composer_add_header (EMsgComposer 
 void
 e_msg_composer_attach (EMsgComposer *composer, CamelMimePart *attachment)
 {
-	EMsgComposerAttachmentBar *bar;
+	EAttachmentBar *bar;
 	
 	g_return_if_fail (E_IS_MSG_COMPOSER (composer));
 	g_return_if_fail (CAMEL_IS_MIME_PART (attachment));
 	
-	bar = E_MSG_COMPOSER_ATTACHMENT_BAR (composer->attachment_bar);
-	e_msg_composer_attachment_bar_attach_mime_part (bar, attachment);
+	bar = E_ATTACHMENT_BAR (composer->attachment_bar);
+	e_attachment_bar_attach_mime_part (bar, attachment);
 	gtk_widget_show (composer->attachment_expander);
 	gtk_widget_show (composer->attachment_scrolled_window);
 
Index: e-msg-composer.h
===================================================================
RCS file: /cvs/gnome/evolution/composer/e-msg-composer.h,v
retrieving revision 1.93
diff -u -p -r1.93 e-msg-composer.h
--- e-msg-composer.h	23 May 2005 07:10:03 -0000	1.93
+++ e-msg-composer.h	6 Jul 2005 10:59:34 -0000
@@ -31,7 +31,6 @@ typedef struct _EMsgComposerClass  EMsgC
 #include <bonobo/bonobo-window.h>
 #include <bonobo/bonobo-ui-component.h>
 
-#include "e-msg-composer-attachment-bar.h"
 #include "e-msg-composer-hdrs.h"
 #include "Editor.h"
 
Index: configure.in
===================================================================
RCS file: /cvs/gnome/evolution/configure.in,v
retrieving revision 1.824
diff -u -p -r1.824 configure.in
--- configure.in	27 Jun 2005 00:36:06 -0000	1.824
+++ configure.in	6 Jul 2005 10:54:58 -0000
@@ -1221,7 +1221,7 @@ EVO_SET_COMPILE_FLAGS(TZDIALOG, libecal-
 AC_SUBST(TZDIALOG_CFLAGS)
 AC_SUBST(TZDIALOG_LIBS)
 
-EVO_SET_COMPILE_FLAGS(E_WIDGETS, glib-2.0 libbonoboui-2.0 >= $BONOBOUI_REQUIRED gnome-vfs-2.0 libgnomeui-2.0 libglade-2.0 libgnomecanvas-2.0 libxml-2.0 gconf-2.0 libedataserverui-$EDS_PACKAGE)
+EVO_SET_COMPILE_FLAGS(E_WIDGETS, glib-2.0 libbonoboui-2.0 >= $BONOBOUI_REQUIRED gnome-vfs-2.0 gnome-vfs-module-2.0 libgnomeui-2.0 libglade-2.0 libgnomecanvas-2.0 libxml-2.0 gconf-2.0 libedataserverui-$EDS_PACKAGE)
 AC_SUBST(E_WIDGETS_CFLAGS)
 AC_SUBST(E_WIDGETS_LIBS)
  


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