[evolution-patches] Unified Attachment Bar Patch
- From: Srinivasa Ragavan <sragavan novell com>
- To: evolution-patches lists ximian com
- Subject: [evolution-patches] Unified Attachment Bar Patch
- Date: Thu, 07 Jul 2005 22:20:24 +0530
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]