[evolution] Commit the rest of the attachment UI rewrite
- From: Matthew Barnes <mbarnes src gnome org>
- To: svn-commits-list gnome org
- Subject: [evolution] Commit the rest of the attachment UI rewrite
- Date: Mon, 27 Apr 2009 15:36:39 -0400 (EDT)
commit 4449a34101406bffe508dd40b8b653f7c7d14c7d
Author: Matthew Barnes <mbarnes redhat com>
Date: Mon Apr 27 15:36:19 2009 -0400
Commit the rest of the attachment UI rewrite
Oops, last commit only included the -new- files.
This also removes EExpander, which is no longer used.
---
a11y/e-table/Makefile.am | 5 +-
a11y/widgets/Makefile.am | 2 -
a11y/widgets/ea-expander.c | 165 --
a11y/widgets/ea-expander.h | 51 -
a11y/widgets/ea-widgets.c | 7 -
a11y/widgets/ea-widgets.h | 1 -
calendar/gui/Makefile.am | 2 +
calendar/gui/calendar-component.c | 4 +
calendar/gui/dialogs/comp-editor.c | 1229 ++------
calendar/gui/dialogs/event-editor.c | 2 -
calendar/gui/e-cal-popup.c | 417 ---
calendar/gui/e-cal-popup.h | 2 -
composer/e-composer-actions.c | 66 +-
composer/e-composer-private.c | 87 +-
composer/e-composer-private.h | 12 +-
composer/e-msg-composer.c | 697 ++----
composer/e-msg-composer.h | 12 +-
configure.in | 6 +-
e-util/e-util.c | 207 ++
e-util/e-util.h | 16 +
mail/Makefile.am | 4 +
mail/em-filter-i18n.h | 2 +
mail/em-format-html-display.c | 615 +----
mail/em-format-html-display.h | 2 -
mail/em-popup.c | 123 +-
mail/em-popup.h | 35 +-
mail/mail-component.c | 5 +
plugins/attachment-reminder/attachment-reminder.c | 13 +-
plugins/import-ics-attachments/ChangeLog | 109 -
plugins/import-ics-attachments/Makefile.am | 35 -
plugins/import-ics-attachments/icsimporter.c | 435 ---
...evolution-mail-attachments-import-ics.eplug.xml | 26 -
plugins/save-attachments/ChangeLog | 102 -
plugins/save-attachments/Makefile.am | 31 -
.../org-gnome-save-attachments.eplug.xml | 26 -
.../org-gnome-save-attachments.xml | 20 -
plugins/save-attachments/save-attachments.c | 392 ---
shell/apps_evolution_shell.schemas.in | 30 +-
widgets/misc/Makefile.am | 22 +-
widgets/misc/e-attachment-bar.c | 1504 ----------
widgets/misc/e-attachment-bar.h | 105 -
widgets/misc/e-attachment.c | 3021 ++++++++++++++++----
widgets/misc/e-attachment.h | 186 +-
widgets/misc/e-expander.c | 1341 ---------
widgets/misc/e-expander.h | 82 -
widgets/text/Makefile.am | 2 +
46 files changed, 3430 insertions(+), 7828 deletions(-)
diff --git a/a11y/e-table/Makefile.am b/a11y/e-table/Makefile.am
index 1884c3a..f344d7b 100644
--- a/a11y/e-table/Makefile.am
+++ b/a11y/e-table/Makefile.am
@@ -1,6 +1,7 @@
INCLUDES = \
- -I$(top_srcdir) \
- -I$(top_srcdir)/widgets \
+ -I$(top_srcdir) \
+ -I$(top_srcdir)/widgets \
+ $(E_UTIL_CFLAGS) \
$(GNOME_PLATFORM_CFLAGS) \
-DG_LOG_DOMAIN=\"e-table\"
diff --git a/a11y/widgets/Makefile.am b/a11y/widgets/Makefile.am
index e157f82..6fb8c80 100644
--- a/a11y/widgets/Makefile.am
+++ b/a11y/widgets/Makefile.am
@@ -22,8 +22,6 @@ libevolution_widgets_a11y_la_SOURCES = \
ea-calendar-cell.h \
ea-combo-button.c \
ea-combo-button.h \
- ea-expander.c \
- ea-expander.h \
ea-widgets.c \
ea-widgets.h
diff --git a/a11y/widgets/ea-expander.c b/a11y/widgets/ea-expander.c
deleted file mode 100644
index ae9da5f..0000000
--- a/a11y/widgets/ea-expander.c
+++ /dev/null
@@ -1,165 +0,0 @@
-/*
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) version 3.
- *
- * 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
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with the program; if not, see <http://www.gnu.org/licenses/>
- *
- *
- * Authors:
- * Boby Wang <boby wang sun com>
- *
- * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
- *
- */
-
-#include <config.h>
-#include "ea-expander.h"
-#include <glib/gi18n.h>
-
-static AtkObjectClass *parent_class;
-static GType parent_type;
-
-/* Action IDs */
-enum {
- ACTIVATE,
- LAST_ACTION
-};
-
-static G_CONST_RETURN gchar*
-ea_expander_get_name (AtkObject *a11y)
-{
- return _("Toggle Attachment Bar");
-}
-
-/* Action interface */
-static G_CONST_RETURN gchar *
-ea_expander_action_get_name (AtkAction *action, gint i)
-{
- switch (i)
- {
- case ACTIVATE:
- return _("activate");
- default:
- return NULL;
- }
-}
-
-static gboolean
-ea_expander_do_action (AtkAction *action, gint i)
-{
- GtkWidget *widget;
- EExpander *expander;
-
- widget = GTK_ACCESSIBLE (action)->widget;
- if (!widget || !GTK_WIDGET_IS_SENSITIVE (widget) || !GTK_WIDGET_VISIBLE (widget))
- return FALSE;
-
- expander = E_EXPANDER (widget);
-
- switch (i)
- {
- case ACTIVATE:
- g_signal_emit_by_name (expander, "activate");
- return TRUE;
- default:
- return FALSE;
- }
-}
-
-static gint
-ea_expander_get_n_actions (AtkAction *action)
-{
- return LAST_ACTION;
-}
-
-static void
-atk_action_interface_init (AtkActionIface *iface)
-{
- g_return_if_fail (iface != NULL);
-
- iface->do_action = ea_expander_do_action;
- iface->get_n_actions = ea_expander_get_n_actions;
- iface->get_name = ea_expander_action_get_name;
-}
-
-static void
-ea_expander_class_init (EaExpanderClass *klass)
-{
- AtkObjectClass *atk_object_class = ATK_OBJECT_CLASS (klass);
-
- parent_class = g_type_class_ref (parent_type);
-
- atk_object_class->get_name = ea_expander_get_name;
-}
-
-static void
-ea_expander_init (EaExpander *a11y)
-{
- /* Empty */
-}
-
-GType
-ea_expander_get_type (void)
-{
- static GType type = 0;
-
- if (!type) {
- AtkObjectFactory *factory;
- GTypeQuery query;
-
- GTypeInfo info = {
- sizeof (EaExpanderClass),
- (GBaseInitFunc) NULL,
- (GBaseFinalizeFunc) NULL,
- (GClassInitFunc) ea_expander_class_init,
- (GClassFinalizeFunc) NULL,
- NULL, /* class data */
- sizeof (EaExpander),
- 0,
- (GInstanceInitFunc) ea_expander_init,
- NULL /* value_tree */
- };
-
- static const GInterfaceInfo atk_action_info = {
- (GInterfaceInitFunc) atk_action_interface_init,
- (GInterfaceFinalizeFunc) NULL,
- NULL
- };
-
- factory = atk_registry_get_factory (atk_get_default_registry (), GTK_TYPE_BIN);
- parent_type = atk_object_factory_get_accessible_type (factory);
- g_type_query (parent_type, &query);
-
- info.class_size = query.class_size;
- info.instance_size = query.instance_size;
-
- type = g_type_register_static (parent_type, "EaExpander", &info, 0);
- g_type_add_interface_static (type, ATK_TYPE_ACTION,
- &atk_action_info);
- }
-
- return type;
-}
-
-AtkObject *
-ea_expander_new (GtkWidget *widget)
-{
- EaExpander *a11y;
-
- a11y = g_object_new (ea_expander_get_type (), NULL);
-
- GTK_ACCESSIBLE (a11y)->widget = GTK_WIDGET (widget);
- ATK_OBJECT (a11y)->role = ATK_ROLE_TOGGLE_BUTTON;
-
- return ATK_OBJECT (a11y);
-}
-
diff --git a/a11y/widgets/ea-expander.h b/a11y/widgets/ea-expander.h
deleted file mode 100644
index e670ad0..0000000
--- a/a11y/widgets/ea-expander.h
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) version 3.
- *
- * 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
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with the program; if not, see <http://www.gnu.org/licenses/>
- *
- *
- * Authors:
- * Boby Wang <boby wang sun com>
- *
- * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
- *
- */
-
-#ifndef _EA_EXPANDER_H_
-#define _EA_EXPANDER_H_
-
-#include <gtk/gtk.h>
-#include <misc/e-expander.h>
-
-#define EA_TYPE_EXPANDER (ea_expander_get_type ())
-#define EA_EXPANDER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), EA_TYPE_EXPANDER, EaExpander))
-#define EA_EXPANDER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass,), EA_TYPE_EXPANDER, EaExpanderClass))
-#define EA_IS_EXPANDER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), EA_TYPE_EXPANDER))
-#define EA_IS_EXPANDER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), EA_TYPE_EXPANDER_CLASS))
-
-typedef struct _EaExpander EaExpander;
-typedef struct _EaExpanderClass EaExpanderClass;
-
-struct _EaExpander {
- GtkAccessible object;
-};
-
-struct _EaExpanderClass {
- GtkAccessibleClass parent_class;
-};
-
-/* Standard Glib function */
-GType ea_expander_get_type (void);
-AtkObject* ea_expander_new (GtkWidget *expander);
-
-#endif /* ! _EA_EXPANDER_H_ */
diff --git a/a11y/widgets/ea-widgets.c b/a11y/widgets/ea-widgets.c
index 66c1668..5befb44 100644
--- a/a11y/widgets/ea-widgets.c
+++ b/a11y/widgets/ea-widgets.c
@@ -23,12 +23,10 @@
#include "ea-factory.h"
#include "widgets/ea-calendar-item.h"
#include "widgets/ea-combo-button.h"
-#include "widgets/ea-expander.h"
#include "ea-widgets.h"
EA_FACTORY_GOBJECT (EA_TYPE_CALENDAR_ITEM, ea_calendar_item, ea_calendar_item_new)
EA_FACTORY (EA_TYPE_COMBO_BUTTON, ea_combo_button, ea_combo_button_new)
-EA_FACTORY (EA_TYPE_EXPANDER, ea_expander, ea_expander_new)
void e_calendar_item_a11y_init (void)
{
@@ -39,8 +37,3 @@ void e_combo_button_a11y_init (void)
{
EA_SET_FACTORY (e_combo_button_get_type (), ea_combo_button);
}
-
-void e_expander_a11y_init (void)
-{
- EA_SET_FACTORY (e_expander_get_type (), ea_expander);
-}
diff --git a/a11y/widgets/ea-widgets.h b/a11y/widgets/ea-widgets.h
index f4aff74..20c1c96 100644
--- a/a11y/widgets/ea-widgets.h
+++ b/a11y/widgets/ea-widgets.h
@@ -29,6 +29,5 @@
void e_calendar_item_a11y_init (void);
void e_combo_button_a11y_init (void);
-void e_expander_a11y_init (void);
#endif /* _EA_WIDGETS_H__ */
diff --git a/calendar/gui/Makefile.am b/calendar/gui/Makefile.am
index e61f6a1..b5dab7a 100644
--- a/calendar/gui/Makefile.am
+++ b/calendar/gui/Makefile.am
@@ -69,6 +69,8 @@ etspec_DATA = \
libevolution_calendar_la_SOURCES = \
$(IDL_GENERATED) \
+ e-attachment-handler-calendar.c \
+ e-attachment-handler-calendar.h \
cal-search-bar.c \
cal-search-bar.h \
calendar-config.c \
diff --git a/calendar/gui/calendar-component.c b/calendar/gui/calendar-component.c
index 942960b..4d30929 100644
--- a/calendar/gui/calendar-component.c
+++ b/calendar/gui/calendar-component.c
@@ -58,6 +58,7 @@
#include "e-util/e-error.h"
#include "e-cal-menu.h"
#include "e-cal-popup.h"
+#include "e-attachment-handler-calendar.h"
/* IDs for user creatable items */
#define CREATE_EVENT_ID "event"
@@ -1576,6 +1577,9 @@ calendar_component_class_init (CalendarComponentClass *class)
object_class->dispose = impl_dispose;
object_class->finalize = impl_finalize;
+
+ /* Register attachment handler types. */
+ e_attachment_handler_calendar_get_type ();
}
static void
diff --git a/calendar/gui/dialogs/comp-editor.c b/calendar/gui/dialogs/comp-editor.c
index f303435..6456a5c 100644
--- a/calendar/gui/dialogs/comp-editor.c
+++ b/calendar/gui/dialogs/comp-editor.c
@@ -63,9 +63,9 @@
#include "../e-cal-popup.h"
#include "../calendar-config-keys.h"
#include "cal-attachment-select-file.h"
+#include "widgets/misc/e-attachment-view.h"
+#include "widgets/misc/e-attachment-paned.h"
-#include "e-attachment-bar.h"
-#include "misc/e-expander.h"
#include "e-util/e-error.h"
#define COMP_EDITOR_GET_PRIVATE(obj) \
@@ -95,12 +95,7 @@ struct _CompEditorPrivate {
GtkNotebook *notebook;
/* Attachment handling */
- GtkWidget *attachment_bar;
- GtkWidget *attachment_scrolled_window;
- GtkWidget *attachment_expander;
- GtkWidget *attachment_expander_label;
- GtkWidget *attachment_expander_icon;
- GtkWidget *attachment_expander_num;
+ GtkWidget *attachment_view;
/* Manages menus and toolbars */
GtkUIManager *manager;
@@ -151,7 +146,7 @@ static const gchar *ui =
" <menu action='view-menu'/>"
" <menu action='insert-menu'>"
" <menuitem action='attach'/>"
-" <menuitem action='attach-recent'/>"
+" <placeholder name='recent-placeholder'/>"
" </menu>"
" <menu action='options-menu'/>"
" <menu action='help-menu'>"
@@ -163,13 +158,10 @@ static const gchar *ui =
" <toolitem action='print'/>"
" <toolitem action='close'/>"
" <separator/>"
-" <toolitem action='attach'/>"
-" <separator/>"
" </toolbar>"
"</ui>";
static void comp_editor_show_help (CompEditor *editor);
-static void setup_widgets (CompEditor *editor);
static void real_edit_comp (CompEditor *editor, ECalComponent *comp);
static gboolean real_send_comp (CompEditor *editor, ECalComponentItipMethod method, gboolean strip_alarms);
@@ -180,441 +172,63 @@ static void page_dates_changed_cb (CompEditor *editor, CompEditorPageDates *date
static void obj_modified_cb (ECal *client, GList *objs, gpointer data);
static void obj_removed_cb (ECal *client, GList *uids, gpointer data);
-static gboolean open_attachment (EAttachmentBar *bar, CompEditor *editor);
G_DEFINE_TYPE (CompEditor, comp_editor, GTK_TYPE_WINDOW)
enum {
- DND_TYPE_MESSAGE_RFC822,
- DND_TYPE_X_UID_LIST,
- DND_TYPE_TEXT_URI_LIST,
- DND_TYPE_NETSCAPE_URL,
- DND_TYPE_TEXT_VCARD,
- DND_TYPE_TEXT_CALENDAR,
-};
-
-static GtkTargetEntry drop_types[] = {
- { "message/rfc822", 0, DND_TYPE_MESSAGE_RFC822 },
- { "x-uid-list", 0, DND_TYPE_X_UID_LIST },
- { "text/uri-list", 0, DND_TYPE_TEXT_URI_LIST },
- { "_NETSCAPE_URL", 0, DND_TYPE_NETSCAPE_URL },
- { "text/x-vcard", 0, DND_TYPE_TEXT_VCARD },
- { "text/calendar", 0, DND_TYPE_TEXT_CALENDAR },
-};
-
-#define num_drop_types (sizeof (drop_types) / sizeof (drop_types[0]))
-
-static struct {
- char *target;
- GdkAtom atom;
- guint32 actions;
-} drag_info[] = {
- { "message/rfc822", NULL, GDK_ACTION_COPY },
- { "x-uid-list", NULL, GDK_ACTION_ASK|GDK_ACTION_MOVE|GDK_ACTION_COPY },
- { "text/uri-list", NULL, GDK_ACTION_COPY },
- { "_NETSCAPE_URL", NULL, GDK_ACTION_COPY },
- { "text/x-vcard", NULL, GDK_ACTION_COPY },
- { "text/calendar", NULL, GDK_ACTION_COPY },
-};
-
-enum {
OBJECT_CREATED,
LAST_SIGNAL
};
static guint comp_editor_signals[LAST_SIGNAL] = { 0 };
-static void
-attach_message(CompEditor *editor, CamelMimeMessage *msg)
-{
- CamelMimePart *mime_part;
- const char *subject;
- guint i;
- char *filename = NULL;
-
- mime_part = camel_mime_part_new();
- camel_mime_part_set_disposition(mime_part, "inline");
- subject = camel_mime_message_get_subject(msg);
- if (subject) {
- char *desc = g_strdup_printf(_("Attached message - %s"), subject);
-
- camel_mime_part_set_description(mime_part, desc);
- g_free(desc);
- } else
- camel_mime_part_set_description(mime_part, _("Attached message"));
-
- i = e_attachment_bar_get_num_attachments (E_ATTACHMENT_BAR (editor->priv->attachment_bar));
- i++;
- filename = g_strdup_printf ("email%d",i);
- camel_mime_part_set_filename (mime_part, filename);
-
- camel_medium_set_content_object((CamelMedium *)mime_part, (CamelDataWrapper *)msg);
- camel_mime_part_set_content_type(mime_part, "message/rfc822");
- e_attachment_bar_attach_mime_part(E_ATTACHMENT_BAR(editor->priv->attachment_bar), mime_part);
- camel_object_unref(mime_part);
- g_free (filename);
-}
-
-struct _drop_data {
- CompEditor *editor;
-
- GdkDragContext *context;
- /* Only selection->data and selection->length are valid */
- GtkSelectionData *selection;
-
- guint32 action;
- guint info;
- guint time;
-
- unsigned int move:1;
- unsigned int moved:1;
- unsigned int aborted:1;
-};
-
-static void
-drop_action(CompEditor *editor, GdkDragContext *context, guint32 action, GtkSelectionData *selection, guint info, guint time)
-{
- char *tmp, *str, **urls;
- CamelMimePart *mime_part;
- CamelStream *stream;
- CamelURL *url;
- CamelMimeMessage *msg;
- char *content_type;
- int i, success=FALSE, delete=FALSE;
-
- switch (info) {
- case DND_TYPE_MESSAGE_RFC822:
- d(printf ("dropping a message/rfc822\n"));
- /* write the message(s) out to a CamelStream so we can use it */
- stream = camel_stream_mem_new ();
- camel_stream_write (stream, (char *)selection->data, selection->length);
- camel_stream_reset (stream);
-
- msg = camel_mime_message_new ();
- if (camel_data_wrapper_construct_from_stream((CamelDataWrapper *)msg, stream) != -1) {
- attach_message(editor, msg);
- success = TRUE;
- delete = action == GDK_ACTION_MOVE;
- }
-
- camel_object_unref(msg);
- camel_object_unref(stream);
- break;
- case DND_TYPE_TEXT_URI_LIST:
- case DND_TYPE_NETSCAPE_URL:
- d(printf ("dropping a text/uri-list\n"));
- tmp = g_strndup ((char *)selection->data, selection->length);
- urls = g_strsplit (tmp, "\n", 0);
- g_free (tmp);
-
- for (i = 0; urls[i] != NULL; i++) {
- str = g_strstrip (urls[i]);
- if (urls[i][0] == '#')
- continue;
-
- if (!g_ascii_strncasecmp (str, "mailto:", 7)) {
- /* TODO does not handle mailto now */
- } else {
- url = camel_url_new (str, NULL);
-
- if (url == NULL)
- continue;
-
- if (!g_ascii_strcasecmp (url->protocol, "file"))
- e_attachment_bar_attach
- (E_ATTACHMENT_BAR (editor->priv->attachment_bar),
- url->path,
- "attachment");
- else
- e_attachment_bar_attach_remote_file
- (E_ATTACHMENT_BAR (editor->priv->attachment_bar),
- str, "attachment");
-
- camel_url_free (url);
- }
- }
-
- g_strfreev (urls);
- success = TRUE;
- break;
- case DND_TYPE_TEXT_VCARD:
- case DND_TYPE_TEXT_CALENDAR:
- content_type = gdk_atom_name (selection->type);
- d(printf ("dropping a %s\n", content_type));
-
- mime_part = camel_mime_part_new ();
- camel_mime_part_set_content (mime_part, (char *)selection->data, selection->length, content_type);
- camel_mime_part_set_disposition (mime_part, "inline");
-
- e_attachment_bar_attach_mime_part
- (E_ATTACHMENT_BAR (editor->priv->attachment_bar),
- mime_part);
-
- camel_object_unref (mime_part);
- g_free (content_type);
-
- success = TRUE;
- break;
- case DND_TYPE_X_UID_LIST: {
- GPtrArray *uids;
- char *inptr, *inend;
- CamelFolder *folder;
- CamelException ex = CAMEL_EXCEPTION_INITIALISER;
-
- /* NB: This all runs synchronously, could be very slow/hang/block the ui */
-
- uids = g_ptr_array_new();
-
- inptr = (char *)selection->data;
- inend = (char *)(selection->data + selection->length);
- while (inptr < inend) {
- char *start = inptr;
-
- while (inptr < inend && *inptr)
- inptr++;
-
- if (start > (char *)selection->data)
- g_ptr_array_add(uids, g_strndup(start, inptr-start));
-
- inptr++;
- }
-
- if (uids->len > 0) {
- folder = mail_tool_uri_to_folder((char *)selection->data, 0, &ex);
- if (folder) {
- if (uids->len == 1) {
- msg = camel_folder_get_message(folder, uids->pdata[0], &ex);
- if (msg == NULL)
- goto fail;
- attach_message(editor, msg);
- } else {
- CamelMultipart *mp = camel_multipart_new();
- char *desc;
- char *filename = NULL;
- guint num;
-
- camel_data_wrapper_set_mime_type((CamelDataWrapper *)mp, "multipart/digest");
- camel_multipart_set_boundary(mp, NULL);
- for (i=0;i<uids->len;i++) {
-
- msg = camel_folder_get_message(folder, uids->pdata[i], &ex);
- if (msg) {
- mime_part = camel_mime_part_new();
- camel_mime_part_set_disposition(mime_part, "inline");
- camel_medium_set_content_object((CamelMedium *)mime_part, (CamelDataWrapper *)msg);
- camel_mime_part_set_content_type(mime_part, "message/rfc822");
- camel_multipart_add_part(mp, mime_part);
- camel_object_unref(mime_part);
- camel_object_unref(msg);
- } else {
- camel_object_unref(mp);
- goto fail;
- }
- }
- mime_part = camel_mime_part_new();
- camel_medium_set_content_object((CamelMedium *)mime_part, (CamelDataWrapper *)mp);
- /* translators, this count will always be >1 */
- 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);
-
- num = e_attachment_bar_get_num_attachments (E_ATTACHMENT_BAR (editor->priv->attachment_bar));
- num++;
- filename = g_strdup_printf ("email%d", num);
- camel_mime_part_set_filename (mime_part, filename);
-
- e_attachment_bar_attach_mime_part
- (E_ATTACHMENT_BAR(editor->priv->attachment_bar), mime_part);
- camel_object_unref(mime_part);
- camel_object_unref(mp);
- g_free (filename);
- }
- success = TRUE;
- delete = action == GDK_ACTION_MOVE;
- fail:
- if (camel_exception_is_set(&ex)) {
- char *name;
-
- camel_object_get(folder, NULL, CAMEL_FOLDER_NAME, &name, NULL);
- e_error_run((GtkWindow *)editor, "mail-editor:attach-nomessages",
- name?name:(char *)selection->data, camel_exception_get_description(&ex), NULL);
- camel_object_free(folder, CAMEL_FOLDER_NAME, name);
- }
- camel_object_unref(folder);
- } else {
- e_error_run((GtkWindow *)editor, "mail-editor:attach-nomessages",
- (char *)selection->data, camel_exception_get_description(&ex), NULL);
- }
-
- camel_exception_clear(&ex);
- }
-
- g_ptr_array_free(uids, TRUE);
-
- break; }
- default:
- d(printf ("dropping an unknown\n"));
- break;
- }
-
- printf("Drag finished, success %d delete %d\n", success, delete);
-
- gtk_drag_finish(context, success, delete, time);
-}
-
-static void
-drop_popup_copy (EPopup *ep, EPopupItem *item, void *data)
-{
- struct _drop_data *m = data;
- drop_action(m->editor, m->context, GDK_ACTION_COPY, m->selection, m->info, m->time);
-}
-
-static void
-drop_popup_move (EPopup *ep, EPopupItem *item, void *data)
-{
- struct _drop_data *m = data;
- drop_action(m->editor, m->context, GDK_ACTION_MOVE, m->selection, m->info, m->time);
-}
-
-static void
-drop_popup_cancel(EPopup *ep, EPopupItem *item, void *data)
-{
- struct _drop_data *m = data;
- gtk_drag_finish(m->context, FALSE, FALSE, m->time);
-}
-
-static EPopupItem drop_popup_menu[] = {
- { E_POPUP_ITEM, "00.emc.02", N_("_Copy"), drop_popup_copy, NULL, "mail-copy", 0 },
- { E_POPUP_ITEM, "00.emc.03", N_("_Move"), drop_popup_move, NULL, "mail-move", 0 },
- { E_POPUP_BAR, "10.emc" },
- { E_POPUP_ITEM, "99.emc.00", N_("Cancel _Drag"), drop_popup_cancel, NULL, NULL, 0 },
-};
-
-static void
-drop_popup_free(EPopup *ep, GSList *items, void *data)
-{
- struct _drop_data *m = data;
-
- g_slist_free(items);
-
- g_object_unref(m->context);
- g_object_unref(m->editor);
- g_free(m->selection->data);
- g_free(m->selection);
- g_free(m);
-}
-
-static void
-drag_data_received (CompEditor *editor, GdkDragContext *context,
- int x, int y, GtkSelectionData *selection,
- guint info, guint time)
-{
- if (selection->data == NULL || selection->length == -1)
- return;
-
- if (context->action == GDK_ACTION_ASK) {
- ECalPopup *ecp;
- GSList *menus = NULL;
- GtkMenu *menu;
- int i;
- struct _drop_data *m;
-
- m = g_malloc0(sizeof(*m));
- m->context = context;
- g_object_ref(context);
- m->editor = editor;
- g_object_ref(editor);
- m->action = context->action;
- m->info = info;
- m->time = time;
- m->selection = g_malloc0(sizeof(*m->selection));
- m->selection->data = g_malloc(selection->length);
- memcpy(m->selection->data, selection->data, selection->length);
- m->selection->length = selection->length;
-
- ecp = e_cal_popup_new("org.gnome.evolution.calendar.editor.popup.drop");
- for (i=0;i<sizeof(drop_popup_menu)/sizeof(drop_popup_menu[0]);i++)
- menus = g_slist_append(menus, &drop_popup_menu[i]);
-
- e_popup_add_items((EPopup *)ecp, menus, NULL, drop_popup_free, m);
- menu = e_popup_create_menu_once((EPopup *)ecp, NULL, 0);
- gtk_menu_popup(menu, NULL, NULL, NULL, NULL, 0, time);
- } else {
- drop_action(editor, context, context->action, selection, info, time);
- }
-}
-
-static gboolean
-drag_motion(GObject *o, GdkDragContext *context, gint x, gint y, guint time, CompEditor *editor)
-{
- GList *targets;
- GdkDragAction action, actions = 0;
-
- for (targets = context->targets; targets; targets = targets->next) {
- int i;
-
- for (i=0;i<sizeof(drag_info)/sizeof(drag_info[0]);i++)
- if (targets->data == (void *)drag_info[i].atom)
- actions |= drag_info[i].actions;
- }
-
- actions &= context->actions;
- action = context->suggested_action;
- /* we default to copy */
- if (action == GDK_ACTION_ASK && (actions & (GDK_ACTION_MOVE|GDK_ACTION_COPY)) != (GDK_ACTION_MOVE|GDK_ACTION_COPY))
- action = GDK_ACTION_COPY;
-
- gdk_drag_status(context, action, time);
-
- return action != 0;
-}
-
-static void
-add_to_bar (CompEditor *editor, GPtrArray *file_list, int is_inline)
-{
- CompEditorPrivate *priv = editor->priv;
- int i;
-
- for (i = 0; i < file_list->len; i++) {
- CamelURL *url;
-
- if (!(url = camel_url_new (file_list->pdata[i], NULL)))
- continue;
-
- if (!g_ascii_strcasecmp (url->protocol, "file")) {
- e_attachment_bar_attach((EAttachmentBar *)priv->attachment_bar, url->path, is_inline ? "inline" : "attachment");
- } else {
- e_attachment_bar_attach_remote_file ((EAttachmentBar *)priv->attachment_bar, file_list->pdata[i], is_inline ? "inline" : "attachment");
- }
-
- camel_url_free (url);
- }
-}
-
static GSList *
get_attachment_list (CompEditor *editor)
{
- GSList *parts = NULL, *list = NULL, *p = NULL;
+ EAttachmentStore *store;
+ EAttachmentView *view;
+ GtkTreeModel *model;
+ GtkTreeIter iter;
+ GSList *parts = NULL, *list = NULL;
const char *comp_uid = NULL;
const char *local_store = e_cal_get_local_attachment_store (editor->priv->client);
+ gboolean valid;
int ticker=0;
+
e_cal_component_get_uid (editor->priv->comp, &comp_uid);
- parts = e_attachment_bar_get_parts((EAttachmentBar *)editor->priv->attachment_bar);
+ view = E_ATTACHMENT_VIEW (editor->priv->attachment_view);
+ store = e_attachment_view_get_store (view);
- for (p = parts; p!=NULL ; p = p->next) {
+ model = GTK_TREE_MODEL (store);
+ valid = gtk_tree_model_get_iter_first (model, &iter);
+
+ while (valid) {
+ EAttachment *attachment;
CamelDataWrapper *wrapper;
+ CamelMimePart *mime_part;
CamelStream *stream;
char *attach_file_url;
char *safe_fname, *utf8_safe_fname;
char *filename;
+ gint column_id;
+
+ column_id = E_ATTACHMENT_STORE_COLUMN_ATTACHMENT;
+ gtk_tree_model_get (model, &iter, column_id, &attachment, -1);
+ mime_part = e_attachment_get_mime_part (attachment);
+ g_object_unref (attachment);
+
+ valid = gtk_tree_model_iter_next (model, &iter);
- wrapper = camel_medium_get_content_object (CAMEL_MEDIUM (p->data));
+ if (mime_part == NULL)
+ continue;
+
+ wrapper = camel_medium_get_content_object (CAMEL_MEDIUM (mime_part));
/* Extract the content from the stream and write it down
* as a mime part file into the directory denoting the
* calendar source */
- utf8_safe_fname = camel_file_util_safe_filename (camel_mime_part_get_filename ((CamelMimePart *) p->data));
+ utf8_safe_fname = camel_file_util_safe_filename (camel_mime_part_get_filename (mime_part));
/* It is absolutely fine to get a NULL from the filename of
* mime part. We assume that it is named "Attachment"
@@ -993,20 +607,21 @@ static void
action_attach_cb (GtkAction *action,
CompEditor *editor)
{
- GPtrArray *file_list;
- gboolean is_inline = FALSE;
- int i;
-
- file_list = comp_editor_select_file_attachments (editor, &is_inline);
+ EAttachmentStore *store;
+ EAttachmentView *view;
- if (file_list) {
- add_to_bar (editor, file_list, is_inline);
+ view = E_ATTACHMENT_VIEW (editor->priv->attachment_view);
+ store = e_attachment_view_get_store (view);
- for (i = 0; i < file_list->len; i++)
- g_free (file_list->pdata[i]);
+ e_attachment_store_run_load_dialog (store, GTK_WINDOW (editor));
+}
- g_ptr_array_free (file_list, TRUE);
- }
+static void
+action_classification_cb (GtkRadioAction *action,
+ GtkRadioAction *current,
+ CompEditor *editor)
+{
+ comp_editor_set_changed (editor, TRUE);
}
static void
@@ -1132,12 +747,17 @@ action_save_cb (GtkAction *action,
CompEditor *editor)
{
CompEditorPrivate *priv = editor->priv;
+ EAttachmentStore *store;
+ EAttachmentView *view;
ECalComponentText text;
gboolean delegated = FALSE;
gboolean read_only, correct = FALSE;
ECalComponent *comp;
- if (e_attachment_bar_get_download_count (E_ATTACHMENT_BAR (editor->priv->attachment_bar)) ){
+ view = E_ATTACHMENT_VIEW (priv->attachment_view);
+ store = e_attachment_view_get_store (view);
+
+ if (e_attachment_store_get_num_loading (store) > 0) {
gboolean response = 1;
/*FIXME: Cannot use mail functions from calendar!!!! */
#if 0
@@ -1520,6 +1140,40 @@ static GtkToggleActionEntry coordinated_toggle_entries[] = {
};
static void
+comp_editor_setup_recent_menu (CompEditor *editor)
+{
+ EAttachmentView *view;
+ GtkUIManager *ui_manager;
+ GtkAction *action;
+ GtkActionGroup *action_group;
+ const gchar *action_name;
+ const gchar *path;
+ guint merge_id;
+
+ ui_manager = editor->priv->manager;
+ view = E_ATTACHMENT_VIEW (editor->priv->attachment_view);
+ action_group = comp_editor_get_action_group (editor, "individual");
+ merge_id = gtk_ui_manager_new_merge_id (ui_manager);
+ path = "/main-menu/insert-menu/recent-placeholder";
+ action_name = "recent-menu";
+
+ action = e_attachment_view_recent_action_new (
+ view, action_name, _("Recent _Documents"));
+
+ if (action != NULL) {
+ gtk_action_group_add_action (action_group, action);
+ g_object_unref (action);
+
+ gtk_ui_manager_add_ui (
+ ui_manager, merge_id, path,
+ action_name, action_name,
+ GTK_UI_MANAGER_AUTO, FALSE);
+ }
+
+ gtk_ui_manager_ensure_update (ui_manager);
+}
+
+static void
comp_editor_set_property (GObject *object,
guint property_id,
const GValue *value,
@@ -1695,15 +1349,89 @@ comp_editor_map (GtkWidget *widget)
GTK_WIDGET_CLASS (comp_editor_parent_class)->map (widget);
}
+static gboolean
+comp_editor_delete_event (GtkWidget *widget,
+ GdkEventAny *event)
+{
+ CompEditor *editor;
+
+ editor = COMP_EDITOR (widget);
+
+ commit_all_fields (editor);
+
+ if (prompt_and_save_changes (editor, TRUE))
+ close_dialog (editor);
+
+ return TRUE;
+}
+
+static gboolean
+comp_editor_key_press_event (GtkWidget *widget,
+ GdkEventKey *event)
+{
+ CompEditor *editor;
+
+ editor = COMP_EDITOR (widget);
+
+ if (event->keyval == GDK_Escape) {
+ commit_all_fields (editor);
+
+ if (prompt_and_save_changes (editor, TRUE))
+ close_dialog (editor);
+
+ return TRUE;
+ }
+
+ /* Chain up to parent's key_press_event() method. */
+ return GTK_WIDGET_CLASS (comp_editor_parent_class)->
+ key_press_event (widget, event);
+}
+
+static gboolean
+comp_editor_drag_motion (GtkWidget *widget,
+ GdkDragContext *context,
+ gint x,
+ gint y,
+ guint time)
+{
+ CompEditorPrivate *priv;
+ EAttachmentView *view;
+
+ priv = COMP_EDITOR_GET_PRIVATE (widget);
+ view = E_ATTACHMENT_VIEW (priv->attachment_view);
+
+ return e_attachment_view_drag_motion (view, context, x, y, time);
+}
+
+static void
+comp_editor_drag_data_received (GtkWidget *widget,
+ GdkDragContext *context,
+ gint x,
+ gint y,
+ GtkSelectionData *selection,
+ guint info,
+ guint time)
+{
+ CompEditorPrivate *priv;
+ EAttachmentView *view;
+
+ priv = COMP_EDITOR_GET_PRIVATE (widget);
+ view = E_ATTACHMENT_VIEW (priv->attachment_view);
+
+ /* Forward the data to the attachment view. Note that calling
+ * e_attachment_view_drag_data_received() will not work because
+ * that function only handles the case where all the other drag
+ * handlers have failed. */
+ e_attachment_paned_drag_data_received (
+ E_ATTACHMENT_PANED (view),
+ context, x, y, selection, info, time);
+}
+
static void
comp_editor_class_init (CompEditorClass *class)
{
GObjectClass *object_class;
GtkWidgetClass *widget_class;
- int i;
-
- for (i = 0; i < G_N_ELEMENTS (drag_info); i++)
- drag_info[i].atom = gdk_atom_intern(drag_info[i].target, FALSE);
g_type_class_add_private (class, sizeof (CompEditorPrivate));
@@ -1715,6 +1443,10 @@ comp_editor_class_init (CompEditorClass *class)
widget_class = GTK_WIDGET_CLASS (class);
widget_class->map = comp_editor_map;
+ widget_class->delete_event = comp_editor_delete_event;
+ widget_class->key_press_event = comp_editor_key_press_event;
+ widget_class->drag_motion = comp_editor_drag_motion;
+ widget_class->drag_data_received = comp_editor_drag_data_received;
class->help_section = "usage-calendar";
class->edit_comp = real_edit_comp;
@@ -1777,19 +1509,18 @@ comp_editor_class_init (CompEditorClass *class)
}
static void
-classification_changed_cb (GtkRadioAction *action, GtkRadioAction *current, CompEditor *editor)
-{
- g_return_if_fail (IS_COMP_EDITOR (editor));
-
- comp_editor_set_changed (editor, TRUE);
-}
-
-static void
comp_editor_init (CompEditor *editor)
{
CompEditorPrivate *priv;
+ EAttachmentView *view;
+ GdkDragAction drag_actions;
+ GtkTargetList *target_list;
+ GtkTargetEntry *targets;
GtkActionGroup *action_group;
GtkAction *action;
+ GtkWidget *container;
+ GtkWidget *widget;
+ gint n_targets;
GError *error = NULL;
editor->priv = priv = COMP_EDITOR_GET_PRIVATE (editor);
@@ -1798,17 +1529,18 @@ comp_editor_init (CompEditor *editor)
priv->changed = FALSE;
priv->needs_send = FALSE;
priv->mod = CALOBJ_MOD_ALL;
- priv->existing_org = FALSE;
- priv->user_org = FALSE;
- priv->warned = FALSE;
+ priv->existing_org = FALSE;
+ priv->user_org = FALSE;
+ priv->warned = FALSE;
priv->is_group_item = FALSE;
- priv->attachment_bar = e_attachment_bar_new (NULL);
priv->manager = gtk_ui_manager_new ();
- gtk_window_add_accel_group (
- GTK_WINDOW (editor),
- gtk_ui_manager_get_accel_group (priv->manager));
+ gtk_window_add_accel_group (
+ GTK_WINDOW (editor),
+ gtk_ui_manager_get_accel_group (priv->manager));
+
+ /* Setup Action Groups */
action_group = gtk_action_group_new ("core");
gtk_action_group_set_translation_domain (
@@ -1833,11 +1565,7 @@ comp_editor_init (CompEditor *editor)
action_group, classification_radio_entries,
G_N_ELEMENTS (classification_radio_entries),
E_CAL_COMPONENT_CLASS_PUBLIC,
- G_CALLBACK (classification_changed_cb), editor);
- action = e_attachment_bar_recent_action_new (
- E_ATTACHMENT_BAR (priv->attachment_bar),
- "attach-recent", _("Recent _Documents"));
- gtk_action_group_add_action (action_group, action);
+ G_CALLBACK (action_classification_cb), editor);
gtk_ui_manager_insert_action_group (
priv->manager, action_group, 0);
g_object_unref (action_group);
@@ -1867,14 +1595,57 @@ comp_editor_init (CompEditor *editor)
g_error_free (error);
}
- setup_widgets (editor);
+ /* Setup Widgets */
+
+ container = GTK_WIDGET (editor);
+
+ widget = gtk_vbox_new (FALSE, 0);
+ gtk_container_add (GTK_CONTAINER (container), widget);
+ gtk_widget_show (widget);
+
+ container = widget;
+
+ widget = comp_editor_get_managed_widget (editor, "/main-menu");
+ gtk_box_pack_start (GTK_BOX (container), widget, FALSE, FALSE, 0);
+ gtk_widget_show (widget);
+
+ widget = comp_editor_get_managed_widget (editor, "/main-toolbar");
+ gtk_box_pack_start (GTK_BOX (container), widget, FALSE, FALSE, 0);
+ gtk_widget_show (widget);
+
+ widget = e_attachment_paned_new ();
+ gtk_container_set_border_width (GTK_CONTAINER (widget), 6);
+ gtk_box_pack_start (GTK_BOX (container), widget, TRUE, TRUE, 0);
+ priv->attachment_view = g_object_ref (widget);
+ gtk_widget_show (widget);
+
+ container = e_attachment_paned_get_content_area (
+ E_ATTACHMENT_PANED (priv->attachment_view));
+
+ widget = gtk_notebook_new ();
+ gtk_notebook_set_show_tabs (GTK_NOTEBOOK (widget), FALSE);
+ gtk_box_pack_start (GTK_BOX (container), widget, TRUE, TRUE, 0);
+ priv->notebook = GTK_NOTEBOOK (widget);
+ gtk_widget_show (widget);
+
+ comp_editor_setup_recent_menu (editor);
- /* DND support */
- gtk_drag_dest_set (GTK_WIDGET (editor), GTK_DEST_DEFAULT_ALL, drop_types, num_drop_types, GDK_ACTION_COPY|GDK_ACTION_ASK|GDK_ACTION_MOVE);
- g_signal_connect(editor, "drag_data_received", G_CALLBACK (drag_data_received), NULL);
- g_signal_connect(editor, "drag-motion", G_CALLBACK(drag_motion), editor);
+ /* Drag-and-Drop Support */
- gtk_window_set_type_hint (GTK_WINDOW (editor), GDK_WINDOW_TYPE_HINT_NORMAL);
+ view = E_ATTACHMENT_VIEW (priv->attachment_view);
+ target_list = e_attachment_view_get_target_list (view);
+ drag_actions = e_attachment_view_get_drag_actions (view);
+
+ targets = gtk_target_table_new_from_list (target_list, &n_targets);
+
+ gtk_drag_dest_set (
+ GTK_WIDGET (editor), GTK_DEST_DEFAULT_ALL,
+ targets, n_targets, drag_actions);
+
+ gtk_target_table_free (targets, n_targets);
+
+ gtk_window_set_type_hint (
+ GTK_WINDOW (editor), GDK_WINDOW_TYPE_HINT_NORMAL);
}
static gboolean
@@ -1927,402 +1698,17 @@ prompt_and_save_changes (CompEditor *editor, gboolean send)
}
}
-static int
-delete_event_cb (GtkWidget *widget, GdkEvent *event, gpointer data)
-{
- CompEditor *editor = COMP_EDITOR (data);
-
- commit_all_fields (editor);
-
- if (prompt_and_save_changes (editor, TRUE))
- close_dialog (editor);
-
- return TRUE;
-}
-
static void
-attachment_bar_changed_cb (EAttachmentBar *bar,
- void *data)
+attachment_store_changed_cb (CompEditor *editor)
{
- CompEditor *editor = COMP_EDITOR (data);
-
- 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),
- attachment_num);
- gtk_label_set_markup (GTK_LABEL (editor->priv->attachment_expander_num),
- num_text);
- g_free (num_text);
-
- gtk_widget_show (editor->priv->attachment_expander_icon);
- e_expander_set_expanded(E_EXPANDER(editor->priv->attachment_expander),TRUE);
-
- } else {
- gtk_label_set_text (GTK_LABEL (editor->priv->attachment_expander_num), "");
- gtk_widget_hide (editor->priv->attachment_expander_icon);
- e_expander_set_expanded(E_EXPANDER(editor->priv->attachment_expander),FALSE);
- }
-
-
/* Mark the editor as changed so it prompts about unsaved
changes on close */
comp_editor_set_changed (editor, TRUE);
-
-}
-
-static void
-attachment_expander_activate_cb (EExpander *expander,
- void *data)
-{
- CompEditor *editor = COMP_EDITOR (data);
- gboolean show = e_expander_get_expanded (expander);
-
- /* Update the expander label */
- if (show)
- gtk_label_set_text_with_mnemonic (GTK_LABEL (editor->priv->attachment_expander_label),
- _("Hide Attachment _Bar"));
- else
- gtk_label_set_text_with_mnemonic (GTK_LABEL (editor->priv->attachment_expander_label),
- _("Show Attachment _Bar"));
-}
-
-static gboolean
-open_attachment (EAttachmentBar *bar, CompEditor *editor)
-{
- GnomeIconList *icon_list;
- GList *p;
- int num;
- char *attach_file_url;
-
- if (E_IS_ATTACHMENT_BAR (bar)) {
- icon_list = GNOME_ICON_LIST (bar);
- p = gnome_icon_list_get_selection (icon_list);
- if (p) {
- EAttachment *attachment;
- GSList *list;
- const char *comp_uid = NULL;
- char *filename = NULL;
- const char *local_store = e_cal_get_local_attachment_store (editor->priv->client);
-
- e_cal_component_get_uid (editor->priv->comp, &comp_uid);
- num = GPOINTER_TO_INT (p->data);
- list = e_attachment_bar_get_attachment (bar, num);
- attachment = list->data;
- g_slist_free (list);
-
- filename = g_strdup_printf ("%s-%s",
- comp_uid,
- camel_mime_part_get_filename(attachment->body));
-
- attach_file_url = g_build_path ("/", local_store, filename, NULL);
-
- /* launch the url now */
- e_show_uri (GTK_WINDOW (editor), attach_file_url);
-
- g_free (filename);
- g_free (attach_file_url); }
- return TRUE;
- } else
- return FALSE;
-}
-
-static gboolean
-attachment_bar_icon_clicked_cb (EAttachmentBar *bar, GdkEvent *event, CompEditor *editor)
-{
- if (E_IS_ATTACHMENT_BAR (bar) && event->type == GDK_2BUTTON_PRESS)
- if (open_attachment (bar, editor))
- return TRUE;
- return FALSE;
-}
-
-/* Callbacks. */
-
-static void
-cab_open(EPopup *ep, EPopupItem *item, void *data)
-{
- EAttachmentBar *bar = data;
- CompEditor *editor = COMP_EDITOR (gtk_widget_get_toplevel (GTK_WIDGET (bar)));
-
- if (!open_attachment (bar, editor))
- g_message ("\n Open failed");
-}
-
-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++) {
- CamelURL *url;
-
- url = camel_url_new (file_list->pdata[i], NULL);
- if (url == NULL)
- continue;
-
- if (!g_ascii_strcasecmp (url->protocol, "file"))
- e_attachment_bar_attach (bar, url->path, is_inline ? "inline" : "attachment");
- else
- e_attachment_bar_attach_remote_file (bar, file_list->pdata[i], is_inline ? "inline" : "attachment");
- g_free (file_list->pdata[i]);
- camel_url_free (url);
- }
-
- 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_("_Open"), cab_open, NULL, GTK_STOCK_OPEN, E_CAL_POPUP_ATTACHMENTS_ONE},
- { E_POPUP_ITEM, "20.attach", N_("_Remove"), cab_remove, NULL, GTK_STOCK_REMOVE, E_CAL_POPUP_ATTACHMENTS_MANY | E_CAL_POPUP_ATTACHMENTS_MODIFY },
- { E_POPUP_ITEM, "30.attach", N_("_Properties"), cab_properties, NULL, GTK_STOCK_PROPERTIES, E_CAL_POPUP_ATTACHMENTS_ONE },
- { E_POPUP_BAR, "40.attach.00", NULL, NULL, NULL, NULL, E_CAL_POPUP_ATTACHMENTS_MANY|E_CAL_POPUP_ATTACHMENTS_ONE },
- { E_POPUP_ITEM, "40.attach.01", N_("_Add attachment..."), cab_add, NULL, GTK_STOCK_ADD, E_CAL_POPUP_ATTACHMENTS_MODIFY},
-};
-
-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, GPOINTER_TO_INT(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)
-{
- GSList *attachments = NULL, *menus = NULL;
- int i;
- ECalPopup *ecp;
- ECalPopupTargetAttachments *t;
- GtkMenu *menu;
- CompEditor *editor = COMP_EDITOR (gtk_widget_get_toplevel (GTK_WIDGET (bar)));
-
- 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, editor, 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 (EAttachmentBar *bar)
-{
- cab_popup (bar, NULL, -1);
-
- return TRUE;
-}
-
-
-static int
-button_press_event (EAttachmentBar *bar,
- GdkEventButton *event)
-{
- GnomeIconList *icon_list = GNOME_ICON_LIST (bar);
- int icon_number = -1;
-
- if (event->button != 3)
- return FALSE;
-
- if (!gnome_icon_list_get_selection (icon_list)) {
- 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 (EAttachmentBar *bar,
- GdkEventKey *event)
-{
- if (event->keyval == GDK_Delete) {
- e_attachment_bar_remove_selected (bar);
- return TRUE;
- }
-
- return FALSE;
-}
-
-static gint
-editor_key_press_event (CompEditor *editor,
- GdkEventKey *event)
-{
- if (event->keyval == GDK_Escape) {
- commit_all_fields (editor);
-
- if (prompt_and_save_changes (editor, TRUE))
- close_dialog (editor);
-
- return TRUE;
- }
-
- return FALSE;
}
/* Menu callbacks */
static void
-setup_widgets (CompEditor *editor)
-{
- CompEditorPrivate *priv;
- GtkWidget *expander_hbox;
- GtkWidget *widget;
- GtkWidget *vbox;
-
- priv = editor->priv;
-
- /* Useful vbox */
- vbox = gtk_vbox_new (FALSE, 0);
- gtk_container_add (GTK_CONTAINER (editor), vbox);
- gtk_widget_show (vbox);
-
- /* Main Menu */
- widget = comp_editor_get_managed_widget (editor, "/main-menu");
- gtk_box_pack_start (GTK_BOX (vbox), widget, FALSE, FALSE, 0);
- gtk_widget_show (widget);
-
- /* Main Toolbar */
- widget = comp_editor_get_managed_widget (editor, "/main-toolbar");
- gtk_box_pack_start (GTK_BOX (vbox), widget, FALSE, FALSE, 0);
- gtk_widget_show (widget);
-
- /* Notebook */
- widget = gtk_notebook_new ();
- gtk_notebook_set_show_tabs (GTK_NOTEBOOK (widget), FALSE);
- gtk_box_pack_start (GTK_BOX (vbox), widget, TRUE, TRUE, 0);
- gtk_widget_show (widget);
- priv->notebook = GTK_NOTEBOOK (widget);
-
- g_signal_connect (editor, "delete_event", G_CALLBACK (delete_event_cb), editor);
- g_signal_connect (editor, "key_press_event", G_CALLBACK (editor_key_press_event), editor);
-
- /*Attachments */
- priv->attachment_scrolled_window = gtk_scrolled_window_new (NULL, NULL);
- gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (priv->attachment_scrolled_window),
- GTK_SHADOW_IN);
- gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (priv->attachment_scrolled_window),
- GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
-
- 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);
- gtk_widget_show (priv->attachment_bar);
- g_signal_connect (priv->attachment_bar, "changed",
- G_CALLBACK (attachment_bar_changed_cb), editor);
- g_signal_connect (GNOME_ICON_LIST (priv->attachment_bar), "event",
- G_CALLBACK (attachment_bar_icon_clicked_cb), editor);
- priv->attachment_expander_label =
- gtk_label_new_with_mnemonic (_("Show Attachment _Bar"));
- priv->attachment_expander_num = gtk_label_new ("");
- gtk_label_set_use_markup (GTK_LABEL (priv->attachment_expander_num), TRUE);
- gtk_misc_set_alignment (GTK_MISC (priv->attachment_expander_label), 0.0, 0.5);
- gtk_misc_set_alignment (GTK_MISC (priv->attachment_expander_num), 1.0, 0.5);
- expander_hbox = gtk_hbox_new (FALSE, 0);
-
- priv->attachment_expander_icon = gtk_image_new_from_icon_name ("mail-attachment", GTK_ICON_SIZE_MENU);
- gtk_misc_set_alignment (GTK_MISC (priv->attachment_expander_icon), 1, 0.5);
- gtk_widget_set_size_request (priv->attachment_expander_icon, 100, -1);
-
- gtk_box_pack_start (GTK_BOX (expander_hbox), priv->attachment_expander_label,
- TRUE, TRUE, 0);
- gtk_box_pack_start (GTK_BOX (expander_hbox), priv->attachment_expander_icon,
- TRUE, TRUE, 0);
- gtk_box_pack_start (GTK_BOX (expander_hbox), priv->attachment_expander_num,
- TRUE, TRUE, 0);
- gtk_widget_show_all (expander_hbox);
- gtk_widget_hide (priv->attachment_expander_icon);
-
- priv->attachment_expander = e_expander_new ("");
- e_expander_set_label_widget (E_EXPANDER (priv->attachment_expander), expander_hbox);
- atk_object_set_name (gtk_widget_get_accessible (priv->attachment_expander), _("Show Attachments"));
- atk_object_set_description (gtk_widget_get_accessible (priv->attachment_expander), _("Press space key to toggle attachment bar"));
- gtk_container_add (GTK_CONTAINER (priv->attachment_expander), priv->attachment_scrolled_window);
-
- gtk_box_pack_start (GTK_BOX (vbox), priv->attachment_expander, FALSE, FALSE, 4);
- gtk_widget_show (priv->attachment_expander);
- e_expander_set_expanded (E_EXPANDER (priv->attachment_expander), FALSE);
- g_signal_connect_after (priv->attachment_expander, "activate",
- G_CALLBACK (attachment_expander_activate_cb), editor);
-}
-
-
-static void
comp_editor_show_help (CompEditor *editor)
{
CompEditorClass *class;
@@ -2861,12 +2247,14 @@ comp_editor_get_client (CompEditor *editor)
static void
set_attachment_list (CompEditor *editor, GSList *attach_list)
{
- GSList *p = NULL;
- const char *comp_uid= NULL;
+ EAttachmentStore *store;
+ EAttachmentView *view;
+ GSList *iter = NULL;
- e_cal_component_get_uid (editor->priv->comp, &comp_uid);
+ view = E_ATTACHMENT_VIEW (editor->priv->attachment_view);
+ store = e_attachment_view_get_store (view);
- if (e_attachment_bar_get_num_attachments (E_ATTACHMENT_BAR (editor->priv->attachment_bar))) {
+ if (e_attachment_store_get_num_attachments (store) > 0) {
/* To prevent repopulating the
* bar due to redraw functions in fill_widget.
* Assumes it can be set only once.
@@ -2874,112 +2262,55 @@ set_attachment_list (CompEditor *editor, GSList *attach_list)
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;
- char *ptr;
-
- 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 = g_filename_from_uri (attach_filename, NULL, NULL);
- if (!file_name)
- continue;
-
- if (g_stat (file_name, &statbuf) < 0) {
- g_warning ("Cannot attach file %s: %s", file_name, g_strerror (errno));
- g_free (file_name);
- 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);
- g_free (file_name);
- return;
- }
-
- 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));
- g_free (file_name);
- return;
- }
-
- mime_type = e_util_guess_mime_type (file_name, TRUE);
- 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);
+ for (iter = attach_list; iter != NULL; iter = iter->next) {
+ EAttachment *attachment;
+ const gchar *uri = iter->data;
- camel_mime_part_set_disposition (part, "attachment");
-
- ptr = strstr (file_name, comp_uid);
- if (ptr) {
- ptr += strlen(comp_uid);
- if (*ptr++ == '-')
- camel_mime_part_set_filename (part, ptr);
- }
- g_free (file_name);
-
- e_attachment_bar_attach_mime_part ((EAttachmentBar *) editor->priv->attachment_bar, part);
- e_expander_set_expanded (E_EXPANDER (editor->priv->attachment_expander), TRUE);
-
- camel_object_unref (part);
+ attachment = e_attachment_new_for_uri (uri);
+ e_attachment_store_add_attachment (store, attachment);
+ e_attachment_load_async (
+ attachment, (GAsyncReadyCallback)
+ e_attachment_load_handle_error, editor);
+ g_object_unref (attachment);
}
}
static void
fill_widgets (CompEditor *editor)
{
+ EAttachmentStore *store;
+ EAttachmentView *view;
CompEditorPrivate *priv;
GList *l;
GtkAction *action;
+ view = E_ATTACHMENT_VIEW (editor->priv->attachment_view);
+ store = e_attachment_view_get_store (view);
+
priv = editor->priv;
/*Check if attachments are available here and set them*/
if (e_cal_component_has_attachments (priv->comp)) {
GSList *attachment_list = NULL;
e_cal_component_get_attachment_list (priv->comp, &attachment_list);
- g_signal_handlers_block_by_func(priv->attachment_bar, G_CALLBACK (attachment_bar_changed_cb), editor);
+ g_signal_handlers_block_by_func (
+ store, G_CALLBACK (attachment_store_changed_cb),
+ editor);
set_attachment_list (editor, attachment_list);
- g_signal_handlers_unblock_by_func(priv->attachment_bar, G_CALLBACK (attachment_bar_changed_cb), editor);
+ g_signal_handlers_unblock_by_func (
+ store, G_CALLBACK (attachment_store_changed_cb),
+ editor);
g_slist_foreach (attachment_list, (GFunc)g_free, NULL);
g_slist_free (attachment_list);
}
action = comp_editor_get_action (editor, "classify-public");
- g_signal_handlers_block_by_func (action, G_CALLBACK (classification_changed_cb), editor);
+ g_signal_handlers_block_by_func (action, G_CALLBACK (action_classification_cb), editor);
for (l = priv->pages; l != NULL; l = l->next)
comp_editor_page_fill_widgets (l->data, priv->comp);
- g_signal_handlers_unblock_by_func (action, G_CALLBACK (classification_changed_cb), editor);
+ g_signal_handlers_unblock_by_func (action, G_CALLBACK (action_classification_cb), editor);
}
static void
@@ -3303,20 +2634,41 @@ comp_editor_close (CompEditor *editor)
GSList *
comp_editor_get_mime_attach_list (CompEditor *editor)
{
+ EAttachmentStore *store;
+ EAttachmentView *view;
+ GtkTreeModel *model;
+ GtkTreeIter iter;
struct CalMimeAttach *cal_mime_attach;
- GSList *attach_list = NULL, *l, *parts;
+ GSList *attach_list = NULL;
+ gboolean valid;
+
+ view = E_ATTACHMENT_VIEW (editor->priv->attachment_view);
+ store = e_attachment_view_get_store (view);
- /* TODO assert sanity of bar */
- parts = e_attachment_bar_get_parts (E_ATTACHMENT_BAR (editor->priv->attachment_bar));
- for (l = parts; l ; l = l->next) {
+ model = GTK_TREE_MODEL (store);
+ valid = gtk_tree_model_get_iter_first (model, &iter);
+ while (valid) {
+ EAttachment *attachment;
CamelDataWrapper *wrapper;
+ CamelMimePart *mime_part;
CamelStreamMem *mstream;
unsigned char *buffer = NULL;
const char *desc, *disp;
+ gint column_id;
+
+ column_id = E_ATTACHMENT_STORE_COLUMN_ATTACHMENT;
+ gtk_tree_model_get (model, &iter, column_id, &attachment, -1);
+ mime_part = e_attachment_get_mime_part (attachment);
+ g_object_unref (attachment);
+
+ valid = gtk_tree_model_iter_next (model, &iter);
+
+ if (mime_part == NULL)
+ continue;
cal_mime_attach = g_malloc0 (sizeof (struct CalMimeAttach));
- wrapper = camel_medium_get_content_object (CAMEL_MEDIUM (l->data));
+ wrapper = camel_medium_get_content_object (CAMEL_MEDIUM (mime_part));
mstream = (CamelStreamMem *) camel_stream_mem_new ();
camel_data_wrapper_decode_to_stream (wrapper, (CamelStream *) mstream);
@@ -3324,15 +2676,14 @@ comp_editor_get_mime_attach_list (CompEditor *editor)
cal_mime_attach->encoded_data = (char *)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);
+ cal_mime_attach->filename = g_strdup (camel_mime_part_get_filename (mime_part));
+ desc = camel_mime_part_get_description (mime_part);
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));
- disp = camel_mime_part_get_disposition ((CamelMimePart *)l->data);
+ disp = camel_mime_part_get_disposition (mime_part);
if (disp && !g_ascii_strcasecmp(disp, "inline"))
cal_mime_attach->disposition = TRUE;
@@ -3342,8 +2693,6 @@ comp_editor_get_mime_attach_list (CompEditor *editor)
}
- g_slist_free (parts);
-
return attach_list;
}
diff --git a/calendar/gui/dialogs/event-editor.c b/calendar/gui/dialogs/event-editor.c
index a579d77..f32f245 100644
--- a/calendar/gui/dialogs/event-editor.c
+++ b/calendar/gui/dialogs/event-editor.c
@@ -512,8 +512,6 @@ event_editor_init (EventEditor *ee)
g_signal_connect_swapped (
ee->priv->model, "row_deleted",
G_CALLBACK (event_editor_model_changed_cb), ee);
-
- gtk_window_set_default_size (GTK_WINDOW (ee), 300, 225);
}
static void
diff --git a/calendar/gui/e-cal-popup.c b/calendar/gui/e-cal-popup.c
index b9f0d5f..0292f16 100644
--- a/calendar/gui/e-cal-popup.c
+++ b/calendar/gui/e-cal-popup.c
@@ -86,378 +86,11 @@ ecalp_target_free(EPopup *ep, EPopupTarget *t)
/* Standard menu code */
-static char *
-temp_save_part(CamelMimePart *part, char *path, gboolean file)
-{
- const char *filename;
- char *tmpdir, *utf8_mfilename = NULL, *mfilename = NULL, *usepath;
- CamelStream *stream;
- CamelDataWrapper *wrapper;
-
- if (!path) {
- tmpdir = e_mkdtemp("evolution-tmp-XXXXXX");
- if (tmpdir == NULL) {
- return NULL;
- }
-
- filename = camel_mime_part_get_filename (part);
- if (filename == NULL) {
- /* This is the default filename used for temporary file creation */
- filename = _("Unknown");
- } else {
- utf8_mfilename = g_strdup (filename);
- e_filename_make_safe (utf8_mfilename);
- mfilename = g_filename_from_utf8 ((const char *) utf8_mfilename, -1, NULL, NULL, NULL);
- g_free (utf8_mfilename);
- filename = (const char *) mfilename;
- }
-
- path = g_build_filename(tmpdir, filename, NULL);
- g_free(tmpdir);
- g_free(mfilename);
- } else if (!file) {
- tmpdir = path;
- filename = camel_mime_part_get_filename (part);
- if (filename == NULL) {
- /* This is the default filename used for temporary file creation */
- filename = _("Unknown");
- } else {
- utf8_mfilename = g_strdup (filename);
- e_filename_make_safe (utf8_mfilename);
- mfilename = g_filename_from_utf8 ((const char *)utf8_mfilename, -1, NULL, NULL, NULL);
- g_free (utf8_mfilename);
- filename = (const char *) mfilename;
- }
-
- path = g_build_filename(tmpdir, filename, NULL);
- g_free(mfilename);
- }
-
- if (strstr (path, "://"))
- usepath = path;
- else
- usepath = g_strjoin (NULL, "file://", path, NULL);
-
- wrapper = camel_medium_get_content_object (CAMEL_MEDIUM (part));
- stream = camel_stream_vfs_new_with_uri (usepath, CAMEL_STREAM_VFS_CREATE);
-
- if (usepath != path)
- g_free (usepath);
-
- if (!stream) {
- /* TODO handle error conditions */
- g_message ("DEBUG: could not open the file to write\n");
- return NULL;
- }
-
- if (camel_data_wrapper_decode_to_stream (wrapper, (CamelStream *) stream) == -1) {
- camel_stream_close (stream);
- camel_object_unref (stream);
- g_message ("DEBUG: could not write to file\n");
- return NULL;
- }
-
- camel_stream_close(stream);
- camel_object_unref(stream);
-
- return path;
-}
-
-static void
-ecalp_part_popup_saveas(EPopup *ep, EPopupItem *item, void *data)
-{
- EPopupTarget *t = ep->target;
- CamelMimePart *part = NULL;
- char *file, *mfilename = NULL;
- const char *filename;
-
- part = ((EAttachment *) ((ECalPopupTargetAttachments *) t)->attachments->data)->body;
- filename = camel_mime_part_get_filename (part);
- if (filename == NULL) {
- /* This is the default filename used for temporary file creation */
- filename = _("Unknown");
- } else {
- mfilename = g_strdup(filename);
- e_filename_make_safe(mfilename);
- filename = mfilename;
- }
- file = e_file_dialog_save (_("Save As..."), filename);
-
- if (file)
- temp_save_part (part, file, TRUE);
-
- g_free (file);
- g_free (mfilename);
-}
-
-static void
-ecalp_part_popup_save_selected(EPopup *ep, EPopupItem *item, void *data)
-{
- GSList *parts;
- EPopupTarget *t = ep->target;
- char *dir, *path;
-
- dir = e_file_dialog_save_folder (_("Select folder to save selected attachments..."));
- parts = ((ECalPopupTargetAttachments *) t)->attachments;
-
- for (;parts; parts=parts->next) {
- path = temp_save_part (((EAttachment *)parts->data)->body, dir, FALSE);
- /* Probably we 'll do some reporting in next release, like listing the saved files and locations */
- g_free (path);
- }
-}
-
-static void
-ecalp_part_popup_set_background(EPopup *ep, EPopupItem *item, void *data)
-{
- EPopupTarget *t = ep->target;
- GConfClient *gconf;
- char *str, *filename, *path, *extension;
- unsigned int i=1;
- CamelMimePart *part = NULL;
-
- part = ((EAttachment *) ((ECalPopupTargetAttachments *) t)->attachments->data)->body;
-
- if (!part)
- return;
-
- filename = g_strdup(camel_mime_part_get_filename(part));
-
- /* if filename is blank, create a default filename based on MIME type */
- if (!filename || !filename[0]) {
- CamelContentType *ct;
-
- ct = camel_mime_part_get_content_type(part);
- g_free (filename);
- filename = g_strdup_printf (_("untitled_image.%s"), ct->subtype);
- }
-
- e_filename_make_safe(filename);
-
- path = g_build_filename(g_get_home_dir(), ".gnome2", "wallpapers", filename, NULL);
-
- extension = strrchr(filename, '.');
- if (extension)
- *extension++ = 0;
-
- /* if file exists, stick a (number) on the end */
- while (g_file_test(path, G_FILE_TEST_EXISTS)) {
- char *name;
- name = g_strdup_printf(extension?"%s (%d).%s":"%s (%d)", filename, i++, extension);
- g_free(path);
- path = g_build_filename(g_get_home_dir(), ".gnome2", "wallpapers", name, NULL);
- g_free(name);
- }
-
- g_free(filename);
-
- if (temp_save_part(part, path, TRUE)) {
- gconf = gconf_client_get_default();
-
- /* if the filename hasn't changed, blank the filename before
- * setting it so that gconf detects a change and updates it */
- if ((str = gconf_client_get_string(gconf, "/desktop/gnome/background/picture_filename", NULL)) != NULL
- && strcmp (str, path) == 0) {
- gconf_client_set_string(gconf, "/desktop/gnome/background/picture_filename", "", NULL);
- }
-
- g_free (str);
- gconf_client_set_string(gconf, "/desktop/gnome/background/picture_filename", path, NULL);
-
- /* if GNOME currently doesn't display a picture, set to "wallpaper"
- * display mode, otherwise leave it alone */
- if ((str = gconf_client_get_string(gconf, "/desktop/gnome/background/picture_options", NULL)) == NULL
- || strcmp(str, "none") == 0) {
- gconf_client_set_string(gconf, "/desktop/gnome/background/picture_options", "wallpaper", NULL);
- }
-
- gconf_client_suggest_sync(gconf, NULL);
-
- g_free(str);
- g_object_unref(gconf);
- }
-
- g_free(path);
-}
-
-static const EPopupItem ecalp_standard_part_apps_bar = { E_POPUP_BAR, "99.object" };
-
-static ECalPopupItem ecalp_attachment_object_popups[] = {
- { E_POPUP_ITEM, "00.attach.00", N_("_Save As..."), ecalp_part_popup_saveas, NULL, "document-save-as", E_CAL_POPUP_ATTACHMENTS_ONE },
- { E_POPUP_ITEM, "00.attach.10", N_("Set as _Background"), ecalp_part_popup_set_background, NULL, NULL, E_CAL_POPUP_ATTACHMENTS_IMAGE },
- { E_POPUP_ITEM, "00.attach.20", N_("_Save Selected"), ecalp_part_popup_save_selected, NULL, "document-save-as", E_CAL_POPUP_ATTACHMENTS_MULTIPLE },
- { E_POPUP_BAR, "05.attach", },
-};
-
-static void
-ecalp_apps_open_in(EPopup *ep, EPopupItem *item, void *data)
-{
- char *path;
- EPopupTarget *target = ep->target;
- CamelMimePart *part;
-
- part = ((EAttachment *) ((ECalPopupTargetAttachments *) target)->attachments->data)->body;
-
- path = temp_save_part(part, NULL, FALSE);
- if (path) {
- GAppInfo *app = item->user_data;
- GList *uris = NULL;
- GError *error = NULL;
-
- if (g_app_info_supports_files (app)) {
- GFile *file = g_file_new_for_path (path);
-
- uris = g_list_append (uris, file);
- g_app_info_launch (app, uris, NULL, &error);
- g_object_unref (file);
- } else {
- char *uri;
-
- uri = e_util_filename_to_uri (path);
- uris = g_list_append (uris, uri);
-
- g_app_info_launch_uris (app, uris, NULL, &error);
- g_free (uri);
- }
-
- if (error) {
- g_warning ("%s", error->message);
- g_error_free (error);
- }
-
- g_list_free (uris);
- g_free (path);
- }
-}
-
-static void
-ecalp_apps_popup_free(EPopup *ep, GSList *free_list, void *data)
-{
- while (free_list) {
- GSList *n = free_list->next;
- EPopupItem *item = free_list->data;
-
- if (item->user_data && item->activate == ecalp_apps_open_in)
- g_object_unref (item->user_data);
-
- g_free(item->path);
- g_free(item->label);
- g_free(item);
- g_slist_free_1(free_list);
-
- free_list = n;
- }
-}
-
-static void
-ecalp_standard_items_free(EPopup *ep, GSList *items, void *data)
-{
- g_slist_free(items);
-}
-
-static void
-ecalp_standard_menu_factory (EPopup *ecalp, void *data)
-{
- int i, len;
- EPopupItem *items;
- GSList *menus = NULL;
- GList *apps = NULL;
- char *mime_type = NULL;
- const char *filename = NULL;
-
- switch (ecalp->target->type) {
- case E_CAL_POPUP_TARGET_ATTACHMENTS: {
- ECalPopupTargetAttachments *t = (ECalPopupTargetAttachments *)ecalp->target;
- GSList *list = t->attachments;
- EAttachment *attachment;
-
- items = ecalp_attachment_object_popups;
- len = G_N_ELEMENTS(ecalp_attachment_object_popups);
-
- if (g_slist_length(list) != 1 || !((EAttachment *)list->data)->is_available_local) {
- break;
- }
-
- /* Only one attachment selected */
- attachment = list->data;
- mime_type = camel_data_wrapper_get_mime_type((CamelDataWrapper *)attachment->body);
- filename = camel_mime_part_get_filename(attachment->body);
-
-
- break; }
- default:
- items = NULL;
- len = 0;
- }
-
- if (mime_type) {
- gchar *cp;
-
- /* does gvfs expect lowercase MIME types? */
- for (cp = mime_type; *cp != '\0'; cp++)
- *cp = g_ascii_tolower (*cp);
-
- cp = g_content_type_from_mime_type (mime_type);
- apps = g_app_info_get_all_for_type (cp ? cp : mime_type);
- g_free (cp);
-
- if (apps == NULL || strcmp(mime_type, "application/octet-stream") == 0) {
- if (filename) {
- gchar *name_type;
-
- name_type = e_util_guess_mime_type (filename, FALSE);
- cp = g_content_type_from_mime_type (name_type);
- /* show alternative apps first */
- apps = g_list_concat (g_app_info_get_all_for_type (cp ? cp : name_type), apps);
- g_free (cp);
- g_free (name_type);
- }
- }
- g_free (mime_type);
-
- if (apps) {
- GSList *open_menus = NULL;
- GList *l;
-
- menus = g_slist_prepend(menus, (void *)&ecalp_standard_part_apps_bar);
-
- for (l = apps, i = 0; l; l = l->next, i++) {
- GAppInfo *app = l->data;
- EPopupItem *item;
-
- item = g_malloc0(sizeof(*item));
- item->type = E_POPUP_ITEM;
- item->path = g_strdup_printf("99.object.%02d", i);
- item->label = g_strdup_printf(_("Open in %s..."), g_app_info_get_name (app));
- item->activate = ecalp_apps_open_in;
- item->user_data = app;
-
- open_menus = g_slist_prepend(open_menus, item);
- }
-
- if (open_menus)
- e_popup_add_items(ecalp, open_menus, NULL, ecalp_apps_popup_free, NULL);
-
- g_list_free (apps);
- }
- }
-
- for (i=0;i<len;i++) {
- if ((items[i].visible & ecalp->target->mask) == 0)
- menus = g_slist_prepend(menus, &items[i]);
- }
-
- if (menus)
- e_popup_add_items(ecalp, menus, NULL, ecalp_standard_items_free, NULL);
-}
-
static void
ecalp_class_init(GObjectClass *klass)
{
klass->finalize = ecalp_finalise;
((EPopupClass *)klass)->target_free = ecalp_target_free;
-
- e_popup_class_add_factory((EPopupClass *)klass, NULL, ecalp_standard_menu_factory, NULL);
}
GType
@@ -750,56 +383,6 @@ e_cal_popup_target_new_source(ECalPopup *eabp, ESourceSelector *selector)
return t;
}
-/**
- * e_cal_popup_target_new_attachments:
- * @ecp:
- * @attachments: A list of CalAttachment objects, reffed for
- * the list. Will be unreff'd once finished with.
- *
- * Owns the list @attachments and their items after they're passed in.
- *
- * Return value:
- **/
-ECalPopupTargetAttachments *
-e_cal_popup_target_new_attachments(ECalPopup *ecp, CompEditor *editor, GSList *attachments)
-{
- ECalPopupTargetAttachments *t = e_popup_target_new(&ecp->popup, E_CAL_POPUP_TARGET_ATTACHMENTS, sizeof(*t));
- guint32 mask = ~0;
- int len = g_slist_length(attachments);
- ECal *client = comp_editor_get_client (editor);
- CompEditorFlags flags = comp_editor_get_flags (editor);
- gboolean read_only = FALSE;
- GError *error = NULL;
-
- if (!e_cal_is_read_only (client, &read_only, &error)) {
- if (error->code != E_CALENDAR_STATUS_BUSY)
- read_only = TRUE;
- g_error_free (error);
- }
-
- if (!read_only && (!(flags & COMP_EDITOR_MEETING) ||
- (flags & COMP_EDITOR_NEW_ITEM) ||
- (flags & COMP_EDITOR_USER_ORG)))
- mask &= ~ E_CAL_POPUP_ATTACHMENTS_MODIFY;
-
- t->attachments = attachments;
- if (len > 0)
- mask &= ~ E_CAL_POPUP_ATTACHMENTS_MANY;
-
- if (len == 1 && ((EAttachment *)attachments->data)->is_available_local) {
- if (camel_content_type_is(((CamelDataWrapper *) ((EAttachment *) attachments->data)->body)->mime_type, "image", "*"))
- mask &= ~ E_CAL_POPUP_ATTACHMENTS_IMAGE;
- mask &= ~ E_CAL_POPUP_ATTACHMENTS_ONE;
- }
-
- if (len > 1)
- mask &= ~ E_CAL_POPUP_ATTACHMENTS_MULTIPLE;
-
- t->target.mask = mask;
-
- return t;
-}
-
/* ********************************************************************** */
/* Popup menu plugin handler */
diff --git a/calendar/gui/e-cal-popup.h b/calendar/gui/e-cal-popup.h
index fb899c3..34874ef 100644
--- a/calendar/gui/e-cal-popup.h
+++ b/calendar/gui/e-cal-popup.h
@@ -195,8 +195,6 @@ ECalPopup *e_cal_popup_new(const char *menuid);
ECalPopupTargetSelect *e_cal_popup_target_new_select(ECalPopup *eabp, struct _ECalModel *model, GPtrArray *events);
ECalPopupTargetSource *e_cal_popup_target_new_source(ECalPopup *eabp, struct _ESourceSelector *selector);
-ECalPopupTargetAttachments * e_cal_popup_target_new_attachments (ECalPopup *ecp,
- CompEditor *editor, GSList *attachments);
/* ********************************************************************** */
diff --git a/composer/e-composer-actions.c b/composer/e-composer-actions.c
index 61ad1e9..e46aba4 100644
--- a/composer/e-composer-actions.c
+++ b/composer/e-composer-actions.c
@@ -31,69 +31,13 @@ static void
action_attach_cb (GtkAction *action,
EMsgComposer *composer)
{
- EAttachmentBar *bar;
- GtkWidget *dialog;
- GtkWidget *option;
- GSList *uris, *iter;
- const gchar *disposition;
- gboolean active;
- gint response;
-
- bar = E_ATTACHMENT_BAR (composer->priv->attachment_bar);
-
- dialog = gtk_file_chooser_dialog_new (
- _("Insert Attachment"),
- GTK_WINDOW (composer),
- GTK_FILE_CHOOSER_ACTION_OPEN,
- GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
- _("A_ttach"), GTK_RESPONSE_OK,
- NULL);
-
- gtk_dialog_set_default_response (
- GTK_DIALOG (dialog), GTK_RESPONSE_OK);
- gtk_file_chooser_set_local_only (
- GTK_FILE_CHOOSER (dialog), FALSE);
- gtk_file_chooser_set_select_multiple (
- GTK_FILE_CHOOSER (dialog), TRUE);
- gtk_window_set_icon_name (
- GTK_WINDOW (dialog), "mail-message-new");
+ EAttachmentView *view;
+ EAttachmentStore *store;
- option = gtk_check_button_new_with_mnemonic (
- _("_Suggest automatic display of attachment"));
- gtk_widget_show (option);
- gtk_file_chooser_set_extra_widget (
- GTK_FILE_CHOOSER (dialog), option);
+ view = e_msg_composer_get_attachment_view (composer);
+ store = e_attachment_view_get_store (view);
- response = gtkhtml_editor_file_chooser_dialog_run (
- GTKHTML_EDITOR (composer), dialog);
-
- if (response != GTK_RESPONSE_OK)
- goto exit;
-
- uris = gtk_file_chooser_get_uris (GTK_FILE_CHOOSER (dialog));
- active = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (option));
- disposition = active ? "inline" : "attachment";
-
- for (iter = uris; iter != NULL; iter = iter->next) {
- CamelURL *url;
-
- url = camel_url_new (iter->data, NULL);
- if (url == NULL)
- continue;
-
- if (!g_ascii_strcasecmp (url->protocol, "file"))
- e_attachment_bar_attach (bar, url->path, disposition);
- else
- e_attachment_bar_attach_remote_file (bar, iter->data, disposition);
-
- camel_url_free (url);
- }
-
- g_slist_foreach (uris, (GFunc) g_free, NULL);
- g_slist_free (uris);
-
-exit:
- gtk_widget_destroy (dialog);
+ e_attachment_store_run_load_dialog (store, GTK_WINDOW (composer));
}
static void
diff --git a/composer/e-composer-private.c b/composer/e-composer-private.c
index d47a372..ab1e092 100644
--- a/composer/e-composer-private.c
+++ b/composer/e-composer-private.c
@@ -49,27 +49,29 @@ composer_setup_charset_menu (EMsgComposer *composer)
static void
composer_setup_recent_menu (EMsgComposer *composer)
{
+ EAttachmentView *view;
GtkUIManager *manager;
- GtkAction *action = NULL;
- const gchar *path, *action_name;
+ GtkAction *action;
+ const gchar *action_name;
+ const gchar *path;
guint merge_id;
+ view = e_msg_composer_get_attachment_view (composer);
manager = gtkhtml_editor_get_ui_manager (GTKHTML_EDITOR (composer));
- action_name = "recent-menu";
path = "/main-menu/insert-menu/insert-menu-top/recent-placeholder";
merge_id = gtk_ui_manager_new_merge_id (manager);
+ action_name = "recent-menu";
- action = e_attachment_bar_recent_action_new (
- e_msg_composer_get_attachment_bar (composer),
- action_name, _("Recent _Documents"));
+ action = e_attachment_view_recent_action_new (
+ view, action_name, _("Recent _Documents"));
if (action != NULL) {
- gtk_action_group_add_action (composer->priv->composer_actions, action);
+ gtk_action_group_add_action (
+ composer->priv->composer_actions, action);
- gtk_ui_manager_add_ui (
+ gtk_ui_manager_add_ui (
manager, merge_id, path,
- action_name,
- action_name,
+ action_name, action_name,
GTK_UI_MANAGER_AUTO, FALSE);
}
@@ -84,7 +86,6 @@ e_composer_private_init (EMsgComposer *composer)
GtkhtmlEditor *editor;
GtkUIManager *manager;
GtkWidget *widget;
- GtkWidget *expander;
GtkWidget *container;
GtkWidget *send_widget;
const gchar *path;
@@ -136,6 +137,8 @@ e_composer_private_init (EMsgComposer *composer)
/* Construct the header table. */
+ container = editor->vbox;
+
widget = e_composer_header_table_new ();
gtk_container_set_border_width (GTK_CONTAINER (widget), 6);
gtk_box_pack_start (GTK_BOX (editor->vbox), widget, FALSE, FALSE, 0);
@@ -143,59 +146,23 @@ e_composer_private_init (EMsgComposer *composer)
priv->header_table = g_object_ref (widget);
gtk_widget_show (widget);
- /* Construct attachment widgets.
- * XXX Move this stuff into a new custom widget. */
-
- widget = gtk_expander_new (NULL);
- gtk_expander_set_expanded (GTK_EXPANDER (widget), FALSE);
- gtk_container_set_border_width (GTK_CONTAINER (widget), 6);
- gtk_box_pack_start (GTK_BOX (editor->vbox), widget, FALSE, FALSE, 0);
- priv->attachment_expander = g_object_ref (widget);
- gtk_widget_show (widget);
- expander = widget;
-
- widget = gtk_scrolled_window_new (NULL, NULL);
- gtk_scrolled_window_set_policy (
- GTK_SCROLLED_WINDOW (widget),
- GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
- gtk_scrolled_window_set_shadow_type (
- GTK_SCROLLED_WINDOW (widget), GTK_SHADOW_IN);
- gtk_container_add (GTK_CONTAINER (expander), widget);
- priv->attachment_scrolled_window = g_object_ref (widget);
- gtk_widget_show (widget);
- container = widget;
-
- widget = e_attachment_bar_new (NULL);
- GTK_WIDGET_SET_FLAGS (widget, GTK_CAN_FOCUS);
- gtk_container_add (GTK_CONTAINER (container), widget);
- priv->attachment_bar = g_object_ref (widget);
- gtk_widget_show (widget);
+ /* Construct the attachment paned. */
- widget = gtk_hbox_new (FALSE, 0);
- gtk_expander_set_label_widget (GTK_EXPANDER (expander), widget);
+ widget = e_attachment_paned_new ();
+ gtk_box_pack_start (GTK_BOX (container), widget, TRUE, TRUE, 0);
+ priv->attachment_paned = g_object_ref (widget);
gtk_widget_show (widget);
- container = widget;
- widget = gtk_label_new_with_mnemonic (_("Show _Attachment Bar"));
- gtk_misc_set_alignment (GTK_MISC (widget), 0.0, 0.5);
- gtk_box_pack_start (GTK_BOX (container), widget, TRUE, TRUE, 6);
- priv->attachment_expander_label = g_object_ref (widget);
- gtk_widget_show (widget);
+ /* Reparent the scrolled window containing the GtkHTML widget
+ * into the content area of the top attachment pane. */
- widget = gtk_image_new_from_icon_name (
- "mail-attachment", GTK_ICON_SIZE_MENU);
- gtk_misc_set_alignment (GTK_MISC (widget), 1.0, 0.5);
- gtk_widget_set_size_request (widget, 100, -1);
- gtk_box_pack_start (GTK_BOX (container), widget, TRUE, TRUE, 0);
- priv->attachment_expander_icon = g_object_ref (widget);
- gtk_widget_hide (widget);
-
- widget = gtk_label_new (NULL);
- gtk_label_set_use_markup (GTK_LABEL (widget), TRUE);
- gtk_misc_set_alignment (GTK_MISC (widget), 1.0, 0.5);
- gtk_box_pack_start (GTK_BOX (container), widget, FALSE, FALSE, 6);
- priv->attachment_expander_num = g_object_ref (widget);
- gtk_widget_show (widget);
+ widget = GTK_WIDGET (gtkhtml_editor_get_html (editor));
+ widget = gtk_widget_get_parent (widget);
+ container = e_attachment_paned_get_content_area (
+ E_ATTACHMENT_PANED (priv->attachment_paned));
+ gtk_widget_reparent (widget, container);
+ gtk_box_set_child_packing (
+ GTK_BOX (container), widget, TRUE, TRUE, 0, GTK_PACK_START);
composer_setup_recent_menu (composer);
}
diff --git a/composer/e-composer-private.h b/composer/e-composer-private.h
index ec6626e..669af31 100644
--- a/composer/e-composer-private.h
+++ b/composer/e-composer-private.h
@@ -25,11 +25,12 @@
#include <camel/camel-iconv.h>
-#include "e-attachment-bar.h"
#include "e-composer-actions.h"
#include "e-composer-autosave.h"
#include "e-composer-header-table.h"
#include "e-util/gconf-bridge.h"
+#include "widgets/misc/e-attachment-paned.h"
+#include "widgets/misc/e-attachment-store.h"
#define E_MSG_COMPOSER_GET_PRIVATE(obj) \
(G_TYPE_INSTANCE_GET_PRIVATE \
@@ -94,6 +95,8 @@ struct _EMsgComposerPrivate {
GtkWidget *html_editor;
GtkWidget *header_table;
+ GtkWidget *attachment_paned;
+
GtkActionGroup *charset_actions;
GtkActionGroup *composer_actions;
@@ -102,13 +105,6 @@ struct _EMsgComposerPrivate {
GtkWidget *focused_entry;
- GtkWidget *attachment_bar;
- GtkWidget *attachment_scrolled_window;
- GtkWidget *attachment_expander;
- GtkWidget *attachment_expander_label;
- GtkWidget *attachment_expander_icon;
- GtkWidget *attachment_expander_num;
-
GtkWidget *address_dialog;
GHashTable *inline_images;
diff --git a/composer/e-msg-composer.c b/composer/e-msg-composer.c
index d39a212..a277729 100644
--- a/composer/e-msg-composer.c
+++ b/composer/e-msg-composer.c
@@ -60,7 +60,6 @@
#include "e-util/e-dialog-utils.h"
#include "misc/e-charset-picker.h"
-#include "misc/e-expander.h"
#include "e-util/e-error.h"
#include "e-util/e-plugin-ui.h"
#include "e-util/e-util-private.h"
@@ -98,7 +97,6 @@
#include "e-msg-composer.h"
#include "e-attachment.h"
-#include "e-attachment-bar.h"
#include "e-composer-autosave.h"
#include "e-composer-private.h"
#include "e-composer-header-table.h"
@@ -152,39 +150,6 @@ enum {
LAST_SIGNAL
};
-enum {
- DND_TYPE_MESSAGE_RFC822,
- DND_TYPE_X_UID_LIST,
- DND_TYPE_TEXT_URI_LIST,
- DND_TYPE_NETSCAPE_URL,
- DND_TYPE_TEXT_VCARD,
- DND_TYPE_TEXT_CALENDAR
-};
-
-static GtkTargetEntry drop_types[] = {
- { "message/rfc822", 0, DND_TYPE_MESSAGE_RFC822 },
- { "x-uid-list", 0, DND_TYPE_X_UID_LIST },
- { "text/uri-list", 0, DND_TYPE_TEXT_URI_LIST },
- { "_NETSCAPE_URL", 0, DND_TYPE_NETSCAPE_URL },
- { "text/x-vcard", 0, DND_TYPE_TEXT_VCARD },
- { "text/calendar", 0, DND_TYPE_TEXT_CALENDAR }
-};
-
-static struct {
- gchar *target;
- GdkAtom atom;
- guint32 actions;
-} drag_info[] = {
- { "message/rfc822", NULL, GDK_ACTION_COPY },
- { "x-uid-list", NULL, GDK_ACTION_ASK |
- GDK_ACTION_MOVE |
- GDK_ACTION_COPY },
- { "text/uri-list", NULL, GDK_ACTION_COPY },
- { "_NETSCAPE_URL", NULL, GDK_ACTION_COPY },
- { "text/x-vcard", NULL, GDK_ACTION_COPY },
- { "text/calendar", NULL, GDK_ACTION_COPY }
-};
-
static gpointer parent_class;
static guint signals[LAST_SIGNAL];
@@ -195,7 +160,6 @@ static GSList *all_composers = NULL;
static GList *add_recipients (GList *list, const gchar *recips);
static void handle_mailto (EMsgComposer *composer, const gchar *mailto);
-static void handle_uri (EMsgComposer *composer, const gchar *uri, gboolean html_dnd);
/* used by e_msg_composer_add_message_attachments () */
static void add_attachments_from_multipart (EMsgComposer *composer, CamelMultipart *multipart,
@@ -527,7 +491,8 @@ build_message (EMsgComposer *composer,
GtkhtmlEditor *editor;
EMsgComposerPrivate *p = composer->priv;
- EAttachmentBar *attachment_bar;
+ EAttachmentView *view;
+ EAttachmentStore *store;
EComposerHeaderTable *table;
GtkToggleAction *action;
CamelDataWrapper *plain, *html, *current;
@@ -554,7 +519,8 @@ build_message (EMsgComposer *composer,
editor = GTKHTML_EDITOR (composer);
table = e_msg_composer_get_header_table (composer);
account = e_composer_header_table_get_account (table);
- attachment_bar = E_ATTACHMENT_BAR (p->attachment_bar);
+ view = e_msg_composer_get_attachment_view (composer);
+ store = e_attachment_view_get_store (view);
/* evil kludgy hack for Redirect */
if (p->redirect) {
@@ -714,7 +680,7 @@ build_message (EMsgComposer *composer,
} else
current = plain;
- if (e_attachment_bar_get_num_attachments (attachment_bar)) {
+ if (e_attachment_store_get_num_attachments (store) > 0) {
CamelMultipart *multipart = camel_multipart_new ();
if (p->is_alternative) {
@@ -733,7 +699,8 @@ build_message (EMsgComposer *composer,
camel_multipart_add_part (multipart, part);
camel_object_unref (part);
- e_attachment_bar_to_multipart (attachment_bar, multipart, p->charset);
+ e_attachment_store_add_to_multipart (
+ store, multipart, p->charset);
if (p->is_alternative) {
for (i = camel_multipart_get_number (multipart); i > 1; i--) {
@@ -976,107 +943,6 @@ skip_content:
return NULL;
}
-/* Attachment Bar */
-
-static void
-emcab_add (EPopup *ep, EPopupItem *item, gpointer data)
-{
- GtkWidget *widget = data;
- GtkWidget *composer;
-
- composer = gtk_widget_get_toplevel (widget);
- gtk_action_activate (ACTION (ATTACH));
-}
-
-static void
-emcab_properties (EPopup *ep, EPopupItem *item, gpointer data)
-{
- EAttachmentBar *attachment_bar = data;
-
- e_attachment_bar_edit_selected (attachment_bar);
-}
-
-static void
-emcab_remove (EPopup *ep, EPopupItem *item, gpointer data)
-{
- EAttachmentBar *attachment_bar = data;
-
- e_attachment_bar_remove_selected (attachment_bar);
-}
-
-static void
-emcab_popup_position (GtkMenu *menu, int *x, int *y, gboolean *push_in, gpointer user_data)
-{
- GtkWidget *widget = user_data;
- GnomeIconList *icon_list = user_data;
- GList *selection;
- GnomeCanvasPixbuf *image;
-
- gdk_window_get_origin (widget->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, GPOINTER_TO_INT(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 *list, gpointer data)
-{
- g_slist_free (list);
-}
-
-/* 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 },
-};
-
-/* if id != -1, then use it as an index for target of the popup */
-
-static void
-emcab_popup (EAttachmentBar *bar, GdkEventButton *event, int id)
-{
- GSList *attachments = NULL, *menus = NULL;
- int i;
- EMPopup *emp;
- EMPopupTargetAttachments *t;
- GtkMenu *menu;
-
- 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);
-}
-
/* Signatures */
static gchar *
@@ -1467,108 +1333,17 @@ autosave_load_draft (const gchar *filename)
/* Miscellaneous callbacks. */
-static gint
-attachment_bar_button_press_event_cb (EAttachmentBar *attachment_bar,
- GdkEventButton *event)
-{
- GnomeIconList *icon_list;
- gint icon_number;
-
- if (event->button != 3)
- return FALSE;
-
- icon_list = GNOME_ICON_LIST (attachment_bar);
- 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 (attachment_bar, event, icon_number);
-
- return TRUE;
-}
-
static void
-attachment_bar_changed_cb (EAttachmentBar *attachment_bar,
- EMsgComposer *composer)
+attachment_store_changed_cb (EMsgComposer *composer)
{
GtkhtmlEditor *editor;
- GtkWidget *widget;
- guint attachment_num;
-
- editor = GTKHTML_EDITOR (composer);
- attachment_num = e_attachment_bar_get_num_attachments (attachment_bar);
-
- if (attachment_num > 0) {
- gchar *markup;
-
- markup = g_strdup_printf (
- "<b>%d</b> %s", attachment_num, ngettext (
- "Attachment", "Attachments", attachment_num));
- widget = composer->priv->attachment_expander_num;
- gtk_label_set_markup (GTK_LABEL (widget), markup);
- g_free (markup);
-
- gtk_widget_show (composer->priv->attachment_expander_icon);
-
- widget = composer->priv->attachment_expander;
- gtk_expander_set_expanded (GTK_EXPANDER (widget), TRUE);
- } else {
- widget = composer->priv->attachment_expander_num;
- gtk_label_set_text (GTK_LABEL (widget), "");
-
- gtk_widget_hide (composer->priv->attachment_expander_icon);
-
- widget = composer->priv->attachment_expander;
- gtk_expander_set_expanded (GTK_EXPANDER (widget), FALSE);
- }
/* Mark the editor as changed so it prompts about unsaved
- changes on close. */
+ * changes on close. */
+ editor = GTKHTML_EDITOR (composer);
gtkhtml_editor_set_changed (editor, TRUE);
}
-static gint
-attachment_bar_key_press_event_cb (EAttachmentBar *attachment_bar,
- GdkEventKey *event)
-{
- if (event->keyval == GDK_Delete) {
- e_attachment_bar_remove_selected (attachment_bar);
- return TRUE;
- }
-
- return FALSE;
-}
-
-static gboolean
-attachment_bar_popup_menu_cb (EAttachmentBar *attachment_bar)
-{
- emcab_popup (attachment_bar, NULL, -1);
-
- return TRUE;
-}
-
-static void
-attachment_expander_notify_cb (GtkExpander *expander,
- GParamSpec *pspec,
- EMsgComposer *composer)
-{
- GtkLabel *label;
- const gchar *text;
-
- label = GTK_LABEL (composer->priv->attachment_expander_label);
-
- /* Update the expander label */
- if (gtk_expander_get_expanded (expander))
- text = _("Hide _Attachment Bar");
- else
- text = _("Show _Attachment Bar");
-
- gtk_label_set_text_with_mnemonic (label, text);
-}
-
static void
msg_composer_subject_changed_cb (EMsgComposer *composer)
{
@@ -1765,35 +1540,6 @@ msg_composer_account_list_changed_cb (EMsgComposer *composer)
}
static void
-msg_composer_attach_message (EMsgComposer *composer,
- CamelMimeMessage *msg)
-{
- CamelMimePart *mime_part;
- GString *description;
- const gchar *subject;
- EMsgComposerPrivate *p = composer->priv;
-
- mime_part = camel_mime_part_new ();
- camel_mime_part_set_disposition (mime_part, "inline");
- subject = camel_mime_message_get_subject (msg);
-
- description = g_string_new (_("Attached message"));
- if (subject != NULL)
- g_string_append_printf (description, " - %s", subject);
- camel_mime_part_set_description (mime_part, description->str);
- g_string_free (description, TRUE);
-
- camel_medium_set_content_object (
- (CamelMedium *) mime_part, (CamelDataWrapper *) msg);
- camel_mime_part_set_content_type (mime_part, "message/rfc822");
-
- e_attachment_bar_attach_mime_part (
- E_ATTACHMENT_BAR (p->attachment_bar), mime_part);
-
- camel_object_unref (mime_part);
-}
-
-static void
msg_composer_update_preferences (GConfClient *client,
guint cnxn_id,
GConfEntry *entry,
@@ -1849,17 +1595,7 @@ struct _drop_data {
unsigned int aborted:1;
};
-int
-e_msg_composer_get_remote_download_count (EMsgComposer *composer)
-{
- EAttachmentBar *attachment_bar;
-
- g_return_val_if_fail (E_IS_MSG_COMPOSER (composer), 0);
-
- attachment_bar = E_ATTACHMENT_BAR (composer->priv->attachment_bar);
- return e_attachment_bar_get_download_count (attachment_bar);
-}
-
+#if 0 /* FIXME */
static void
drop_action (EMsgComposer *composer,
GdkDragContext *context,
@@ -2033,55 +1769,7 @@ drop_action (EMsgComposer *composer,
gtk_drag_finish (context, success, delete, time);
}
-
-static void
-drop_popup_copy (EPopup *ep, EPopupItem *item, gpointer data)
-{
- struct _drop_data *m = data;
-
- drop_action (
- m->composer, m->context, GDK_ACTION_COPY,
- m->selection, m->info, m->time, FALSE);
-}
-
-static void
-drop_popup_move (EPopup *ep, EPopupItem *item, gpointer data)
-{
- struct _drop_data *m = data;
-
- drop_action (
- m->composer, m->context, GDK_ACTION_MOVE,
- m->selection, m->info, m->time, FALSE);
-}
-
-static void
-drop_popup_cancel (EPopup *ep, EPopupItem *item, gpointer data)
-{
- struct _drop_data *m = data;
-
- gtk_drag_finish (m->context, FALSE, FALSE, m->time);
-}
-
-static EPopupItem drop_popup_menu[] = {
- { E_POPUP_ITEM, "00.emc.02", N_("_Copy"), drop_popup_copy, NULL, "mail-copy", 0 },
- { E_POPUP_ITEM, "00.emc.03", N_("_Move"), drop_popup_move, NULL, "mail-move", 0 },
- { E_POPUP_BAR, "10.emc" },
- { E_POPUP_ITEM, "99.emc.00", N_("Cancel _Drag"), drop_popup_cancel, NULL, NULL, 0 },
-};
-
-static void
-drop_popup_free (EPopup *ep, GSList *items, gpointer data)
-{
- struct _drop_data *m = data;
-
- g_slist_free (items);
-
- g_object_unref (m->context);
- g_object_unref (m->composer);
- g_free (m->selection->data);
- g_free (m->selection);
- g_free (m);
-}
+#endif
static void
msg_composer_notify_header_cb (EMsgComposer *composer)
@@ -2341,33 +2029,14 @@ msg_composer_drag_motion (GtkWidget *widget,
gint y,
guint time)
{
- GList *targets;
- GdkDragAction actions = 0;
- GdkDragAction chosen_action;
-
- targets = context->targets;
- while (targets != NULL) {
- gint ii;
-
- for (ii = 0; ii < G_N_ELEMENTS (drag_info); ii++)
- if (targets->data == (gpointer) drag_info[ii].atom)
- actions |= drag_info[ii].actions;
-
- targets = g_list_next (targets);
- }
-
- actions &= context->actions;
- chosen_action = context->suggested_action;
-
- /* we default to copy */
- if (chosen_action == GDK_ACTION_ASK &&
- (actions & (GDK_ACTION_MOVE|GDK_ACTION_COPY)) !=
- (GDK_ACTION_MOVE|GDK_ACTION_COPY))
- chosen_action = GDK_ACTION_COPY;
+ EMsgComposer *composer;
+ EAttachmentView *view;
- gdk_drag_status (context, chosen_action, time);
+ /* Widget may be EMsgComposer or GtkHTML. */
+ composer = E_MSG_COMPOSER (gtk_widget_get_toplevel (widget));
+ view = e_msg_composer_get_attachment_view (composer);
- return (chosen_action != 0);
+ return e_attachment_view_drag_motion (view, context, x, y, time);
}
static void
@@ -2380,46 +2049,19 @@ msg_composer_drag_data_received (GtkWidget *widget,
guint time)
{
EMsgComposer *composer;
+ EAttachmentView *view;
/* Widget may be EMsgComposer or GtkHTML. */
composer = E_MSG_COMPOSER (gtk_widget_get_toplevel (widget));
-
- if (selection->data == NULL)
- return;
-
- if (selection->length == -1)
- return;
-
- if (context->action == GDK_ACTION_ASK) {
- EMPopup *emp;
- GSList *menus = NULL;
- GtkMenu *menu;
- gint ii;
- struct _drop_data *m;
-
- m = g_malloc0(sizeof (*m));
- m->context = g_object_ref (context);
- m->composer = g_object_ref (composer);
- m->action = context->action;
- m->info = info;
- m->time = time;
- m->selection = g_malloc0(sizeof (*m->selection));
- m->selection->data = g_malloc (selection->length);
- memcpy (m->selection->data, selection->data, selection->length);
- m->selection->length = selection->length;
-
- emp = em_popup_new ("org.gnome.evolution.mail.composer.popup.drop");
- for (ii = 0; ii < G_N_ELEMENTS (drop_popup_menu); ii++)
- menus = g_slist_append (menus, &drop_popup_menu[ii]);
-
- e_popup_add_items ((EPopup *)emp, menus, NULL, drop_popup_free, m);
- menu = e_popup_create_menu_once ((EPopup *)emp, NULL, 0);
- gtk_menu_popup (menu, NULL, NULL, NULL, NULL, 0, time);
- } else {
- drop_action (
- composer, context, context->action, selection,
- info, time, !GTK_WIDGET_TOPLEVEL (widget));
- }
+ view = e_msg_composer_get_attachment_view (composer);
+
+ /* Forward the data to the attachment view. Note that calling
+ * e_attachment_view_drag_data_received() will not work because
+ * that function only handles the case where all the other drag
+ * handlers have failed. */
+ e_attachment_paned_drag_data_received (
+ E_ATTACHMENT_PANED (view),
+ context, x, y, selection, info, time);
}
static void
@@ -2466,11 +2108,20 @@ static void
msg_composer_paste_clipboard (GtkhtmlEditor *editor)
{
EMsgComposer *composer;
+ EAttachmentView *view;
+ EAttachmentStore *store;
+ GtkClipboard *clipboard;
+ GdkPixbuf *pixbuf;
GtkWidget *parent;
GtkWidget *widget;
- GtkClipboard *clipboard;
+ gchar *filename;
+ gchar *uri;
+ GError *error = NULL;
composer = E_MSG_COMPOSER (editor);
+ view = e_msg_composer_get_attachment_view (composer);
+ store = e_attachment_view_get_store (view);
+
widget = gtk_window_get_focus (GTK_WINDOW (editor));
parent = gtk_widget_get_parent (widget);
@@ -2480,36 +2131,63 @@ msg_composer_paste_clipboard (GtkhtmlEditor *editor)
}
clipboard = gtk_widget_get_clipboard (widget, GDK_SELECTION_CLIPBOARD);
- if (clipboard && gtk_clipboard_wait_is_image_available (clipboard)) {
- GdkPixbuf *pixbuf;
-
- pixbuf = gtk_clipboard_wait_for_image (clipboard);
- if (pixbuf) {
- char *tmpl = g_strconcat (_("Image"), "-XXXXXX", NULL);
- char *filename = e_mktemp (tmpl);
-
- g_free (tmpl);
-
- if (filename && gdk_pixbuf_save (pixbuf, filename, "png", NULL, NULL)) {
- if (gtkhtml_editor_get_html_mode (editor)) {
- char *uri = g_strconcat ("file://", filename, NULL);
- /* this loads image async, thus cannot remove file from this */
- gtkhtml_editor_insert_image (editor, uri);
- g_free (uri);
- } else {
- /* this loads image immediately, remove file from cache to free up disk space */
- e_attachment_bar_attach (E_ATTACHMENT_BAR (composer->priv->attachment_bar), filename, "image/png");
- g_remove (filename);
- }
- }
- g_free (filename);
- g_object_unref (pixbuf);
- }
- } else {
- /* Chain up to parent's paste_clipboard() method. */
- GTKHTML_EDITOR_CLASS (parent_class)->paste_clipboard (editor);
+ /* Assume the clipboard has an image. The return
+ * value will be NULL we we assumed wrong. */
+ pixbuf = gtk_clipboard_wait_for_image (clipboard);
+ if (!GDK_IS_PIXBUF (pixbuf))
+ goto chainup;
+
+ /* Reserve a temporary file. */
+ filename = e_mktemp (NULL);
+ if (filename == NULL) {
+ g_warning ("%s", g_strerror (errno));
+ g_object_unref (pixbuf);
+ g_error_free (error);
+ return;
+ }
+
+ /* Save the pixbuf as a temporary file in image/png format. */
+ if (!gdk_pixbuf_save (pixbuf, filename, "png", &error, NULL)) {
+ g_warning ("%s", error->message);
+ g_object_unref (pixbuf);
+ g_error_free (error);
+ g_free (filename);
+ return;
+ }
+
+ /* Convert the filename to a URI. */
+ uri = g_filename_to_uri (filename, NULL, &error);
+ if (error != NULL) {
+ g_warning ("%s", error->message);
+ g_object_unref (pixbuf);
+ g_error_free (error);
+ g_free (filename);
+ return;
}
+
+ if (gtkhtml_editor_get_html_mode (editor))
+ gtkhtml_editor_insert_image (editor, uri);
+ else {
+ EAttachment *attachment;
+
+ attachment = e_attachment_new_for_uri (uri);
+ e_attachment_store_add_attachment (store, attachment);
+ e_attachment_load_async (
+ attachment, (GAsyncReadyCallback)
+ e_attachment_load_handle_error, composer);
+ g_object_unref (attachment);
+ }
+
+ g_object_unref (pixbuf);
+ g_free (filename);
+ g_free (uri);
+
+ return;
+
+chainup:
+ /* Chain up to parent's paste_clipboard() method. */
+ GTKHTML_EDITOR_CLASS (parent_class)->paste_clipboard (editor);
}
static void
@@ -2733,11 +2411,6 @@ msg_composer_class_init (EMsgComposerClass *class)
GtkObjectClass *gtk_object_class;
GtkWidgetClass *widget_class;
GtkhtmlEditorClass *editor_class;
- gint ii;
-
- for (ii = 0; ii < G_N_ELEMENTS (drag_info); ii++)
- drag_info[ii].atom =
- gdk_atom_intern (drag_info[ii].target, FALSE);
parent_class = g_type_class_peek_parent (class);
g_type_class_add_private (class, sizeof (EMsgComposerPrivate));
@@ -2789,10 +2462,16 @@ msg_composer_class_init (EMsgComposerClass *class)
static void
msg_composer_init (EMsgComposer *composer)
{
+ EAttachmentView *view;
+ EAttachmentStore *store;
EComposerHeaderTable *table;
+ GdkDragAction drag_actions;
+ GtkTargetList *target_list;
+ GtkTargetEntry *targets;
GtkUIManager *manager;
GtkhtmlEditor *editor;
GtkHTML *html;
+ gint n_targets;
composer->priv = E_MSG_COMPOSER_GET_PRIVATE (composer);
@@ -2801,6 +2480,7 @@ msg_composer_init (EMsgComposer *composer)
editor = GTKHTML_EDITOR (composer);
html = gtkhtml_editor_get_html (editor);
manager = gtkhtml_editor_get_ui_manager (editor);
+ view = e_msg_composer_get_attachment_view (composer);
all_composers = g_slist_prepend (all_composers, composer);
table = E_COMPOSER_HEADER_TABLE (composer->priv->header_table);
@@ -2809,36 +2489,21 @@ msg_composer_init (EMsgComposer *composer)
/* Drag-and-Drop Support */
- gtk_drag_dest_set (
- GTK_WIDGET (composer), GTK_DEST_DEFAULT_ALL,
- drop_types, G_N_ELEMENTS (drop_types),
- GDK_ACTION_COPY | GDK_ACTION_ASK | GDK_ACTION_MOVE);
+ target_list = e_attachment_view_get_target_list (view);
+ drag_actions = e_attachment_view_get_drag_actions (view);
- /* XXX I'm not sure why we have to explicitly configure the
- * attachment bar as a drag destination when CompEditor
- * doesn't and previous Evolution releases (2.22 and
- * prior) don't, but this is the only way I could figure
- * out how to get drag-and-drop to the attachment bar
- * working again. I'm probably overlooking something
- * simple... */
+ targets = gtk_target_table_new_from_list (target_list, &n_targets);
gtk_drag_dest_set (
- composer->priv->attachment_bar, GTK_DEST_DEFAULT_ALL,
- drop_types, G_N_ELEMENTS (drop_types),
- GDK_ACTION_COPY | GDK_ACTION_ASK | GDK_ACTION_MOVE);
-
- g_signal_connect (
- composer->priv->attachment_bar, "drag-motion",
- G_CALLBACK (msg_composer_drag_motion), NULL);
-
- g_signal_connect (
- composer->priv->attachment_bar, "drag-data-received",
- G_CALLBACK (msg_composer_drag_data_received), NULL);
+ GTK_WIDGET (composer), GTK_DEST_DEFAULT_ALL,
+ targets, n_targets, drag_actions);
g_signal_connect (
html, "drag-data-received",
G_CALLBACK (msg_composer_drag_data_received), NULL);
+ gtk_target_table_free (targets, n_targets);
+
/* Configure Headers */
e_composer_header_table_set_account_list (
@@ -2877,23 +2542,17 @@ msg_composer_init (EMsgComposer *composer)
msg_composer_account_changed_cb (composer);
msg_composer_account_list_changed_cb (composer);
- /* Attachment Bar */
+ /* Attachments */
- g_signal_connect (
- composer->priv->attachment_bar, "button_press_event",
- G_CALLBACK (attachment_bar_button_press_event_cb), NULL);
- g_signal_connect (
- composer->priv->attachment_bar, "key_press_event",
- G_CALLBACK (attachment_bar_key_press_event_cb), NULL);
- g_signal_connect (
- composer->priv->attachment_bar, "popup-menu",
- G_CALLBACK (attachment_bar_popup_menu_cb), NULL);
- g_signal_connect (
- composer->priv->attachment_bar, "changed",
- G_CALLBACK (attachment_bar_changed_cb), composer);
- g_signal_connect_after (
- composer->priv->attachment_expander, "notify::expanded",
- G_CALLBACK (attachment_expander_notify_cb), composer);
+ store = e_attachment_view_get_store (view);
+
+ g_signal_connect_swapped (
+ store, "row-deleted",
+ G_CALLBACK (attachment_store_changed_cb), composer);
+
+ g_signal_connect_swapped (
+ store, "row-inserted",
+ G_CALLBACK (attachment_store_changed_cb), composer);
e_composer_autosave_register (composer);
@@ -3738,7 +3397,7 @@ disable_editor (EMsgComposer *composer)
action = GTKHTML_EDITOR_ACTION_INSERT_MENU (composer);
gtk_action_set_sensitive (action, FALSE);
- gtk_widget_set_sensitive (composer->priv->attachment_bar, FALSE);
+ gtk_widget_set_sensitive (composer->priv->attachment_paned, FALSE);
}
/**
@@ -3837,7 +3496,8 @@ add_recipients (GList *list, const gchar *recips)
static void
handle_mailto (EMsgComposer *composer, const gchar *mailto)
{
- EMsgComposerPrivate *priv = composer->priv;
+ EAttachmentView *view;
+ EAttachmentStore *store;
EComposerHeaderTable *table;
GList *to = NULL, *cc = NULL, *bcc = NULL;
EDestination **tov, **ccv, **bccv;
@@ -3846,9 +3506,10 @@ handle_mailto (EMsgComposer *composer, const gchar *mailto)
gsize nread, nwritten;
const gchar *p;
gint len, clen;
- CamelURL *url;
table = e_msg_composer_get_header_table (composer);
+ view = e_msg_composer_get_attachment_view (composer);
+ store = e_attachment_view_get_store (view);
buf = g_strdup (mailto);
@@ -3920,20 +3581,18 @@ handle_mailto (EMsgComposer *composer, const gchar *mailto)
}
} else if (!g_ascii_strcasecmp (header, "attach") ||
!g_ascii_strcasecmp (header, "attachment")) {
- /* Change file url to absolute path */
- if (!g_ascii_strncasecmp (content, "file:", 5)) {
- url = camel_url_new (content, NULL);
- e_attachment_bar_attach (E_ATTACHMENT_BAR (priv->attachment_bar),
- url->path,
- "attachment");
- camel_url_free (url);
- } else {
- e_attachment_bar_attach (E_ATTACHMENT_BAR (priv->attachment_bar),
- content,
- "attachment");
- }
- gtk_widget_show (priv->attachment_expander);
- gtk_widget_show (priv->attachment_scrolled_window);
+ EAttachment *attachment;
+
+ camel_url_decode (content);
+ if (g_ascii_strncasecmp (content, "file:", 5) == 0)
+ attachment = e_attachment_new_for_uri (content);
+ else
+ attachment = e_attachment_new_for_path (content);
+ e_attachment_store_add_attachment (store, attachment);
+ e_attachment_load_async (
+ attachment, (GAsyncReadyCallback)
+ e_attachment_load_handle_error, composer);
+ g_object_unref (attachment);
} else if (!g_ascii_strcasecmp (header, "from")) {
/* Ignore */
} else if (!g_ascii_strcasecmp (header, "reply-to")) {
@@ -3985,45 +3644,6 @@ handle_mailto (EMsgComposer *composer, const gchar *mailto)
}
}
-static void
-handle_uri (EMsgComposer *composer,
- const gchar *uri,
- gboolean html_dnd)
-{
- EMsgComposerPrivate *p = composer->priv;
- GtkhtmlEditor *editor;
- gboolean html_content;
-
- editor = GTKHTML_EDITOR (composer);
- html_content = gtkhtml_editor_get_html_mode (editor);
-
- if (!g_ascii_strncasecmp (uri, "mailto:", 7)) {
- handle_mailto (composer, uri);
- } else {
- CamelURL *url = camel_url_new (uri, NULL);
- gchar *type;
-
- if (!url)
- return;
-
- if (!g_ascii_strcasecmp (url->protocol, "file")) {
- type = e_util_guess_mime_type (uri + strlen ("file://"), TRUE);
- if (!type)
- return;
-
- if (strncmp (type, "image", 5) || !html_dnd || (!html_content && !strncmp (type, "image", 5))) {
- e_attachment_bar_attach (E_ATTACHMENT_BAR (p->attachment_bar),
- url->path, "attachment");
- }
- g_free (type);
- } else {
- e_attachment_bar_attach_remote_file (E_ATTACHMENT_BAR (p->attachment_bar),
- uri, "attachment");
- }
- camel_url_free (url);
- }
-}
-
/**
* e_msg_composer_new_from_url:
* @url: a mailto URL
@@ -4187,21 +3807,31 @@ e_msg_composer_remove_header (EMsgComposer *composer,
/**
* e_msg_composer_attach:
* @composer: a composer object
- * @attachment: the CamelMimePart to attach
+ * @mime_part: the #CamelMimePart to attach
*
* Attaches @attachment to the message being composed in the composer.
**/
void
-e_msg_composer_attach (EMsgComposer *composer, CamelMimePart *attachment)
+e_msg_composer_attach (EMsgComposer *composer,
+ CamelMimePart *mime_part)
{
- EAttachmentBar *bar;
- EMsgComposerPrivate *p = composer->priv;
+ EAttachmentView *view;
+ EAttachmentStore *store;
+ EAttachment *attachment;
g_return_if_fail (E_IS_MSG_COMPOSER (composer));
- g_return_if_fail (CAMEL_IS_MIME_PART (attachment));
-
- bar = E_ATTACHMENT_BAR (p->attachment_bar);
- e_attachment_bar_attach_mime_part (bar, attachment);
+ g_return_if_fail (CAMEL_IS_MIME_PART (mime_part));
+
+ view = e_msg_composer_get_attachment_view (composer);
+ store = e_attachment_view_get_store (view);
+
+ attachment = e_attachment_new ();
+ e_attachment_set_mime_part (attachment, mime_part);
+ e_attachment_store_add_attachment (store, attachment);
+ e_attachment_load_async (
+ attachment, (GAsyncReadyCallback)
+ e_attachment_load_handle_error, composer);
+ g_object_unref (attachment);
}
/**
@@ -4315,12 +3945,17 @@ CamelMimeMessage *
e_msg_composer_get_message (EMsgComposer *composer,
gboolean save_html_object_data)
{
+ EAttachmentView *view;
+ EAttachmentStore *store;
GtkhtmlEditor *editor;
gboolean html_content;
g_return_val_if_fail (E_IS_MSG_COMPOSER (composer), NULL);
- if (e_msg_composer_get_remote_download_count (composer) != 0) {
+ view = e_msg_composer_get_attachment_view (composer);
+ store = e_attachment_view_get_store (view);
+
+ if (e_attachment_store_get_num_loading (store) > 0) {
if (!em_utils_prompt_user (GTK_WINDOW (composer), NULL,
"mail-composer:ask-send-message-pending-download", NULL)) {
return NULL;
@@ -4623,14 +4258,6 @@ e_msg_composer_get_raw_message_text (EMsgComposer *composer)
return array;
}
-EAttachmentBar *
-e_msg_composer_get_attachment_bar (EMsgComposer *composer)
-{
- g_return_val_if_fail (E_IS_MSG_COMPOSER (composer), NULL);
-
- return E_ATTACHMENT_BAR (composer->priv->attachment_bar);
-}
-
void
e_msg_composer_set_enable_autosave (EMsgComposer *composer,
gboolean enabled)
@@ -4794,6 +4421,14 @@ e_msg_composer_get_header_table (EMsgComposer *composer)
return E_COMPOSER_HEADER_TABLE (composer->priv->header_table);
}
+EAttachmentView *
+e_msg_composer_get_attachment_view (EMsgComposer *composer)
+{
+ g_return_val_if_fail (E_IS_MSG_COMPOSER (composer), NULL);
+
+ return E_ATTACHMENT_VIEW (composer->priv->attachment_paned);
+}
+
void
e_msg_composer_set_send_options (EMsgComposer *composer,
gboolean send_enable)
diff --git a/composer/e-msg-composer.h b/composer/e-msg-composer.h
index f6b2ca7..54520ec 100644
--- a/composer/e-msg-composer.h
+++ b/composer/e-msg-composer.h
@@ -28,6 +28,7 @@
#include <libedataserver/e-account.h>
#include <libebook/e-destination.h>
#include <gtkhtml-editor.h>
+#include <widgets/misc/e-attachment-view.h>
#include "e-composer-header-table.h"
@@ -100,7 +101,7 @@ void e_msg_composer_modify_header (EMsgComposer *composer,
void e_msg_composer_remove_header (EMsgComposer *composer,
const gchar *name);
void e_msg_composer_attach (EMsgComposer *composer,
- CamelMimePart *attachment);
+ CamelMimePart *mime_part);
CamelMimePart * e_msg_composer_add_inline_image_from_file
(EMsgComposer *composer,
const gchar *filename);
@@ -139,22 +140,19 @@ void e_msg_composer_add_message_attachments
gboolean e_msg_composer_request_close_all(void);
EMsgComposer * e_msg_composer_load_from_file (const gchar *filename);
void e_msg_composer_check_autosave (GtkWindow *parent);
-gint e_msg_composer_get_remote_download_count
- (EMsgComposer *composer);
void e_msg_composer_reply_indent (EMsgComposer *composer);
EComposerHeaderTable *
e_msg_composer_get_header_table (EMsgComposer *composer);
+EAttachmentView *
+ e_msg_composer_get_attachment_view
+ (EMsgComposer *composer);
void e_msg_composer_set_send_options (EMsgComposer *composer,
gboolean send_enable);
GByteArray * e_msg_composer_get_raw_message_text
(EMsgComposer *composer);
-struct _EAttachmentBar *
- e_msg_composer_get_attachment_bar
- (EMsgComposer *composer);
-
gboolean e_msg_composer_is_exiting (EMsgComposer *composer);
GList * e_load_spell_languages (void);
diff --git a/configure.in b/configure.in
index 462a4e7..2595606 100644
--- a/configure.in
+++ b/configure.in
@@ -1775,12 +1775,12 @@ plugins_base_always="calendar-file calendar-http $CALENDAR_WEATHER itip-formatte
plugins_base="$plugins_base_always $SA_JUNK_PLUGIN $BF_JUNK_PLUGIN $EXCHANGE_PLUGIN $MONO_PLUGIN "
all_plugins_base="$plugins_base_always sa-junk-plugin bogo-junk-plugin exchange-operations mono"
-plugins_standard_always="bbdb subject-thread save-calendar select-one-source copy-tool mail-to-task audio-inline mailing-list-actions default-mailer import-ics-attachments prefer-plain mail-notification attachment-reminder face backup-restore email-custom-header templates pst-import"
+plugins_standard_always="bbdb subject-thread save-calendar select-one-source copy-tool mail-to-task audio-inline mailing-list-actions default-mailer prefer-plain mail-notification attachment-reminder face backup-restore email-custom-header templates pst-import"
plugins_standard="$plugins_standard_always"
all_plugins_standard="$plugins_standard"
-plugins_experimental_always="folder-unsubscribe save-attachments external-editor hula-account-setup"
+plugins_experimental_always="folder-unsubscribe external-editor hula-account-setup"
plugins_experimental="$plugins_experimental_always $IPOD_SYNC $TNEF_ATTACHMENTS $PYTHON_PLUGIN"
all_plugins_experimental="$plugins_experimental_always ipod-sync tnef-attachments"
@@ -2080,7 +2080,6 @@ plugins/mail-notification/Makefile
plugins/mail-to-task/Makefile
plugins/mono/Makefile
plugins/subject-thread/Makefile
-plugins/save-attachments/Makefile
plugins/save-calendar/Makefile
plugins/select-one-source/Makefile
plugins/prefer-plain/Makefile
@@ -2105,7 +2104,6 @@ plugins/sa-junk-plugin/Makefile
plugins/bogo-junk-plugin/Makefile
plugins/ipod-sync/Makefile
plugins/publish-calendar/Makefile
-plugins/import-ics-attachments/Makefile
plugins/imap-features/Makefile
plugins/tnef-attachments/Makefile
plugins/templates/Makefile
diff --git a/e-util/e-util.c b/e-util/e-util.c
index 0b28404..c012b26 100644
--- a/e-util/e-util.c
+++ b/e-util/e-util.c
@@ -186,6 +186,183 @@ exit:
}
/**
+ * e_lookup_action:
+ * @ui_manager: a #GtkUIManager
+ * @action_name: the name of an action
+ *
+ * Returns the first #GtkAction named @action_name by traversing the
+ * list of action groups in @ui_manager. If no such action exists, the
+ * function emits a critical warning before returning %NULL, since this
+ * probably indicates a programming error and most code is not prepared
+ * to deal with lookup failures.
+ *
+ * Returns: the first #GtkAction named @action_name
+ **/
+GtkAction *
+e_lookup_action (GtkUIManager *ui_manager,
+ const gchar *action_name)
+{
+ GtkAction *action = NULL;
+ GList *iter;
+
+ g_return_val_if_fail (GTK_IS_UI_MANAGER (ui_manager), NULL);
+ g_return_val_if_fail (action_name != NULL, NULL);
+
+ iter = gtk_ui_manager_get_action_groups (ui_manager);
+
+ while (iter != NULL) {
+ GtkActionGroup *action_group = iter->data;
+
+ action = gtk_action_group_get_action (
+ action_group, action_name);
+ if (action != NULL)
+ return action;
+
+ iter = g_list_next (iter);
+ }
+
+ g_critical ("%s: action `%s' not found", G_STRFUNC, action_name);
+
+ return NULL;
+}
+
+/**
+ * e_lookup_action_group:
+ * @ui_manager: a #GtkUIManager
+ * @group_name: the name of an action group
+ *
+ * Returns the #GtkActionGroup in @ui_manager named @group_name. If no
+ * such action group exists, the function emits a critical warnings before
+ * returning %NULL, since this probably indicates a programming error and
+ * most code is not prepared to deal with lookup failures.
+ *
+ * Returns: the #GtkActionGroup named @group_name
+ **/
+GtkActionGroup *
+e_lookup_action_group (GtkUIManager *ui_manager,
+ const gchar *group_name)
+{
+ GList *iter;
+
+ g_return_val_if_fail (GTK_IS_UI_MANAGER (ui_manager), NULL);
+ g_return_val_if_fail (group_name != NULL, NULL);
+
+ iter = gtk_ui_manager_get_action_groups (ui_manager);
+
+ while (iter != NULL) {
+ GtkActionGroup *action_group = iter->data;
+ const gchar *name;
+
+ name = gtk_action_group_get_name (action_group);
+ if (strcmp (name, group_name) == 0)
+ return action_group;
+
+ iter = g_list_next (iter);
+ }
+
+ g_critical ("%s: action group `%s' not found", G_STRFUNC, group_name);
+
+ return NULL;
+}
+
+/**
+ * e_load_ui_definition:
+ * @ui_manager: a #GtkUIManager
+ * @basename: basename of the UI definition file
+ *
+ * Loads a UI definition into @ui_manager from Evolution's UI directory.
+ * Failure here is fatal, since the application can't function without
+ * its UI definitions.
+ *
+ * Returns: The merge ID for the merged UI. The merge ID can be used to
+ * unmerge the UI with gtk_ui_manager_remove_ui().
+ **/
+guint
+e_load_ui_definition (GtkUIManager *ui_manager,
+ const gchar *basename)
+{
+ gchar *filename;
+ guint merge_id;
+ GError *error = NULL;
+
+ g_return_val_if_fail (GTK_IS_UI_MANAGER (ui_manager), 0);
+ g_return_val_if_fail (basename != NULL, 0);
+
+ filename = g_build_filename (EVOLUTION_UIDIR, basename, NULL);
+ merge_id = gtk_ui_manager_add_ui_from_file (
+ ui_manager, filename, &error);
+ g_free (filename);
+
+ if (error != NULL) {
+ g_error ("%s: %s", basename, error->message);
+ g_assert_not_reached ();
+ }
+
+ return merge_id;
+}
+
+/**
+ * e_action_compare_by_label:
+ * @action1: a #GtkAction
+ * @action2: a #GtkAction
+ *
+ * Compares the labels for @action1 and @action2 using g_utf8_collate().
+ *
+ * Returns: < 0 if @action1 compares before @action2, 0 if they
+ * compare equal, > 0 if @action1 compares after @action2
+ **/
+gint
+e_action_compare_by_label (GtkAction *action1,
+ GtkAction *action2)
+{
+ gchar *label1;
+ gchar *label2;
+ gint result;
+
+ /* XXX This is horribly inefficient but will generally only be
+ * used on short lists of actions during UI construction. */
+
+ if (action1 == action2)
+ return 0;
+
+ g_object_get (action1, "label", &label1, NULL);
+ g_object_get (action2, "label", &label2, NULL);
+
+ result = g_utf8_collate (label1, label2);
+
+ g_free (label1);
+ g_free (label2);
+
+ return result;
+}
+
+/**
+ * e_action_group_remove_all_actions:
+ * @action_group: a #GtkActionGroup
+ *
+ * Removes all actions from the action group.
+ **/
+void
+e_action_group_remove_all_actions (GtkActionGroup *action_group)
+{
+ GList *list, *iter;
+
+ /* XXX I've proposed this function for inclusion in GTK+.
+ * GtkActionGroup stores actions in an internal hash
+ * table and can do this more efficiently by calling
+ * g_hash_table_remove_all().
+ *
+ * http://bugzilla.gnome.org/show_bug.cgi?id=550485 */
+
+ g_return_if_fail (GTK_IS_ACTION_GROUP (action_group));
+
+ list = gtk_action_group_list_actions (action_group);
+ for (iter = list; iter != NULL; iter = iter->next)
+ gtk_action_group_remove_action (action_group, iter->data);
+ g_list_free (list);
+}
+
+/**
* e_str_without_underscores:
* @s: the string to strip underscores from.
*
@@ -1321,3 +1498,33 @@ e_util_get_category_filter_options (void)
return g_slist_reverse (res);
}
+
+static gpointer
+e_camel_object_copy (gpointer camel_object)
+{
+ if (CAMEL_IS_OBJECT (camel_object))
+ camel_object_ref (camel_object);
+
+ return camel_object;
+}
+
+static void
+e_camel_object_free (gpointer camel_object)
+{
+ if (CAMEL_IS_OBJECT (camel_object))
+ camel_object_unref (camel_object);
+}
+
+GType
+e_camel_object_get_type (void)
+{
+ static GType type = 0;
+
+ if (G_UNLIKELY (type == 0))
+ type = g_boxed_type_register_static (
+ "ECamelObject",
+ (GBoxedCopyFunc) e_camel_object_copy,
+ (GBoxedFreeFunc) e_camel_object_free);
+
+ return type;
+}
diff --git a/e-util/e-util.h b/e-util/e-util.h
index 021e328..480da24 100644
--- a/e-util/e-util.h
+++ b/e-util/e-util.h
@@ -27,6 +27,7 @@
#include <gtk/gtk.h>
#include <limits.h>
#include <gconf/gconf-client.h>
+#include <camel/camel-object.h>
#include <cairo.h>
#include <e-util/e-marshal.h>
@@ -46,6 +47,16 @@ void e_show_uri (GtkWindow *parent,
const gchar *uri);
void e_display_help (GtkWindow *parent,
const gchar *link_id);
+GtkAction * e_lookup_action (GtkUIManager *ui_manager,
+ const gchar *action_name);
+GtkActionGroup *e_lookup_action_group (GtkUIManager *ui_manager,
+ const gchar *group_name);
+guint e_load_ui_definition (GtkUIManager *ui_manager,
+ const gchar *basename);
+gint e_action_compare_by_label (GtkAction *action1,
+ GtkAction *action2);
+void e_action_group_remove_all_actions
+ (GtkActionGroup *action_group);
char * e_str_without_underscores (const char *s);
gint e_str_compare (gconstpointer x,
@@ -130,6 +141,11 @@ gboolean e_util_read_file (const gchar *filename,
GSList *e_util_get_category_filter_options (void);
+/* Camel uses its own object system, so we have to box
+ * CamelObjects to safely use them as GObject properties. */
+#define E_TYPE_CAMEL_OBJECT (e_camel_object_get_type ())
+GType e_camel_object_get_type (void);
+
G_END_DECLS
#endif /* _E_UTIL_H_ */
diff --git a/mail/Makefile.am b/mail/Makefile.am
index 23778d5..2a567ec 100644
--- a/mail/Makefile.am
+++ b/mail/Makefile.am
@@ -54,6 +54,7 @@ idl_DATA = $(MAIL_IDL)
# plugin mail api
mailinclude_HEADERS = \
$(MAIL_IDL_GENERATED_H) \
+ e-mail-attachment-bar.h \
em-composer-utils.h \
em-config.h \
em-event.h \
@@ -93,6 +94,9 @@ mailinclude_HEADERS = \
libevolution_mail_la_SOURCES = \
$(MAIL_IDL_GENERATED) \
$(mailinclude_HEADERS) \
+ e-attachment-handler-mail.c \
+ e-attachment-handler-mail.h \
+ e-mail-attachment-bar.c \
e-searching-tokenizer.c \
e-searching-tokenizer.h \
em-account-editor.c \
diff --git a/mail/em-filter-i18n.h b/mail/em-filter-i18n.h
index 8b8d0c3..c0b2925 100644
--- a/mail/em-filter-i18n.h
+++ b/mail/em-filter-i18n.h
@@ -26,6 +26,7 @@ char *s = N_("Exist");
char *s = N_("exists");
char *s = N_("Expression");
char *s = N_("Follow Up");
+char *s = N_("Forward to");
char *s = N_("Important");
char *s = N_("is");
char *s = N_("is after");
@@ -46,6 +47,7 @@ char *s = N_("Message Body");
char *s = N_("Message Header");
char *s = N_("Message is Junk");
char *s = N_("Message is not Junk");
+char *s = N_("Message Location");
char *s = N_("Move to Folder");
char *s = N_("Pipe to Program");
char *s = N_("Play Sound");
diff --git a/mail/em-format-html-display.c b/mail/em-format-html-display.c
index ad72ee8..7897058 100644
--- a/mail/em-format-html-display.c
+++ b/mail/em-format-html-display.c
@@ -80,14 +80,15 @@
#include "mail-config.h"
+#include "e-mail-attachment-bar.h"
#include "em-format-html-display.h"
#include "e-searching-tokenizer.h"
#include "em-icon-stream.h"
#include "em-utils.h"
#include "em-popup.h"
-#include "e-attachment.h"
-#include "e-attachment-bar.h"
#include "e-icon-entry.h"
+#include "widgets/misc/e-attachment-button.h"
+#include "widgets/misc/e-attachment-view.h"
#ifdef G_OS_WIN32
/* Undefine the similar macro from <pthread.h>,it doesn't check if
@@ -113,18 +114,7 @@ struct _EMFormatHTMLDisplayPrivate {
int search_wrap; /* are we doing a wrap search */
gboolean search_active; /* if the search is active */
- /* for Attachment bar */
- GtkWidget *attachment_bar;
- GtkWidget *attachment_box;
- GtkWidget *label;
- GtkWidget *save_txt;
- GtkWidget *arrow;
- GtkWidget *forward;
- GtkWidget *down;
- GtkWidget *attachment_area;
- gboolean show_bar;
- GHashTable *files;
- gboolean updated;
+ GtkWidget *attachment_view; /* weak reference */
};
static int efhd_html_button_press_event (GtkWidget *widget, GdkEventButton *event, EMFormatHTMLDisplay *efh);
@@ -134,8 +124,6 @@ static void efhd_html_on_url (GtkHTML *html, const char *url, EMFormatHTMLDispla
static void efhd_attachment_frame(EMFormat *emf, CamelStream *stream, EMFormatPURI *puri);
static gboolean efhd_attachment_image(EMFormatHTML *efh, GtkHTMLEmbedded *eb, EMFormatHTMLPObject *pobject);
static void efhd_message_add_bar(EMFormat *emf, CamelStream *stream, CamelMimePart *part, const EMFormatHandler *info);
-static void efhd_message_update_bar(EMFormat *emf, CamelStream *stream, CamelMimePart *part, const EMFormatHandler *info);
-static void efhd_attachment_bar_refresh (EMFormatHTMLDisplay *efhd);
struct _attach_puri {
EMFormatPURI puri;
@@ -186,7 +174,6 @@ static void efhd_format_attachment(EMFormat *, CamelStream *, CamelMimePart *, c
static void efhd_format_optional(EMFormat *, CamelStream *, CamelMimePart *, CamelStream *);
static void efhd_format_secure(EMFormat *emf, CamelStream *stream, CamelMimePart *part, CamelCipherValidity *valid);
static void efhd_complete(EMFormat *);
-gboolean efhd_mnemonic_show_bar (GtkWidget *widget, gboolean focus, GtkWidget *efhd);
static gboolean efhd_bonobo_object(EMFormatHTML *efh, GtkHTMLEmbedded *eb, EMFormatHTMLPObject *pobject);
static gboolean efhd_use_component(const char *mime_type);
@@ -279,9 +266,6 @@ efhd_init(GObject *o)
#undef efh
efhd->nobar = getenv("EVOLUTION_NO_BAR") != NULL;
-
- efhd->priv->show_bar = FALSE;
- efhd->priv->files = NULL;
}
static void
@@ -291,9 +275,6 @@ efhd_finalise(GObject *o)
/* check pending stuff */
- if (efhd->priv->files)
- g_hash_table_destroy(efhd->priv->files);
-
g_free(efhd->priv->search_text);
g_free(efhd->priv);
@@ -431,12 +412,6 @@ void em_format_html_display_set_caret_mode(EMFormatHTMLDisplay *efhd, gboolean s
gtk_html_set_caret_mode(((EMFormatHTML *)efhd)->html, state);
}
-EAttachmentBar *
-em_format_html_display_get_bar (EMFormatHTMLDisplay *efhd)
-{
- return E_ATTACHMENT_BAR (efhd->priv->attachment_bar);
-}
-
void
em_format_html_display_set_search(EMFormatHTMLDisplay *efhd, int type, GSList *strings)
{
@@ -933,11 +908,6 @@ efhd_complete(EMFormat *emf)
if (efhd->priv->search_dialog && efhd->priv->search_active)
efhd_update_matches(efhd);
-
- if (efhd->priv->files) {
- g_hash_table_destroy (efhd->priv->files);
- efhd->priv->files = NULL;
- }
}
/* ********************************************************************** */
@@ -1293,9 +1263,7 @@ static EMFormatHandler type_builtin_table[] = {
{ "image/pjpeg", (EMFormatFunc)efhd_image },
{ "x-evolution/message/prefix", (EMFormatFunc)efhd_message_prefix },
- { "x-evolution/message/post-header", (EMFormatFunc)efhd_message_add_bar },
- { "x-evolution/message/post-header-closure", (EMFormatFunc)efhd_message_update_bar },
-
+ { "x-evolution/message/post-header", (EMFormatFunc)efhd_message_add_bar }
};
static void
@@ -1343,15 +1311,8 @@ static const EMFormatHandler *efhd_find_handler(EMFormat *emf, const char *mime_
static void efhd_format_clone(EMFormat *emf, CamelFolder *folder, const char *uid, CamelMimeMessage *msg, EMFormat *src)
{
- EMFormatHTMLDisplay *efhd = (EMFormatHTMLDisplay *) emf;
-
- if (emf != src) {
- if (src)
- efhd->priv->show_bar = ((EMFormatHTMLDisplay *)src)->priv->show_bar;
- else
- efhd->priv->show_bar = FALSE;
+ if (emf != src)
((EMFormatHTML *) emf)->header_wrap_flags = 0;
- }
((EMFormatClass *)efhd_parent)->format_clone(emf, folder, uid, msg, src);
}
@@ -1467,12 +1428,14 @@ efhd_attachment_show(EPopup *ep, EPopupItem *item, void *data)
}
static void
-efhd_attachment_button_show(GtkWidget *w, void *data)
+efhd_attachment_button_expanded (GtkWidget *widget,
+ GParamSpec *pspec,
+ struct _attach_puri *info)
{
- if (!efhd_can_process_attachment (w))
+ if (!efhd_can_process_attachment (widget))
return;
- efhd_attachment_show(NULL, NULL, data);
+ efhd_attachment_show (NULL, NULL, info);
}
static void
@@ -1811,16 +1774,12 @@ static gboolean
efhd_attachment_button(EMFormatHTML *efh, GtkHTMLEmbedded *eb, EMFormatHTMLPObject *pobject)
{
EMFormatHTMLDisplay *efhd = (EMFormatHTMLDisplay *)efh;
- EAttachment *new;
struct _attach_puri *info;
- GtkWidget *hbox, *w, *button, *mainbox;
- char *simple_type, *tmp, *new_file = NULL;
- const char *file;
- GtkTargetEntry drag_types[] = {
- { NULL, 0, 0 },
- { "text/uri-list", 0, 1 },
- };
- AtkObject *a11y;
+ EAttachmentView *view;
+ EAttachmentStore *store;
+ EAttachment *attachment;
+ GtkWidget *widget;
+ gpointer parent;
/* FIXME: handle default shown case */
d(printf("adding attachment button/content\n"));
@@ -1832,139 +1791,36 @@ efhd_attachment_button(EMFormatHTML *efh, GtkHTMLEmbedded *eb, EMFormatHTMLPObje
return TRUE;
}
- if (efhd->priv->attachment_bar) {
- file = camel_mime_part_get_filename(info->puri.part);
-
- new = info->attachment;
-
- if (!file) {
- file = "attachment.dat";
- new->file_name = g_strdup(file);
- }
-
- tmp = g_hash_table_lookup (efhd->priv->files, file);
- if (tmp) {
- guint count = GPOINTER_TO_UINT(tmp);
- char *ext;
- char *tmp_file = g_strdup (file);
-
- if ((ext = strrchr(tmp_file, '.'))) {
- ext[0] = 0;
- new_file = g_strdup_printf("%s(%d).%s", tmp_file, count++, ext+1);
- } else {
- new_file = g_strdup_printf("%s(%d)", tmp_file, count++);
- }
-
- g_free (tmp_file);
- g_hash_table_insert (efhd->priv->files, g_strdup(file), GUINT_TO_POINTER(count));
- g_free (new->file_name);
- new->file_name = new_file;
- } else {
- g_hash_table_insert (efhd->priv->files, g_strdup(file), GUINT_TO_POINTER(1));
- }
-
- /* Store the status of encryption / signature on the attachment for emblem display
- * FIXME: May not work well always
- */
- new->sign = info->sign;
- new->encrypt = info->encrypt;
-
- /* Add the attachment to the bar.*/
- e_attachment_bar_add_attachment_silent (E_ATTACHMENT_BAR(efhd->priv->attachment_bar), new);
- efhd_attachment_bar_refresh(efhd);
- }
-
- mainbox = gtk_hbox_new(FALSE, 0);
-
- button = gtk_button_new();
-
- if (info->handle) {
- g_signal_connect(button, "clicked", G_CALLBACK(efhd_attachment_button_show), info);
- g_object_set_data (G_OBJECT (button), "efh", efh);
- } else {
- gtk_widget_set_sensitive(button, FALSE);
- GTK_WIDGET_UNSET_FLAGS(button, GTK_CAN_FOCUS);
- }
-
- hbox = gtk_hbox_new(FALSE, 2);
- info->forward = gtk_image_new_from_stock(GTK_STOCK_GO_FORWARD, GTK_ICON_SIZE_BUTTON);
- gtk_box_pack_start((GtkBox *)hbox, info->forward, TRUE, TRUE, 0);
- if (info->handle) {
- info->down = gtk_image_new_from_stock(GTK_STOCK_GO_DOWN, GTK_ICON_SIZE_BUTTON);
- gtk_box_pack_start((GtkBox *)hbox, info->down, TRUE, TRUE, 0);
- }
-
- w = gtk_image_new();
- gtk_widget_set_size_request(w, 24, 24);
- gtk_box_pack_start((GtkBox *)hbox, w, TRUE, TRUE, 0);
- gtk_container_add((GtkContainer *)button, hbox);
- gtk_box_pack_start((GtkBox *)mainbox, button, TRUE, TRUE, 0);
-
- /* Check for snooped type to get the right icon/processing */
- if (info->snoop_mime_type)
- simple_type = g_strdup(info->snoop_mime_type);
- else
- simple_type = camel_content_type_simple (((CamelDataWrapper *)pobject->part)->mime_type);
- camel_strdown(simple_type);
-
- /* FIXME: offline parts, just get icon */
- if (camel_content_type_is(((CamelDataWrapper *)pobject->part)->mime_type, "image", "*")) {
- EMFormatHTMLJob *job;
- GdkPixbuf *mini;
- char *key;
-
- key = pobject->classid;
- mini = em_icon_stream_get_image(key, 24, 24);
- if (mini) {
- d(printf("got image from cache '%s'\n", key));
- gtk_image_set_from_pixbuf((GtkImage *)w, mini);
- g_object_unref(mini);
- } else {
- d(printf("need to create icon image '%s'\n", key));
- job = em_format_html_job_new(efh, efhd_write_icon_job, pobject);
- job->stream = (CamelStream *)em_icon_stream_new((GtkImage *)w, key, 24, 24, FALSE);
- em_format_html_job_queue(efh, job);
- }
- } else {
- GdkPixbuf *pixbuf, *mini;
-
- if ((pixbuf = e_icon_for_mime_type (simple_type, 24))) {
- if ((mini = e_icon_factory_pixbuf_scale (pixbuf, 24, 24))) {
- gtk_image_set_from_pixbuf ((GtkImage *) w, mini);
- g_object_unref (mini);
- }
- g_object_unref (pixbuf);
- }
- }
-
- drag_types[0].target = simple_type;
- gtk_drag_source_set(button, GDK_BUTTON1_MASK, drag_types, sizeof(drag_types)/sizeof(drag_types[0]), GDK_ACTION_COPY);
- g_signal_connect(button, "drag-data-get", G_CALLBACK(efhd_drag_data_get), pobject);
- g_signal_connect (button, "drag-data-delete", G_CALLBACK(efhd_drag_data_delete), pobject);
- g_free(simple_type);
+ attachment = info->attachment;
+ e_attachment_set_shown (attachment, info->shown);
+ e_attachment_set_signed (attachment, info->sign);
+ e_attachment_set_encrypted (attachment, info->encrypt);
+ e_attachment_set_can_show (attachment, info->handle != NULL);
- button = gtk_button_new();
- /*GTK_WIDGET_UNSET_FLAGS(button, GTK_CAN_FOCUS);*/
- gtk_container_add((GtkContainer *)button, gtk_arrow_new(GTK_ARROW_DOWN, GTK_SHADOW_NONE));
+ parent = gtk_widget_get_toplevel (GTK_WIDGET (efh->html));
+ parent = GTK_WIDGET_TOPLEVEL (parent) ? parent : NULL;
- a11y = gtk_widget_get_accessible (button);
- atk_object_set_name (a11y, _("Attachment"));
+ view = E_ATTACHMENT_VIEW (efhd->priv->attachment_view);
+ gtk_widget_show (efhd->priv->attachment_view);
- g_signal_connect(button, "button_press_event", G_CALLBACK(efhd_attachment_popup), info);
- g_signal_connect(button, "popup_menu", G_CALLBACK(efhd_attachment_popup_menu), info);
- g_signal_connect(button, "clicked", G_CALLBACK(efhd_attachment_popup_menu), info);
- gtk_box_pack_start((GtkBox *)mainbox, button, TRUE, TRUE, 0);
+ store = e_attachment_view_get_store (view);
+ e_attachment_store_add_attachment (store, info->attachment);
- g_object_set_data (G_OBJECT (button), "efh", efh);
+ e_attachment_load_async (
+ info->attachment, (GAsyncReadyCallback)
+ e_attachment_load_handle_error, parent);
- gtk_widget_show_all(mainbox);
+ widget = e_attachment_button_new (view);
+ e_attachment_button_set_attachment (
+ E_ATTACHMENT_BUTTON (widget), attachment);
+ gtk_container_add (GTK_CONTAINER (eb), widget);
+ gtk_widget_show (widget);
- if (info->shown)
- gtk_widget_hide(info->forward);
- else if (info->down)
- gtk_widget_hide(info->down);
+ g_object_set_data (G_OBJECT (widget), "efh", efh);
- gtk_container_add((GtkContainer *)eb, mainbox);
+ g_signal_connect (
+ widget, "notify::expanded",
+ G_CALLBACK (efhd_attachment_button_expanded), info);
return TRUE;
}
@@ -2138,330 +1994,57 @@ type_ok:
}
static void
-attachment_bar_arrow_clicked(GtkWidget *w, EMFormatHTMLDisplay *efhd)
+efhd_bar_resize (EMFormatHTML *efh,
+ GtkAllocation *event)
{
+ EMFormatHTMLDisplay *efhd = (EMFormatHTMLDisplay *) efh;
+ GtkWidget *widget;
+ gint width;
- efhd->priv->show_bar = !efhd->priv->show_bar;
+ widget = GTK_WIDGET (efh->html);
+ width = widget->allocation.width - 12;
- if (efhd->priv->show_bar) {
- gtk_widget_show(efhd->priv->attachment_box);
- gtk_widget_show(efhd->priv->down);
- gtk_widget_hide(efhd->priv->forward);
- } else {
- gtk_widget_hide(efhd->priv->attachment_box);
- gtk_widget_show(efhd->priv->forward);
- gtk_widget_hide(efhd->priv->down);
+ if (width > 0) {
+ widget = efhd->priv->attachment_view;
+ gtk_widget_set_size_request (widget, width, -1);
}
}
-static void
-attachments_save_all_clicked (GtkWidget *widget, EMFormatHTMLDisplay *efhd)
-{
- GSList *attachment_parts;
- guint n_attachment_parts;
-
- attachment_parts = e_attachment_bar_get_parts (
- E_ATTACHMENT_BAR (efhd->priv->attachment_bar));
- n_attachment_parts = g_slist_length (attachment_parts);
- g_return_if_fail (n_attachment_parts > 0);
-
- if (n_attachment_parts == 1)
- em_utils_save_part (
- widget, _("Save attachment as"),
- attachment_parts->data);
- else
- em_utils_save_parts (
- widget, _("Select folder to save all attachments"),
- attachment_parts);
-
- g_slist_free (attachment_parts);
-}
-
-static void
-efhd_bar_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, GPOINTER_TO_INT(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
-efhd_bar_save_selected(EPopup *ep, EPopupItem *item, void *data)
-{
- EMFormatHTMLDisplay *efhd = (EMFormatHTMLDisplay *)data;
- GSList *attachment_parts, *tmp;
- GSList *parts = NULL;
-
- attachment_parts = e_attachment_bar_get_selected(E_ATTACHMENT_BAR(efhd->priv->attachment_bar));
-
- for (tmp = attachment_parts; tmp; tmp=tmp->next)
- parts = g_slist_prepend(parts, ((EAttachment *)tmp->data)->body);
-
- parts = g_slist_reverse(parts);
- em_utils_save_parts(efhd->priv->attachment_bar, _("Select folder to save selected attachments..."), parts);
- g_slist_free (parts);
-
- g_slist_foreach(attachment_parts, (GFunc)g_object_unref, NULL);
- g_slist_free (attachment_parts);
-}
-
-static EPopupItem efhd_bar_menu_items[] = {
- { E_POPUP_BAR, "05.display", },
- { E_POPUP_ITEM, "05.display.01", N_("_Save Selected..."), efhd_bar_save_selected, NULL, NULL, EM_POPUP_ATTACHMENTS_MULTIPLE},
-};
-
-static gboolean
-efhd_bar_button_press_event(EAttachmentBar *bar, GdkEventButton *event, EMFormat *emf)
-{
- GtkMenu *menu;
- GSList *list=NULL;
- EPopupTarget *target;
- EMPopup *emp;
- GSList *menus = NULL;
- int i;
-
- if (event && event->button != 3)
- return FALSE;
-
- /** @HookPoint-EMPopup: Attachment Bar Context Menu
- * @Id: org.gnome.evolution.mail.attachments.popup
- * @Class: org.gnome.evolution.mail.popup:1.0
- * @Target: EMPopupTargetPart
- *
- * This is the drop-down menu shown when a user clicks on the attachment bar
- * when attachments are selected.
- */
- emp = em_popup_new("org.gnome.evolution.mail.attachments.popup");
-
- /* Add something like save-selected, foward selected attachments in a mail etc....*/
- list = e_attachment_bar_get_selected(bar);
-
- /* Lets not propagate any more the r-click which is intended to us*/
- if ( g_slist_length (list) == 0)
- return TRUE;
-
- target = (EPopupTarget *)em_popup_target_new_attachments(emp, list);
- for (i=0; i<2; i++)
- menus = g_slist_prepend(menus, &efhd_bar_menu_items[i]);
- e_popup_add_items((EPopup *)emp, menus, NULL, efhd_menu_items_free, emf);
-
- ((EMPopupTargetPart *)target)->target.widget = (GtkWidget *)bar;
- menu = e_popup_create_menu_once((EPopup *)emp, (EPopupTarget *)target, 0);
- if (event)
- gtk_menu_popup(menu, NULL, NULL, NULL, NULL, event->button, event->time);
- else
- gtk_menu_popup(menu, NULL, NULL, (GtkMenuPositionFunc)efhd_bar_popup_position, bar, 0, gtk_get_current_event_time());
-
- return TRUE;
-}
-
static gboolean
-efhd_bar_popup_menu_event (EAttachmentBar *bar, EMFormat *emf)
-{
- return efhd_bar_button_press_event(bar, NULL, emf);
-}
-
-static void
-efhd_attachment_bar_refresh (EMFormatHTMLDisplay *efhd)
-{
- int nattachments;
-
- if (!efhd->priv->attachment_bar)
- return;
-
- nattachments = e_attachment_bar_get_num_attachments (E_ATTACHMENT_BAR(efhd->priv->attachment_bar));
- if (nattachments) {
- char *txt;
-
- /* Cant i put in the number of attachments here ?*/
- txt = g_strdup_printf(ngettext("%d at_tachment", "%d at_tachments", nattachments), nattachments);
- gtk_label_set_text_with_mnemonic ((GtkLabel *)efhd->priv->label, txt);
- g_free (txt);
-
- /* Show the bar even when the first attachment is added */
- if (nattachments == 1) {
- gtk_widget_show_all (efhd->priv->attachment_area);
- gtk_label_set_text_with_mnemonic ((GtkLabel *)efhd->priv->save_txt, _("S_ave"));
-
- if (efhd->priv->show_bar) {
- gtk_widget_show(efhd->priv->down);
- gtk_widget_hide(efhd->priv->forward);
- } else {
- gtk_widget_show(efhd->priv->forward);
- gtk_widget_hide(efhd->priv->down);
- gtk_widget_hide(efhd->priv->attachment_box);
- }
- } else if (nattachments > 1) {
- gtk_label_set_text_with_mnemonic ((GtkLabel *)efhd->priv->save_txt, _("S_ave All"));
- }
- }
-}
-
-static void
-efhd_bar_resize(GtkWidget *w, GtkAllocation *event, EMFormatHTML *efh)
+efhd_add_bar (EMFormatHTML *efh,
+ GtkHTMLEmbedded *eb,
+ EMFormatHTMLPObject *pobject)
{
- int width;
- GtkRequisition req;
EMFormatHTMLDisplay *efhd = (EMFormatHTMLDisplay *) efh;
+ GtkWidget *widget;
- gtk_widget_size_request (efhd->priv->attachment_bar, &req);
- width = ((GtkWidget *) efh->html)->allocation.width - 16;
-
- /* Update the width of the bar when the width is greater than 1*/
- if (width > 0)
- e_attachment_bar_set_width(E_ATTACHMENT_BAR(efhd->priv->attachment_bar), width);
-}
-
-static gboolean
-efhd_bar_scroll_event(GtkWidget *w, GdkEventScroll *event, EMFormatHTMLDisplay *efhd)
-{
- gboolean ret;
-
- /* Emulate the scroll over the attachment bar, as if it is scrolled in the window.
- * It doesnt go automatically since the GnomeIconList is a layout by itself
- */
- g_signal_emit_by_name (gtk_widget_get_parent((GtkWidget *)efhd->formathtml.html), "scroll_event", event, &ret);
-
- return TRUE;
-}
-
-gboolean
-efhd_mnemonic_show_bar (GtkWidget *widget, gboolean focus, GtkWidget *efhd)
-{
- attachment_bar_arrow_clicked (NULL, (EMFormatHTMLDisplay *)efhd);
-
- return TRUE;
-}
-
-static gboolean
-efhd_update_bar(EMFormatHTML *efh, GtkHTMLEmbedded *eb, EMFormatHTMLPObject *pobject)
-{
- EMFormatHTMLDisplay *efhd = (EMFormatHTMLDisplay *)efh;
- struct _EMFormatHTMLDisplayPrivate *priv = efhd->priv;
-
- if (priv->attachment_bar)
- e_attachment_bar_refresh (E_ATTACHMENT_BAR (priv->attachment_bar));
-
- return TRUE;
-}
-
-static gboolean
-efhd_add_bar(EMFormatHTML *efh, GtkHTMLEmbedded *eb, EMFormatHTMLPObject *pobject)
-{
- EMFormatHTMLDisplay *efhd = (EMFormatHTMLDisplay *)efh;
- struct _EMFormatHTMLDisplayPrivate *priv = efhd->priv;
- GtkWidget *hbox1, *hbox2, *hbox3, *vbox, *txt, *image, *save, *scroll;
- int width, height, bar_width;
-
- priv->attachment_bar = e_attachment_bar_new(NULL);
- scroll = gtk_scrolled_window_new (NULL, NULL);
- gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scroll), GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
- ((EAttachmentBar *)priv->attachment_bar)->expand = TRUE;
-
- priv->forward = gtk_arrow_new(GTK_ARROW_RIGHT, GTK_SHADOW_NONE);
- priv->down = gtk_arrow_new(GTK_ARROW_DOWN, GTK_SHADOW_NONE);
- hbox3 = gtk_hbox_new (FALSE, 0);
- gtk_box_pack_start ((GtkBox *)hbox3, priv->forward, FALSE, FALSE, 0);
- gtk_box_pack_start ((GtkBox *)hbox3, priv->down, FALSE, FALSE, 0);
- priv->arrow = (GtkWidget *)gtk_tool_button_new(hbox3, NULL);
- g_signal_connect (priv->arrow, "mnemonic_activate", G_CALLBACK (efhd_mnemonic_show_bar), efh);
- atk_object_set_name (gtk_widget_get_accessible (priv->arrow), _("Show Attachments"));
-
- priv->label = gtk_label_new(_("No Attachment"));
- gtk_label_set_mnemonic_widget (GTK_LABEL (priv->label), priv->arrow);
- save = gtk_button_new();
- image = gtk_image_new_from_stock ("gtk-save", GTK_ICON_SIZE_BUTTON);
- txt = gtk_label_new_with_mnemonic(_("S_ave"));
- priv->save_txt = txt;
- hbox1 = gtk_hbox_new(FALSE, 0);
- gtk_box_pack_start((GtkBox *)hbox1, image, FALSE, FALSE, 2);
- gtk_box_pack_start((GtkBox *)hbox1, txt, FALSE, FALSE, 0);
-
- gtk_container_add((GtkContainer *)save, hbox1);
-
- hbox2 = gtk_hbox_new (FALSE, 0);
- gtk_box_pack_start ((GtkBox *)hbox2, priv->arrow, FALSE, FALSE, 0);
- gtk_box_pack_start ((GtkBox *)hbox2, priv->label, FALSE, FALSE, 2);
- gtk_box_pack_start ((GtkBox *)hbox2, save, FALSE, FALSE, 2);
-
- priv->attachment_box = scroll;
- gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (scroll), GTK_SHADOW_IN);
- gtk_container_add ((GtkContainer *)priv->attachment_box, priv->attachment_bar);
-
- gtk_widget_get_size_request(priv->attachment_bar, &width, &height);
-
- /* FIXME: What if the text is more?. Should we reduce the text with appending ...?
- * or resize the bar? How to figure out that, it needs more space? */
- bar_width = ((GtkWidget *)efh->html)->parent->allocation.width - /* FIXME */16;
- gtk_widget_set_size_request (priv->attachment_bar,
- bar_width > 0 ? bar_width : 0,
- 84 /* FIXME: Default show only one row, Dont hardcode size*/);
-
- vbox = gtk_vbox_new (FALSE, 0);
- gtk_box_pack_start ((GtkBox *)vbox, hbox2, FALSE, FALSE, 2);
- gtk_box_pack_start ((GtkBox *)vbox, priv->attachment_box, TRUE, TRUE, 2);
-
- gtk_container_add ((GtkContainer *)eb, vbox);
- gtk_widget_show ((GtkWidget *)eb);
-
- /* Lets hide it by default and show only when there are attachments */
- priv->attachment_area = vbox;
- gtk_widget_hide_all (priv->attachment_area);
+ widget = e_mail_attachment_bar_new ();
+ gtk_container_add (GTK_CONTAINER (eb), widget);
+ efhd->priv->attachment_view = widget;
+ gtk_widget_hide (widget);
- g_signal_connect (priv->arrow, "clicked", G_CALLBACK(attachment_bar_arrow_clicked), efh);
- g_signal_connect (priv->attachment_bar, "button_press_event", G_CALLBACK(efhd_bar_button_press_event), efhd);
- g_signal_connect (priv->attachment_bar, "popup-menu", G_CALLBACK(efhd_bar_popup_menu_event), efhd);
- g_signal_connect (save, "clicked", G_CALLBACK(attachments_save_all_clicked), efh);
- g_signal_connect (eb, "size_allocate", G_CALLBACK (efhd_bar_resize), efh);
- g_signal_connect (priv->attachment_bar, "scroll_event", G_CALLBACK(efhd_bar_scroll_event), efhd);
+ g_signal_connect_swapped (
+ eb, "size-allocate",
+ G_CALLBACK (efhd_bar_resize), efh);
return TRUE;
}
-static void
-efhd_message_update_bar(EMFormat *emf, CamelStream *stream, CamelMimePart *part, const EMFormatHandler *info)
-{
- EMFormatHTMLDisplay *efhd = (EMFormatHTMLDisplay *) emf;
- const char *classid = "attachment-bar-refresh";
-
- if (efhd->nobar || efhd->priv->updated)
- return;
-
- efhd->priv->files = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
- efhd->priv->updated = TRUE;
- em_format_html_add_pobject((EMFormatHTML *)emf, sizeof(EMFormatHTMLPObject), classid, part, efhd_update_bar);
- camel_stream_printf(stream, "<td><object classid=\"%s\"></object></td>", classid);
-
-}
static void
-efhd_message_add_bar(EMFormat *emf, CamelStream *stream, CamelMimePart *part, const EMFormatHandler *info)
+efhd_message_add_bar (EMFormat *emf,
+ CamelStream *stream,
+ CamelMimePart *part,
+ const EMFormatHandler *info)
{
- EMFormatHTMLDisplay *efhd = (EMFormatHTMLDisplay *) emf;
const char *classid = "attachment-bar";
- if (efhd->nobar || efhd->priv->files)
- return;
+ em_format_html_add_pobject (
+ (EMFormatHTML *) emf,
+ sizeof (EMFormatHTMLPObject),
+ classid, part, efhd_add_bar);
- efhd->priv->files = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
- efhd->priv->updated = FALSE;
-
- em_format_html_add_pobject((EMFormatHTML *)emf, sizeof(EMFormatHTMLPObject), classid, part, efhd_add_bar);
- camel_stream_printf(stream, "<td><object classid=\"%s\"></object></td>", classid);
+ camel_stream_printf (
+ stream, "<td><object classid=\"%s\"></object></td>", classid);
}
static void
@@ -2470,43 +2053,50 @@ efhd_format_attachment(EMFormat *emf, CamelStream *stream, CamelMimePart *part,
char *classid, *text, *html;
struct _attach_puri *info;
- classid = g_strdup_printf("attachment%s", emf->part_id->str);
- info = (struct _attach_puri *)em_format_add_puri(emf, sizeof(*info), classid, part, efhd_attachment_frame);
- em_format_html_add_pobject((EMFormatHTML *)emf, sizeof(EMFormatHTMLPObject), classid, part, efhd_attachment_button);
+ classid = g_strdup_printf ("attachment%s", emf->part_id->str);
+ info = (struct _attach_puri *)em_format_add_puri (
+ emf, sizeof (*info), classid, part, efhd_attachment_frame);
+ em_format_html_add_pobject (
+ (EMFormatHTML *) emf, sizeof (EMFormatHTMLPObject),
+ classid, part, efhd_attachment_button);
info->handle = handle;
- info->shown = em_format_is_inline(emf, info->puri.part_id, info->puri.part, handle);
+ info->shown = em_format_is_inline (
+ emf, info->puri.part_id, info->puri.part, handle);
info->snoop_mime_type = emf->snoop_mime_type;
- info->attachment = e_attachment_new_from_mime_part (info->puri.part);
- e_attachment_bar_create_attachment_cache (info->attachment);
+ info->attachment = e_attachment_new ();
+ e_attachment_set_mime_part (info->attachment, info->puri.part);
if (emf->valid) {
info->sign = emf->valid->sign.status;
info->encrypt = emf->valid->encrypt.status;
}
- camel_stream_write_string(stream,
- EM_FORMAT_HTML_VPAD
- "<table cellspacing=0 cellpadding=0><tr><td>"
- "<table width=10 cellspacing=0 cellpadding=0>"
- "<tr><td></td></tr></table></td>");
+ camel_stream_write_string (
+ stream, EM_FORMAT_HTML_VPAD
+ "<table cellspacing=0 cellpadding=0><tr><td>"
+ "<table width=10 cellspacing=0 cellpadding=0>"
+ "<tr><td></td></tr></table></td>");
- camel_stream_printf(stream, "<td><object classid=\"%s\"></object></td>", classid);
+ camel_stream_printf (
+ stream, "<td><object classid=\"%s\"></object></td>", classid);
- camel_stream_write_string(stream,
- "<td><table width=3 cellspacing=0 cellpadding=0>"
- "<tr><td></td></tr></table></td><td><font size=-1>");
+ camel_stream_write_string (
+ stream, "<td><table width=3 cellspacing=0 cellpadding=0>"
+ "<tr><td></td></tr></table></td><td><font size=-1>");
/* output some info about it */
/* FIXME: should we look up mime_type from object again? */
- text = em_format_describe_part(part, mime_type);
- html = camel_text_to_html(text, ((EMFormatHTML *)emf)->text_html_flags & CAMEL_MIME_FILTER_TOHTML_CONVERT_URLS, 0);
- camel_stream_write_string(stream, html);
- g_free(html);
- g_free(text);
-
- camel_stream_write_string(stream,
- "</font></td></tr><tr></table>\n"
- EM_FORMAT_HTML_VPAD);
+ text = em_format_describe_part (part, mime_type);
+ html = camel_text_to_html (
+ text, ((EMFormatHTML *)emf)->text_html_flags &
+ CAMEL_MIME_FILTER_TOHTML_CONVERT_URLS, 0);
+ camel_stream_write_string (stream, html);
+ g_free (html);
+ g_free (text);
+
+ camel_stream_write_string (
+ stream, "</font></td></tr><tr></table>\n"
+ EM_FORMAT_HTML_VPAD);
if (handle) {
if (info->shown)
@@ -2653,7 +2243,8 @@ efhd_format_optional(EMFormat *emf, CamelStream *fstream, CamelMimePart *part, C
info->handle = em_format_find_handler(emf, "text/plain");
info->shown = FALSE;
info->snoop_mime_type = "text/plain";
- info->attachment = e_attachment_new_from_mime_part (info->puri.part);
+ info->attachment = e_attachment_new ();
+ e_attachment_set_mime_part (info->attachment, info->puri.part);
info->mstream = (CamelStreamMem *)mstream;
if (emf->valid) {
info->sign = emf->valid->sign.status;
diff --git a/mail/em-format-html-display.h b/mail/em-format-html-display.h
index 651b981..4e2e7c1 100644
--- a/mail/em-format-html-display.h
+++ b/mail/em-format-html-display.h
@@ -26,7 +26,6 @@
#define _EM_FORMAT_HTML_DISPLAY_H
#include "mail/em-format-html.h"
-#include "widgets/misc/e-attachment-bar.h"
typedef struct _EMFormatHTMLDisplay EMFormatHTMLDisplay;
typedef struct _EMFormatHTMLDisplayClass EMFormatHTMLDisplayClass;
@@ -82,7 +81,6 @@ void em_format_html_display_paste (EMFormatHTMLDisplay *efhd);
void em_format_html_display_zoom_in (EMFormatHTMLDisplay *efhd);
void em_format_html_display_zoom_out (EMFormatHTMLDisplay *efhd);
void em_format_html_display_zoom_reset (EMFormatHTMLDisplay *efhd);
-EAttachmentBar *em_format_html_display_get_bar (EMFormatHTMLDisplay *efhd);
gboolean em_format_html_display_popup_menu (EMFormatHTMLDisplay *efhd);
diff --git a/mail/em-popup.c b/mail/em-popup.c
index 91e6ed6..debad8c 100644
--- a/mail/em-popup.c
+++ b/mail/em-popup.c
@@ -100,12 +100,6 @@ emp_target_free(EPopup *ep, EPopupTarget *t)
g_free(s->uri);
break; }
- case EM_POPUP_TARGET_ATTACHMENTS: {
- EMPopupTargetAttachments *s = (EMPopupTargetAttachments *)t;
-
- g_slist_foreach(s->attachments, (GFunc)g_object_unref, NULL);
- g_slist_free(s->attachments);
- break; }
}
((EPopupClass *)emp_parent)->target_free(ep, t);
@@ -361,42 +355,6 @@ done:
return t;
}
-/**
- * em_popup_target_new_attachments:
- * @emp:
- * @attachments: A list of EMsgComposerAttachment objects, reffed for
- * the list. Will be unreff'd once finished with.
- *
- * Owns the list @attachments and their items after they're passed in.
- *
- * Return value:
- **/
-EMPopupTargetAttachments *
-em_popup_target_new_attachments(EMPopup *emp, GSList *attachments)
-{
- EMPopupTargetAttachments *t = e_popup_target_new(&emp->popup, EM_POPUP_TARGET_ATTACHMENTS, sizeof(*t));
- guint32 mask = ~0;
- int len = g_slist_length(attachments);
-
- t->attachments = attachments;
- if (len > 0)
- mask &= ~ EM_POPUP_ATTACHMENTS_MANY;
- if (len == 1 && ((EAttachment *)attachments->data)->is_available_local) {
-
- if (camel_content_type_is(((CamelDataWrapper *) ((EAttachment *) attachments->data)->body)->mime_type, "image", "*"))
- mask &= ~ EM_POPUP_ATTACHMENTS_IMAGE;
- if (CAMEL_IS_MIME_MESSAGE(camel_medium_get_content_object((CamelMedium *) ((EAttachment *) attachments->data)->body)))
- mask &= ~EM_POPUP_ATTACHMENTS_MESSAGE;
-
- mask &= ~ EM_POPUP_ATTACHMENTS_ONE;
- }
- if (len > 1)
- mask &= ~ EM_POPUP_ATTACHMENTS_MULTIPLE;
- t->target.mask = mask;
-
- return t;
-}
-
/* ********************************************************************** */
static void
@@ -405,11 +363,7 @@ emp_part_popup_saveas(EPopup *ep, EPopupItem *item, void *data)
EPopupTarget *t = ep->target;
CamelMimePart *part = NULL;
- /* If it is of type EM_POPUP_TARGET_ATTACHMENTS, we can assume the length is one. */
- if (t->type == EM_POPUP_TARGET_ATTACHMENTS)
- part = ((EAttachment *) ((EMPopupTargetAttachments *) t)->attachments->data)->body;
- else
- part = ((EMPopupTargetPart *) t)->part;
+ part = ((EMPopupTargetPart *) t)->part;
em_utils_save_part(ep->target->widget, _("Save As..."), part);
}
@@ -423,10 +377,7 @@ emp_part_popup_set_background(EPopup *ep, EPopupItem *item, void *data)
unsigned int i=1;
CamelMimePart *part = NULL;
- if (t->type == EM_POPUP_TARGET_ATTACHMENTS)
- part = ((EAttachment *) ((EMPopupTargetAttachments *) t)->attachments->data)->body;
- else
- part = ((EMPopupTargetPart *) t)->part;
+ part = ((EMPopupTargetPart *) t)->part;
if (!part)
return;
@@ -497,10 +448,7 @@ emp_part_popup_reply_sender(EPopup *ep, EPopupItem *item, void *data)
CamelMimeMessage *message;
CamelMimePart *part;
- if (t->type == EM_POPUP_TARGET_ATTACHMENTS)
- part = ((EAttachment *) ((EMPopupTargetAttachments *) t)->attachments->data)->body;
- else
- part = ((EMPopupTargetPart *) t)->part;
+ part = ((EMPopupTargetPart *) t)->part;
message = (CamelMimeMessage *)camel_medium_get_content_object((CamelMedium *)part);
em_utils_reply_to_message(NULL, NULL, message, REPLY_MODE_SENDER, NULL);
@@ -513,10 +461,7 @@ emp_part_popup_reply_list (EPopup *ep, EPopupItem *item, void *data)
CamelMimeMessage *message;
CamelMimePart *part;
- if (t->type == EM_POPUP_TARGET_ATTACHMENTS)
- part = ((EAttachment *) ((EMPopupTargetAttachments *) t)->attachments->data)->body;
- else
- part = ((EMPopupTargetPart *) t)->part;
+ part = ((EMPopupTargetPart *) t)->part;
message = (CamelMimeMessage *)camel_medium_get_content_object((CamelMedium *)part);
em_utils_reply_to_message(NULL, NULL, message, REPLY_MODE_LIST, NULL);
@@ -529,10 +474,7 @@ emp_part_popup_reply_all (EPopup *ep, EPopupItem *item, void *data)
CamelMimeMessage *message;
CamelMimePart *part;
- if (t->type == EM_POPUP_TARGET_ATTACHMENTS)
- part = ((EAttachment *) ((EMPopupTargetAttachments *) t)->attachments->data)->body;
- else
- part = ((EMPopupTargetPart *) t)->part;
+ part = ((EMPopupTargetPart *) t)->part;
message = (CamelMimeMessage *)camel_medium_get_content_object((CamelMedium *)part);
em_utils_reply_to_message(NULL, NULL, message, REPLY_MODE_ALL, NULL);
@@ -545,10 +487,7 @@ emp_part_popup_forward (EPopup *ep, EPopupItem *item, void *data)
CamelMimeMessage *message;
CamelMimePart *part;
- if (t->type == EM_POPUP_TARGET_ATTACHMENTS)
- part = ((EAttachment *) ((EMPopupTargetAttachments *) t)->attachments->data)->body;
- else
- part = ((EMPopupTargetPart *) t)->part;
+ part = ((EMPopupTargetPart *) t)->part;
/* TODO: have a emfv specific override so we can get the parent folder uri */
message = (CamelMimeMessage *)camel_medium_get_content_object((CamelMedium *) part);
@@ -566,17 +505,6 @@ static EMPopupItem emp_standard_object_popups[] = {
{ E_POPUP_ITEM, "20.part.00", N_("_Forward"), emp_part_popup_forward, NULL, "mail-forward", EM_POPUP_PART_MESSAGE },
};
-static EMPopupItem emp_attachment_object_popups[] = {
- { E_POPUP_ITEM, "00.attach.00", N_("_Save As..."), emp_part_popup_saveas, NULL, "document-save-as", 0 },
- { E_POPUP_ITEM, "00.attach.10", N_("Set as _Background"), emp_part_popup_set_background, NULL, NULL, EM_POPUP_ATTACHMENTS_IMAGE },
- { E_POPUP_BAR, "05.attach", NULL, NULL, NULL, NULL, EM_POPUP_ATTACHMENTS_MESSAGE },
- { E_POPUP_ITEM, "05.attach.00", N_("_Reply to sender"), emp_part_popup_reply_sender, NULL, "mail-reply-sender" , EM_POPUP_ATTACHMENTS_MESSAGE },
- { E_POPUP_ITEM, "05.attach.01", N_("Reply to _List"), emp_part_popup_reply_list, NULL, NULL, EM_POPUP_ATTACHMENTS_MESSAGE},
- { E_POPUP_ITEM, "05.attach.03", N_("Reply to _All"), emp_part_popup_reply_all, NULL, "mail-reply-all", EM_POPUP_ATTACHMENTS_MESSAGE},
- { E_POPUP_BAR, "05.attach.10", NULL, NULL, NULL, NULL, EM_POPUP_ATTACHMENTS_MESSAGE },
- { E_POPUP_ITEM, "05.attach.15", N_("_Forward"), emp_part_popup_forward, NULL, "mail-forward", EM_POPUP_ATTACHMENTS_MESSAGE },
-};
-
static const EPopupItem emp_standard_part_apps_bar = { E_POPUP_BAR, "99.object" };
/* ********************************************************************** */
@@ -634,10 +562,7 @@ emp_apps_open_in(EPopup *ep, EPopupItem *item, void *data)
EPopupTarget *target = ep->target;
CamelMimePart *part;
- if (target->type == EM_POPUP_TARGET_ATTACHMENTS)
- part = ((EAttachment *) ((EMPopupTargetAttachments *) target)->attachments->data)->body;
- else
- part = ((EMPopupTargetPart *) target)->part;
+ part = ((EMPopupTargetPart *) target)->part;
path = em_utils_temp_save_part(target->widget, part, TRUE);
if (path) {
@@ -705,10 +630,7 @@ emp_add_vcard (EPopup *ep, EPopupItem *item, void *data)
CamelStreamMem *mem;
- if (target->type == EM_POPUP_TARGET_ATTACHMENTS)
- part = ((EAttachment *) ((EMPopupTargetAttachments *) target)->attachments->data)->body;
- else
- part = ((EMPopupTargetPart *) target)->part;
+ part = ((EMPopupTargetPart *) target)->part;
if (!part)
return;
@@ -762,25 +684,6 @@ emp_standard_menu_factory(EPopup *emp, void *data)
items = emp_standard_object_popups;
len = LEN(emp_standard_object_popups);
break; }
- case EM_POPUP_TARGET_ATTACHMENTS: {
- EMPopupTargetAttachments *t = (EMPopupTargetAttachments *)emp->target;
- GSList *list = t->attachments;
- EAttachment *attachment;
-
- if (g_slist_length(list) != 1 || !((EAttachment *)list->data)->is_available_local) {
- items = NULL;
- len = 0;
- break;
- }
-
- /* Only one attachment selected */
- attachment = list->data;
- mime_type = camel_data_wrapper_get_mime_type((CamelDataWrapper *)attachment->body);
- filename = camel_mime_part_get_filename(attachment->body);
-
- items = emp_attachment_object_popups;
- len = LEN(emp_attachment_object_popups);
- break; }
default:
items = NULL;
len = 0;
@@ -942,21 +845,11 @@ static const EPopupHookTargetMask emph_folder_masks[] = {
{ NULL }
};
-static const EPopupHookTargetMask emph_attachments_masks[] = {
- { "one", EM_POPUP_ATTACHMENTS_ONE },
- { "many", EM_POPUP_ATTACHMENTS_MANY },
- { "multiple", EM_POPUP_ATTACHMENTS_MULTIPLE },
- { "image", EM_POPUP_ATTACHMENTS_IMAGE },
- { "message", EM_POPUP_ATTACHMENTS_MESSAGE },
- { NULL }
-};
-
static const EPopupHookTargetMap emph_targets[] = {
{ "select", EM_POPUP_TARGET_SELECT, emph_select_masks },
{ "uri", EM_POPUP_TARGET_URI, emph_uri_masks },
{ "part", EM_POPUP_TARGET_PART, emph_part_masks },
{ "folder", EM_POPUP_TARGET_FOLDER, emph_folder_masks },
- { "attachments", EM_POPUP_TARGET_ATTACHMENTS, emph_attachments_masks },
{ NULL }
};
diff --git a/mail/em-popup.h b/mail/em-popup.h
index fbe41a3..77f80e5 100644
--- a/mail/em-popup.h
+++ b/mail/em-popup.h
@@ -43,7 +43,6 @@ typedef struct _EMPopupClass EMPopupClass;
* @EM_POPUP_TARGET_URI: A URI.
* @EM_POPUP_TARGET_PART: A CamelMimePart message part.
* @EM_POPUP_TARGET_FOLDER: A folder URI.
- * @EM_POPUP_TARGET_ATTACHMENTS: A list of attachments.
*
* Defines the value of the targetid for all EMPopup target types.
**/
@@ -51,8 +50,7 @@ enum _em_popup_target_t {
EM_POPUP_TARGET_SELECT,
EM_POPUP_TARGET_URI,
EM_POPUP_TARGET_PART,
- EM_POPUP_TARGET_FOLDER,
- EM_POPUP_TARGET_ATTACHMENTS,
+ EM_POPUP_TARGET_FOLDER
};
/**
@@ -158,26 +156,10 @@ enum _em_popup_target_folder_t {
EM_POPUP_FOLDER_NONSTATIC = 1<<6, /* Except static folders like Outbox.*/
};
-/**
- * enum _em_popup_target_attachments_t - EMPopupTargetAttachments qualifiers.
- *
- * @EM_POPUP_ATTACHMENTS_ONE: There is one and only one attachment selected.
- * @EM_POPUP_ATTACHMENTS_MANY: There is one or more attachments selected.
- *
- **/
-enum _em_popup_target_attachments_t {
- EM_POPUP_ATTACHMENTS_ONE = 1<<0, /* only 1 selected */
- EM_POPUP_ATTACHMENTS_MANY = 1<<1, /* one or more selected */
- EM_POPUP_ATTACHMENTS_MULTIPLE = 1<<2, /* More than 1 selected */
- EM_POPUP_ATTACHMENTS_IMAGE = 1<<3, /* Image selected */
- EM_POPUP_ATTACHMENTS_MESSAGE = 1<<4 /* Message selected */
-};
-
typedef struct _EMPopupTargetSelect EMPopupTargetSelect;
typedef struct _EMPopupTargetURI EMPopupTargetURI;
typedef struct _EMPopupTargetPart EMPopupTargetPart;
typedef struct _EMPopupTargetFolder EMPopupTargetFolder;
-typedef struct _EMPopupTargetAttachments EMPopupTargetAttachments;
/**
* struct _EMPopupTargetURI - An inline URI.
@@ -241,20 +223,6 @@ struct _EMPopupTargetFolder {
char *uri;
};
-/**
- * struct _EMPopupTargetAttachments - A list of composer attachments.
- *
- * @target: Superclass.
- * @attachments: A GSList list of EMsgComposer attachments.
- *
- * This target is used to represent a selected list of attachments in
- * the message composer attachment area.
- **/
-struct _EMPopupTargetAttachments {
- EPopupTarget target;
- GSList *attachments;
-};
-
typedef struct _EPopupItem EMPopupItem;
/* The object */
@@ -276,7 +244,6 @@ EMPopupTargetURI *em_popup_target_new_uri(EMPopup *emp, const char *uri);
EMPopupTargetSelect *em_popup_target_new_select(EMPopup *emp, struct _CamelFolder *folder, const char *folder_uri, GPtrArray *uids);
EMPopupTargetPart *em_popup_target_new_part(EMPopup *emp, struct _CamelMimePart *part, const char *mime_type);
EMPopupTargetFolder *em_popup_target_new_folder(EMPopup *emp, const char *uri, guint32 info_flags, guint32 popup_flags);
-EMPopupTargetAttachments *em_popup_target_new_attachments(EMPopup *emp, GSList *attachments);
/* ********************************************************************** */
diff --git a/mail/mail-component.c b/mail/mail-component.c
index 3b67c43..556715d 100644
--- a/mail/mail-component.c
+++ b/mail/mail-component.c
@@ -92,6 +92,8 @@
#include "e-util/e-non-intrusive-error-dialog.h"
+#include "e-attachment-handler-mail.h"
+
#define MAILER_ERROR_LEVEL_KEY "/apps/evolution/mail/display/error_level"
#define MAILER_ERROR_TIME_OUT_KEY "/apps/evolution/mail/display/error_timeout"
@@ -1259,6 +1261,9 @@ mail_component_class_init (MailComponentClass *class)
epv->setLineStatus = impl_setLineStatus;
mepv->test = impl_mail_test;
+
+ /* Register attachment handler types. */
+ e_attachment_handler_mail_get_type ();
}
static void
diff --git a/plugins/attachment-reminder/attachment-reminder.c b/plugins/attachment-reminder/attachment-reminder.c
index 15bac58..8634ce4 100644
--- a/plugins/attachment-reminder/attachment-reminder.c
+++ b/plugins/attachment-reminder/attachment-reminder.c
@@ -24,6 +24,7 @@
#include <glib/gi18n.h>
#include <string.h>
+#include <glade/glade-xml.h>
#include <gconf/gconf-client.h>
#include <e-util/e-config.h>
@@ -43,9 +44,10 @@
#include <mail/em-utils.h>
-#include "widgets/misc/e-attachment-bar.h"
#include "composer/e-msg-composer.h"
#include "composer/e-composer-actions.h"
+#include "widgets/misc/e-attachment-view.h"
+#include "widgets/misc/e-attachment-store.h"
#define GCONF_KEY_ATTACH_REMINDER_CLUES "/apps/evolution/mail/attachment_reminder_clues"
#define SIGNATURE "-- "
@@ -182,12 +184,13 @@ check_for_attachment_clues (gchar *msg)
static gboolean
check_for_attachment (EMsgComposer *composer)
{
- EAttachmentBar* bar = (EAttachmentBar*)e_msg_composer_get_attachment_bar (composer);
+ EAttachmentView *view;
+ EAttachmentStore *store;
- if (e_attachment_bar_get_num_attachments (bar))
- return TRUE;
+ view = e_msg_composer_get_attachment_view (composer);
+ store = e_attachment_view_get_store (view);
- return FALSE;
+ return (e_attachment_store_get_num_attachments (store) > 0);
}
static gchar*
diff --git a/plugins/import-ics-attachments/ChangeLog b/plugins/import-ics-attachments/ChangeLog
deleted file mode 100644
index 21a9408..0000000
--- a/plugins/import-ics-attachments/ChangeLog
+++ /dev/null
@@ -1,109 +0,0 @@
-2009-01-21 Milan Crha <mcrha redhat com>
-
- * Makefile.am: Use also EVOLUTION_CALENDAR_CFLAGS.
-
-2008-09-02 Sankar P <psankar novell com>
-
-License Changes
-
- * icsimporter.c:
-
-2008-08-12 Bharath Acharya <abharath novell com>
-
- * Makefile.am: Added necessary libraries to link to. Build break while
- compiling on Windows.
-
-2008-08-11 Matthew Barnes <mbarnes redhat com>
-
- ** Fixes part of bug #546892
-
- * icsimporter.c:
- Prefer gtk_image_new_from_icon_name() over e_icon_factory_get_image().
-
-2008-04-17 Milan Crha <mcrha redhat com>
-
- ** Part of fix for bug #526739
-
- * icsimporter.c: Do not include gnome-vfs.
-
-2007-02-20 Paul Bolle <pebolle tiscali nl>
-
- ** Fix for bug #517082
-
- * icsimporter.c: (init_widgets): Fix small leak.
-
-2008-02-06 Milan Crha <mcrha redhat com>
-
- ** Fix for bug #514622
-
- * icsimporter.c: (dialog_close_cb): Drop this function.
- * icsimporter.c: (init_widgets), (dialog_response_cb),
- (ical_import_done): Do not call "close" on already closed dialog.
-
-2007-10-01 Milan Crha <mcrha redhat com>
-
- * icsimporter.c: (prepare_events), (prepare_tasks):
- Really go through every component when removing one.
-
-2007-06-03 Srinivasa Ragavan <sragavan novell com>
-
- ** Fix for version removal from Installed files from Gilles Dartiguelongue
-
- * Makefile.am:
-
-2007-05-12 Matthew Barnes <mbarnes redhat com>
-
- ** Fixes part of bug #337616
-
- * Makefile.am: Add "eplug" file to CLEANFILES.
-
-2007-03-27 Matthew Barnes <mbarnes redhat com>
-
- * icsimporter.c: Don't mix declarations and code (#405495).
-
-2007-03-20 Matthew Barnes <mbarnes redhat com>
-
- ** Fixes part of bug #419524
-
- * Include <glib/gi18n.h> instead of <libgnome/gnome-i18n.h>.
-
-2006-11-28 Parthasarathi Susarla <ajaysusarla gmail com>
-
- ** Fix bug #348679
-
- * icsimporter.c: (org_gnome_evolution_import_ics_attachment):
- Do not access structure elements directly. Use the methods of the
- class in the CamelDataWrapper Class
-
-2006-08-28 Kjartan Maraas <kmaraas gnome org>
-
- * org-gnome-evolution-mail-attachments-import-ics.eplug.xml: Mark
- name and description for translation.
-
-2006-08-23 Srinivasa Ragavan <sragavan novell com>
-
- ** Fix for bug #347248
-
- * icsimporter.c: (get_menu_type), (import_ics): Update the
- em_utils_temp_save_part to use readwrite mode.
-
-2006-02-21 Chenthill Palanisamy <pchenthill novell com>
-
- reviewed by Veerapuram Varadhan <vvaradhan novell com>
-
- Fixes a crash
- * icsimporter.c: (org_gnome_evolution_import_ics_attachments):
- If the number of attachments selected is not equal to one, just return;
-
-
-2006-01-22 Harish Krishnaswamy <kharish novell com>
-
- * icsimporter.c (get_menu_type), (dialog_response_cb),
- (dialog_close_cb), (get_icalcomponent_from_file):
- Fix twenty odd compiler warnings and style oddness.
-
-2006-01-17 Harish Krishnaswamy <kharish novell com>
-
- * import-ics-attachments : Initial commits. Plugin written and submitted by
- Johnny Jacob <johnnyjacob gmail com>
-
diff --git a/plugins/import-ics-attachments/Makefile.am b/plugins/import-ics-attachments/Makefile.am
deleted file mode 100644
index baded42..0000000
--- a/plugins/import-ics-attachments/Makefile.am
+++ /dev/null
@@ -1,35 +0,0 @@
-INCLUDES = \
- -I$(top_srcdir)\
- -I$(top_srcdir)/camel \
- -I$(top_srcdir)/widgets/misc \
- $(EVOLUTION_MAIL_CFLAGS) \
- $(EVOLUTION_CALENDAR_CFLAGS) \
- -DEVOLUTION_DATADIR=\""$(datadir)"\" \
- -DEVOLUTION_PRIVDATADIR=\""$(privdatadir)"\" \
- -DEVOLUTION_ICONSDIR=\""$(imagesdir)"\" \
- -DEVOLUTION_IMAGES=\""$(imagesdir)"\" \
- -DEVOLUTION_BUTTONSDIR=\""$(buttonsdir)"\" \
- -DEVOLUTION_LOCALEDIR=\""$(localedir)"\" \
- -DEVOLUTION_UIDIR=\""$(evolutionuidir)"\" \
- -DCAMEL_PROVIDERDIR=\""$(camel_providerdir)"\" \
- -DPLUGINDIR=\""$(plugindir)"\" \
- -DPREFIX=\""$(prefix)"\"
-
- EVO_PLUGIN_RULE@
-
-plugin_DATA = org-gnome-evolution-mail-attachments-import-ics.eplug
-plugin_LTLIBRARIES = liborg-gnome-evolution-mail-attachments-import-ics.la
-
-liborg_gnome_evolution_mail_attachments_import_ics_la_SOURCES = icsimporter.c
-liborg_gnome_evolution_mail_attachments_import_ics_la_LDFLAGS = -module -avoid-version $(NO_UNDEFINED)
-liborg_gnome_evolution_mail_attachments_import_ics_la_LIBADD = \
- $(top_builddir)/e-util/libeutil.la \
- $(top_builddir)/mail/libevolution-mail.la \
- $(top_builddir)/calendar/common/libevolution-calendarprivate.la \
- $(EVOLUTION_CALENDAR_LIBS) \
- $(EVOLUTION_MAIL_LIBS)
-
-EXTRA_DIST = org-gnome-evolution-mail-attachments-import-ics.eplug.xml
-
-BUILT_SOURCES = $(plugin_DATA)
-CLEANFILES = $(BUILT_SOURCES)
diff --git a/plugins/import-ics-attachments/icsimporter.c b/plugins/import-ics-attachments/icsimporter.c
deleted file mode 100644
index fbd5e46..0000000
--- a/plugins/import-ics-attachments/icsimporter.c
+++ /dev/null
@@ -1,435 +0,0 @@
-/*
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) version 3.
- *
- * 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
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with the program; if not, see <http://www.gnu.org/licenses/>
- *
- *
- * Authors:
- * Johnny Jacob <johnnyjacob gmail com>
- *
- * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
- *
- */
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-#include <string.h>
-#include <glib.h>
-#include <gtk/gtk.h>
-#include <glib/gi18n.h>
-#include <e-util/e-config.h>
-#include <e-util/e-popup.h>
-#include <mail/em-popup.h>
-#include <mail/em-menu.h>
-#include <mail/mail-ops.h>
-#include <mail/mail-mt.h>
-#include <mail/em-folder-view.h>
-#include <mail/em-format-html-display.h>
-#include <mail/em-utils.h>
-#include "e-attachment-bar.h"
-#include <camel/camel-vee-folder.h>
-#include "e-util/e-error.h"
-#include <libedataserverui/e-source-selector.h>
-#include <libecal/e-cal.h>
-#include <libical/icalvcal.h>
-#include <calendar/common/authentication.h>
-
-typedef struct {
- ECal *client;
- int source_type;
- icalcomponent *icalcomp;
- GtkWidget *window;
- GtkWidget *selector;
-} ICalImporterData;
-
-
-static void import_ics (EPlugin *ep, EPopupTarget *t, void *data);
-static icalcomponent* get_icalcomponent_from_file(char *filename);
-static void prepare_events (icalcomponent *icalcomp, GList **vtodos);
-static void prepare_tasks (icalcomponent *icalcomp, GList *vtodos);
-static void import_items(ICalImporterData *icidata);
-static gboolean update_objects (ECal *client, icalcomponent *icalcomp);
-static void dialog_response_cb (GtkDialog *dialog, gint response_id, ICalImporterData *icidata);
-static void ical_import_done(ICalImporterData *icidata);
-static void init_widgets (char *path);
-static icalcomponent_kind get_menu_type (void *data);
-
-void org_gnome_evolution_import_ics_attachments (EPlugin *ep, EMPopupTargetAttachments *t);
-void org_gnome_evolution_import_ics_part (EPlugin *ep, EMPopupTargetPart *t);
-
-static void
-popup_free (EPopup *ep, GSList *items, void *data)
-{
- g_slist_free (items);
-}
-
-static EPopupItem popup_calendar_items[] = {
- { E_POPUP_BAR, "25.display.00"},
- { E_POPUP_ITEM, "25.display.01", N_("_Import to Calendar"), (EPopupActivateFunc)import_ics, NULL, "stock_mail-import"}
-};
-
-static EPopupItem popup_tasks_items[] = {
- { E_POPUP_BAR, "25.display.00"},
- { E_POPUP_ITEM, "25.display.01", N_("_Import to Tasks"), (EPopupActivateFunc)import_ics, NULL, "stock_mail-import"}
-};
-
-
-void org_gnome_evolution_import_ics_attachments (EPlugin *ep, EMPopupTargetAttachments *t)
-{
- GSList *menus = NULL;
- icalcomponent_kind kind;
- int len = 0;
- int i = 0;
- CamelContentType *type;
-
- len = g_slist_length(t->attachments);
-
- if (len != 1)
- return;
-
- type = camel_data_wrapper_get_mime_type_field (((CamelDataWrapper *) ((EAttachment *) t->attachments->data)->body));
- if (type && camel_content_type_is(type, "text", "calendar")) {
-
- kind = get_menu_type (t);
-
- if (kind == ICAL_VTODO_COMPONENT ) {
- for (i = 0; i < sizeof (popup_tasks_items) / sizeof (popup_tasks_items[0]); i++)
- menus = g_slist_prepend (menus, &popup_tasks_items[i]);
- } else if ( kind == ICAL_VEVENT_COMPONENT) {
- for (i = 0; i < sizeof (popup_calendar_items) / sizeof (popup_calendar_items[0]); i++)
- menus = g_slist_prepend (menus, &popup_calendar_items[i]);
- }
-
- e_popup_add_items (t->target.popup, menus, NULL, popup_free, t);
- }
-}
-
-void org_gnome_evolution_import_ics_part (EPlugin*ep, EMPopupTargetPart *t)
-{
- GSList *menus = NULL;
- icalcomponent_kind kind;
- int i = 0;
-
- if (!camel_content_type_is(((CamelDataWrapper *) t->part)->mime_type, "text", "calendar"))
- return;
-
- kind = get_menu_type (t);
-
- if (kind == ICAL_VTODO_COMPONENT ) {
- for (i = 0; i < sizeof (popup_tasks_items) / sizeof (popup_tasks_items[0]); i++)
- menus = g_slist_prepend (menus, &popup_tasks_items[i]);
- } else if ( kind == ICAL_VEVENT_COMPONENT) {
- for (i = 0; i < sizeof (popup_calendar_items) / sizeof (popup_calendar_items[0]); i++)
- menus = g_slist_prepend (menus, &popup_calendar_items[i]);
- }
-
- e_popup_add_items (t->target.popup, menus, NULL, popup_free, t);
-}
-
-static icalcomponent_kind
-get_menu_type (void *data)
-{
- CamelMimePart *part;
- char *path;
- icalcomponent *icalcomp, *subcomp;
- icalcomponent_kind kind;
- EPopupTarget *target = (EPopupTarget *) data;
-
- if (target->type == EM_POPUP_TARGET_ATTACHMENTS)
- part = ((EAttachment *) ((EMPopupTargetAttachments *) target)->attachments->data)->body;
- else
- part = ((EMPopupTargetPart *) target)->part;
-
- path = em_utils_temp_save_part (NULL, part, FALSE);
-
- icalcomp = get_icalcomponent_from_file (path);
-
- subcomp = icalcomponent_get_inner(icalcomp);
- kind = icalcomponent_isa (subcomp);
-
- if (kind == ICAL_VTODO_COMPONENT ) {
- return ICAL_VTODO_COMPONENT;
- } else if ( kind == ICAL_VEVENT_COMPONENT) {
- return ICAL_VEVENT_COMPONENT;
- }
- return ICAL_NO_COMPONENT;
-}
-
-static void
-import_ics (EPlugin *ep, EPopupTarget *t, void *data)
-{
- CamelMimePart *part;
- char *path;
- EPopupTarget *target = (EPopupTarget *) data;
-
- if (target->type == EM_POPUP_TARGET_ATTACHMENTS)
- part = ((EAttachment *) ((EMPopupTargetAttachments *) target)->attachments->data)->body;
- else
- part = ((EMPopupTargetPart *) target)->part;
-
- path = em_utils_temp_save_part (NULL, part, FALSE);
- init_widgets(path);
-}
-
-static void
-init_widgets(char *path)
-{
-
- GtkWidget *vbox, *hbox, *dialog;
- icalcomponent_kind kind;
- icalcomponent *subcomp;
- GtkWidget *selector, *label;
- ESourceList *source_list;
- ESource *primary;
- GtkWidget *scrolled;
- ICalImporterData *icidata = g_malloc0(sizeof(*icidata));
- GtkWidget *icon, *button;
- char *label_str = NULL;
- char *markup;
-
- g_return_if_fail ( path != NULL);
- dialog = gtk_dialog_new_with_buttons (_("Import ICS"),
- NULL, GTK_DIALOG_DESTROY_WITH_PARENT,
- GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
- NULL);
- icidata->window = dialog;
- g_signal_connect (dialog,
- "response",
- G_CALLBACK (dialog_response_cb),
- icidata);
-
- vbox = GTK_DIALOG(dialog)->vbox;
- hbox = gtk_hbox_new (FALSE, FALSE);
- label = gtk_label_new(NULL);
-
- gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, TRUE, 6);
-
- icidata->icalcomp = get_icalcomponent_from_file (path);
-
- subcomp = icalcomponent_get_inner(icidata->icalcomp);
- kind = icalcomponent_isa (subcomp);
-
- if (kind == ICAL_VTODO_COMPONENT ) {
- e_cal_get_sources (&source_list, E_CAL_SOURCE_TYPE_TODO, NULL);
- label_str = _("Select Task List");
- icidata->source_type = E_CAL_SOURCE_TYPE_TODO;
- } else if ( kind == ICAL_VEVENT_COMPONENT) {
- e_cal_get_sources (&source_list, E_CAL_SOURCE_TYPE_EVENT, NULL);
- label_str = _("Select Calendar");
- icidata->source_type = E_CAL_SOURCE_TYPE_EVENT;
- }
-
- markup = g_markup_printf_escaped ("<b>%s</b>", label_str);
- gtk_label_set_markup (GTK_LABEL (label), markup);
- g_free (markup);
- hbox = gtk_hbox_new (FALSE, FALSE);
- gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 6);
- gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 6);
-
- selector = e_source_selector_new (source_list);
- e_source_selector_show_selection (E_SOURCE_SELECTOR (selector), FALSE);
- scrolled = gtk_scrolled_window_new(NULL, NULL);
- gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW (scrolled), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
- gtk_container_add((GtkContainer *)scrolled, selector);
- gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (scrolled), GTK_SHADOW_IN);
- hbox = gtk_hbox_new (FALSE, FALSE);
- gtk_box_pack_start (GTK_BOX (hbox), scrolled, TRUE, TRUE, 6);
- gtk_box_pack_start (GTK_BOX (vbox), hbox, TRUE, TRUE, 6);
- icidata->selector = selector;
-
-
- /* FIXME What if no sources? */
- primary = e_source_list_peek_source_any (source_list);
- e_source_selector_set_primary_selection (E_SOURCE_SELECTOR (selector), primary);
-
- g_object_unref (source_list);
- hbox = gtk_hbox_new (FALSE, FALSE);
- icon = gtk_image_new_from_icon_name (
- "stock_mail-import", GTK_ICON_SIZE_MENU);
- gtk_box_pack_start (GTK_BOX(hbox), icon, FALSE, FALSE, 6);
- label = gtk_label_new_with_mnemonic (_("_Import"));
- gtk_box_pack_start (GTK_BOX(hbox), label, FALSE, FALSE, 6);
- gtk_widget_show(label);
- button = gtk_button_new ();
- gtk_container_add (GTK_CONTAINER (button), hbox);
- gtk_dialog_add_action_widget (GTK_DIALOG (dialog), button, GTK_RESPONSE_OK);
- gtk_widget_grab_focus (button);
-
- gtk_window_set_default_size (GTK_WINDOW (dialog), 210,340);
- gtk_widget_show_all (dialog);
- gtk_dialog_run (GTK_DIALOG (dialog));
- gtk_widget_destroy (dialog);
-}
-
-static void
-dialog_response_cb (GtkDialog *dialog, gint response_id, ICalImporterData *icidata)
-{
- switch (response_id) {
- case GTK_RESPONSE_OK :
- import_items(icidata);
- break;
-
- case GTK_RESPONSE_CANCEL :
- case GTK_RESPONSE_DELETE_EVENT :
- break;
- }
-}
-
-/* This removes all components except VEVENTs and VTIMEZONEs from the toplevel */
-static void
-prepare_events (icalcomponent *icalcomp, GList **vtodos)
-{
- icalcomponent *subcomp;
- icalcompiter iter;
-
- if (vtodos)
- *vtodos = NULL;
-
- iter = icalcomponent_begin_component (icalcomp, ICAL_ANY_COMPONENT);
- while ((subcomp = icalcompiter_deref (&iter)) != NULL) {
- icalcomponent_kind child_kind = icalcomponent_isa (subcomp);
- if (child_kind != ICAL_VEVENT_COMPONENT
- && child_kind != ICAL_VTIMEZONE_COMPONENT) {
-
- icalcompiter_next (&iter);
-
- icalcomponent_remove_component (icalcomp, subcomp);
- if (child_kind == ICAL_VTODO_COMPONENT && vtodos)
- *vtodos = g_list_prepend (*vtodos, subcomp);
- else
- icalcomponent_free (subcomp);
- } else {
- icalcompiter_next (&iter);
- }
- }
-}
-
-/* This removes all components except VTODOs and VTIMEZONEs from the toplevel
- icalcomponent, and adds the given list of VTODO components. The list is
- freed afterwards. */
-static void
-prepare_tasks (icalcomponent *icalcomp, GList *vtodos)
-{
- icalcomponent *subcomp;
- GList *elem;
- icalcompiter iter;
-
- iter = icalcomponent_begin_component (icalcomp, ICAL_ANY_COMPONENT);
- while ((subcomp = icalcompiter_deref (&iter)) != NULL) {
- icalcomponent_kind child_kind = icalcomponent_isa (subcomp);
- if (child_kind != ICAL_VTODO_COMPONENT
- && child_kind != ICAL_VTIMEZONE_COMPONENT) {
- icalcompiter_next (&iter);
- icalcomponent_remove_component (icalcomp, subcomp);
- icalcomponent_free (subcomp);
- } else {
- icalcompiter_next (&iter);
- }
- }
-
- for (elem = vtodos; elem; elem = elem->next) {
- icalcomponent_add_component (icalcomp, elem->data);
- }
- g_list_free (vtodos);
-}
-
-static void
-import_items(ICalImporterData *icidata)
-{
- ESource *source;
- g_return_if_fail (icidata != NULL);
-
- source = e_source_selector_peek_primary_selection ((ESourceSelector *)icidata->selector);
- g_return_if_fail ( source != NULL);
-
- icidata->client = auth_new_cal_from_source (source, icidata->source_type);
- e_cal_open (icidata->client, FALSE, NULL);
-
- switch (icidata->source_type) {
- case E_CAL_SOURCE_TYPE_EVENT:
- prepare_events (icidata->icalcomp, NULL);
- if (!update_objects (icidata->client, icidata->icalcomp))
- /* FIXME: e_error ... */;
- break;
- case E_CAL_SOURCE_TYPE_TODO:
- prepare_tasks (icidata->icalcomp, NULL);
- if (!update_objects (icidata->client, icidata->icalcomp))
- /* FIXME: e_error ... */;
- break;
- default:
- g_assert_not_reached ();
- }
- ical_import_done (icidata);
-}
-
-static gboolean
-update_objects (ECal *client, icalcomponent *icalcomp)
-{
- icalcomponent_kind kind;
- icalcomponent *vcal;
- gboolean success = TRUE;
-
- kind = icalcomponent_isa (icalcomp);
-
- if (kind == ICAL_VTODO_COMPONENT || kind == ICAL_VEVENT_COMPONENT) {
- vcal = e_cal_util_new_top_level ();
- if (icalcomponent_get_method (icalcomp) == ICAL_METHOD_CANCEL)
- icalcomponent_set_method (vcal, ICAL_METHOD_CANCEL);
- else
- icalcomponent_set_method (vcal, ICAL_METHOD_PUBLISH);
- icalcomponent_add_component (vcal, icalcomponent_new_clone (icalcomp));
- } else if (kind == ICAL_VCALENDAR_COMPONENT) {
- vcal = icalcomponent_new_clone (icalcomp);
- if (!icalcomponent_get_first_property (vcal, ICAL_METHOD_PROPERTY))
- icalcomponent_set_method (vcal, ICAL_METHOD_PUBLISH);
- } else
- return FALSE;
-
- if (!e_cal_receive_objects (client, vcal, NULL))
- success = FALSE;
-
- icalcomponent_free (vcal);
-
- return success;
-}
-
-static void
-ical_import_done(ICalImporterData *icidata)
-{
- g_object_unref (icidata->client);
- icalcomponent_free (icidata->icalcomp);
- g_free (icidata);
-}
-
-static icalcomponent *
-get_icalcomponent_from_file(char *filename)
-{
- char *contents;
- icalcomponent *icalcomp;
-
- g_return_val_if_fail (filename != NULL, NULL);
-
- if (!g_file_get_contents (filename, &contents, NULL, NULL)) {
- g_free (filename);
- return NULL;
- }
- g_free (filename);
-
- icalcomp = e_cal_util_parse_ics_string (contents);
- g_free (contents);
-
- if (icalcomp) {
- return icalcomp;
- }
- return NULL;
-}
diff --git a/plugins/import-ics-attachments/org-gnome-evolution-mail-attachments-import-ics.eplug.xml b/plugins/import-ics-attachments/org-gnome-evolution-mail-attachments-import-ics.eplug.xml
deleted file mode 100644
index 745d0fb..0000000
--- a/plugins/import-ics-attachments/org-gnome-evolution-mail-attachments-import-ics.eplug.xml
+++ /dev/null
@@ -1,26 +0,0 @@
-<?xml version="1.0"?>
-<e-plugin-list>
- <!-- the path to the shared library -->
- <e-plugin
- id="org.gnome.evolution.mail.attachments.import.ics"
- type="shlib"
- location="@PLUGINDIR@/liborg-gnome-evolution-mail-attachments-import-ics SOEXT@"
- _name="Import to Calendar">
-
- <author name="Johnny Jacob" email="johnnyjacob gmail com"/>
- <_description>Imports ICS attachments to calendar.</_description>
-
- <hook class="org.gnome.evolution.mail.popup:1.0">
- <menu id="org.gnome.evolution.mail.formathtmldisplay.popup" target="part" factory="org_gnome_evolution_import_ics_part">
- </menu>
- </hook>
- <hook class="org.gnome.evolution.mail.popup:1.0">
- <menu id="org.gnome.evolution.mail.attachments.popup" target="attachments" factory="org_gnome_evolution_import_ics_attachments">
- </menu>
- </hook>
- <hook class="org.gnome.evolution.mail.popup:1.0">
- <menu target="attachments" id="org.gnome.evolution.mail.composer.attachmentbar.popup" factory="org_gnome_evolution_import_ics_attachments">
- </menu>
- </hook>
- </e-plugin>
-</e-plugin-list>
diff --git a/plugins/save-attachments/ChangeLog b/plugins/save-attachments/ChangeLog
deleted file mode 100644
index 9980fdf..0000000
--- a/plugins/save-attachments/ChangeLog
+++ /dev/null
@@ -1,102 +0,0 @@
-2009-01-28 Tor Lillqvist <tml novell com>
-
- * Makefile.am: Use -no-undefined and link with more libs on
- Windows.
-
-2008-09-19 Sankar P <psankar novell com>
-
-License Changes
-
- * save-attachments.c:
-
-2007-12-20 Matthew Barnes <mbarnes redhat com>
-
- ** Fixes part of bug #362638
-
- * save-attachments.c:
- Use the new MailMsg API for messages.
-
-2007-04-02 Sankar P <psankar novell com>
-
- * Committed on behalf of Gilles Dartiguelongue <dartigug esiee fr>
-
- * org-gnome-save-attachments.eplug.xml:
- Cleanup.
- Fixes part of #301149
-
-2007-03-29 Matthew Barnes <mbarnes redhat com>
-
- * save-attachments.c:
- Evolution requires GLib 2.10 now; remove dead backward-compatibility
- code for GLib < 2.8 (#418971).
-
-2007-01-27 Nickolay V. Shmyrev <nshmyrev yandex ru>
-
- * save-attachments.c: (save_got_message):
- mark strings as translatable. See bug #399381 for details.
-
-2006-07-07 Hiroyuki Ikezoe <poincare ikezoe net>
-
- ** Fixes bug #341369
- * save-attachments.c: fixing a memory leak.
-
-2006-02-28 Shi Pu <shi pu sun com>
-
- ** Fixes #323853
-
- * save-attachments.c: (save_response), (entry_changed),
- (save_got_message):
- replace GnomeFileEntry by GtkFileChooserButton.
-
-2005-12-17 Tor Lillqvist <tml novell com>
-
- * save-attachments.c (entry_changed): Use GLib API to manipulate
- pathname.
-
-2005-05-16 Not Zed <NotZed Ximian com>
-
- * save-attachments.c: moved e-error to e-util
-
-2005-05-13 Rodney Dawes <dobey novell com>
-
- * org-gnome-save-attachments.xml: Update for new menu layout
-
-2005-05-12 Not Zed <NotZed Ximian com>
-
- * Makefile.am: setup built_sources/cleanfiles.
-
-2005-05-06 Not Zed <NotZed Ximian com>
-
- * Makefile.am:
- * org-gnome-save-attachments.eplug.xml: s/.in/.xml/ & i18n.
-
-2005-02-24 Björn Torkelsson <torkel acc umu se>
-
- * org-gnome-save-attachments.eplug.in: Removed plugin from the
- name.
- Fixed description and added author
-
-2005-02-07 Not Zed <NotZed Ximian com>
-
- * save-attachments.c (save_part): fix the access() call test.
-
-2005-01-04 Philip Van Hoof <pvanhoof gnome org>
-
- * save-attachments.c: Use standard error messages
-
-2004-12-27 Philip Van Hoof <pvanhoof gnome org>
-
- * save-attachments.c: Warning when overwriting file
-
-2004-11-01 JP Rosevear <jpr novell com>
-
- * Makefile.am: dist xml menu file
-
-2004-11-01 JP Rosevear <jpr novell com>
-
- * Makefile.am: dist .eplug.in file
-
-2004-10-20 Not Zed <NotZed Ximian com>
-
- * Imported save-attachments example plugin.
-
diff --git a/plugins/save-attachments/Makefile.am b/plugins/save-attachments/Makefile.am
deleted file mode 100644
index 05c724a..0000000
--- a/plugins/save-attachments/Makefile.am
+++ /dev/null
@@ -1,31 +0,0 @@
-if OS_WIN32
-NO_UNDEFINED_REQUIRED_LIBS = \
- $(top_builddir)/mail/libevolution-mail.la \
- $(EVOLUTION_MAIL_LIBS) \
- $(GNOME_PLATFORM_LIBS) \
- $(top_builddir)/e-util/libeutil.la
-endif
-
-INCLUDES = \
- -I$(top_srcdir) \
- $(EVOLUTION_MAIL_CFLAGS)
-
- EVO_PLUGIN_RULE@
-
-plugin_DATA = org-gnome-save-attachments.eplug org-gnome-save-attachments.xml
-plugin_LTLIBRARIES = liborg-gnome-save-attachments.la
-
-liborg_gnome_save_attachments_la_SOURCES = save-attachments.c
-liborg_gnome_save_attachments_la_LDFLAGS = -module \
- -avoid-version $(NO_UNDEFINED)
-
-liborg_gnome_save_attachments_la_LIBADD = \
- $(NO_UNDEFINED_REQUIRED_LIBS)
-
-
-EXTRA_DIST = \
- org-gnome-save-attachments.eplug.xml \
- org-gnome-save-attachments.xml
-
-BUILT_SOURCES = org-gnome-save-attachments.eplug
-CLEANFILES = $(BUILT_SOURCES)
diff --git a/plugins/save-attachments/org-gnome-save-attachments.eplug.xml b/plugins/save-attachments/org-gnome-save-attachments.eplug.xml
deleted file mode 100644
index d51b341..0000000
--- a/plugins/save-attachments/org-gnome-save-attachments.eplug.xml
+++ /dev/null
@@ -1,26 +0,0 @@
-<?xml version="1.0"?>
-<e-plugin-list>
- <!-- the path to the shared library -->
- <e-plugin
- id="org.gnome.plugin.attachments.save"
- type="shlib"
- location="@PLUGINDIR@/liborg-gnome-save-attachments SOEXT@"
- _name="Save attachments">
-
- <author name="Not Zed" email="NotZed Ximian com"/>
- <_description>A plugin for saving all attachments or parts of a message at once.</_description>
-
- <hook class="org.gnome.evolution.mail.bonobomenu:1.0">
- <menu id="org.gnome.evolution.mail.browser" target="select">
- <!-- the path to the bonobo menu description -->
- <ui file="@PLUGINDIR@/org-gnome-save-attachments.xml"/>
- <item
- type="item"
- verb="EPSASaveAttachments"
- path="/commands/EPSASaveAttachments"
- enable="one"
- activate="org_gnome_save_attachments_save"/>
- </menu>
- </hook>
- </e-plugin>
-</e-plugin-list>
diff --git a/plugins/save-attachments/org-gnome-save-attachments.xml b/plugins/save-attachments/org-gnome-save-attachments.xml
deleted file mode 100644
index 75f4aef..0000000
--- a/plugins/save-attachments/org-gnome-save-attachments.xml
+++ /dev/null
@@ -1,20 +0,0 @@
-<Root>
- <commands>
- <cmd name="EPSASaveAttachments" _label="Save Attachments..."
- _tip="Save all attachments"
- pixtype="stock" pixname="Save"/>
- </commands>
-
- <menu>
-<!--
- <placeholder name="MessagePlaceholder">
- <submenu name="Message">
- <placeholder name="MailMessageActions">
- <separator f="" name="emaillist5"/>
- <menuitem name="EPSASaveAttachments" verb=""/>
- </placeholder>
- </submenu>
- </placeholder>
--->
- </menu>
-</Root>
diff --git a/plugins/save-attachments/save-attachments.c b/plugins/save-attachments/save-attachments.c
deleted file mode 100644
index c48711c..0000000
--- a/plugins/save-attachments/save-attachments.c
+++ /dev/null
@@ -1,392 +0,0 @@
-/*
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) version 3.
- *
- * 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
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with the program; if not, see <http://www.gnu.org/licenses/>
- *
- *
- * Authors:
- * Michael Zucchi <notzed ximian com>
- *
- * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
- *
- */
-
-/* This is prototype code only, this may, or may not, use undocumented
- * unstable or private internal function calls. */
-
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <unistd.h>
-#include <string.h>
-#include <stdio.h>
-
-#include <gtk/gtk.h>
-#include <glib/gi18n.h>
-#include <glib/gstdio.h>
-
-#include <camel/camel-folder.h>
-#include <camel/camel-exception.h>
-#include <camel/camel-mime-message.h>
-#include <camel/camel-multipart.h>
-#include <camel/camel-utf8.h>
-
-#include "e-util/e-error.h"
-
-#include "mail/em-menu.h"
-#include "mail/em-utils.h"
-
-/* these are sort of mail-internal */
-#include "mail/mail-mt.h"
-#include "mail/mail-ops.h"
-
-void org_gnome_save_attachments_save(EPlugin *ep, EMMenuTargetSelect *target);
-
-struct _save_data {
- CamelFolder *folder;
- char *uid;
- CamelMimeMessage *msg;
-
- char *path;
- char *base;
-
- GtkWidget *entry;
- GtkWidget *tree;
- GtkTreeStore *model;
-};
-
-static void
-free_data(struct _save_data *data)
-{
- if (data->msg)
- camel_object_unref(data->msg);
- g_free(data->base);
- g_free(data->path);
- g_free(data->uid);
- camel_object_unref(data->folder);
- if (data->model)
- g_object_unref(data->model);
- g_free(data);
-}
-
-static char *
-clean_name(const char *s)
-{
- GString *out = g_string_new("");
- int c;
- char *r;
-
- while ( (c = camel_utf8_getc((const unsigned char **)&s)) ) {
- if (!g_unichar_isprint(c) || ( c < 0x7f && strchr(" /'\"`&();|<>$%{}!", c )))
- c = '_';
- g_string_append_u(out, c);
- }
-
- r = g_strdup(out->str);
- g_string_free(out, TRUE);
-
- return r;
-}
-
-static void
-fill_model_rec(CamelMimeMessage *msg, CamelMimePart *part, GtkTreeStore *model, GtkTreeIter *parent, GString *name)
-{
- CamelDataWrapper *containee;
- int parts, i;
- char *type;
- GtkTreeIter iter;
- int len = name->len;
- CamelContentType *mime;
-
- containee = camel_medium_get_content_object((CamelMedium *)part);
- if (containee == NULL)
- return;
-
- mime = ((CamelDataWrapper *)containee)->mime_type;
- type = camel_content_type_simple(mime);
-
- if (CAMEL_IS_MULTIPART(containee)) {
- gtk_tree_store_append(model, &iter, parent);
- g_string_append_printf(name, ".multipart");
- gtk_tree_store_set(model, &iter, 0, FALSE, 1, type, 2, name->str, 3, name->str, 4, part, -1);
-
- parts = camel_multipart_get_number((CamelMultipart *)containee);
- for (i = 0; i < parts; i++) {
- CamelMimePart *mpart = camel_multipart_get_part((CamelMultipart *)containee, i);
-
- g_string_truncate(name, len);
- g_string_append_printf(name, ".%d", i);
- fill_model_rec(msg, mpart, model, &iter, name);
- }
- } else if (CAMEL_IS_MIME_MESSAGE(containee)) {
- gtk_tree_store_append(model, &iter, parent);
- g_string_append_printf(name, ".msg");
- gtk_tree_store_set(model, &iter, 0, FALSE, 1, type, 2, name->str, 3, name->str, 4, part, -1);
- fill_model_rec(msg, (CamelMimePart *)containee, model, &iter, name);
- } else {
- char *filename = NULL;
- const char *ext = NULL, *tmp;
- int save = FALSE;
-
- gtk_tree_store_append(model, &iter, parent);
- tmp = camel_mime_part_get_filename(part);
- if (tmp) {
- filename = clean_name(tmp);
- ext = strrchr(filename, '.');
- }
- tmp = camel_mime_part_get_disposition(part);
- if (tmp && !strcmp(tmp, "attachment"))
- save = TRUE;
-
- if (camel_content_type_is(mime, "text", "*")) {
- if (ext == NULL) {
- if ((ext = mime->subtype) == NULL || !strcmp(ext, "plain"))
- ext = "text";
- }
- } else if (camel_content_type_is(mime, "image", "*")) {
- if (ext == NULL) {
- if ((ext = mime->subtype) == NULL)
- ext = "image";
- }
- save = TRUE;
- }
-
- g_string_append_printf(name, ".%s", ext);
- gtk_tree_store_set(model, &iter, 0, save, 1, type, 2, filename?filename:name->str, 3, filename?NULL:name->str, 4, part, -1);
- g_free(filename);
- }
- g_free(type);
-
- g_string_truncate(name, len);
-}
-
-static void
-fill_model(CamelMimeMessage *msg, GtkTreeStore *model)
-{
- GString *name = g_string_new("");
- GtkTreeIter iter;
-
- gtk_tree_store_append(model, &iter, NULL);
- gtk_tree_store_set(model, &iter, 0, FALSE, 1, "message/rfc822", 2, ".msg", 3, ".msg", 4, msg, -1);
- fill_model_rec(msg, (CamelMimePart *)msg, model, &iter, name);
- g_string_free(name, TRUE);
-}
-
-static gboolean
-save_part(GtkTreeModel *model, GtkTreePath *path, GtkTreeIter *iter, void *d)
-{
- struct _save_data *data = d;
- char *filename, *ext, *save;
- CamelMimePart *part;
- gboolean doit;
-
- /* TODO: check for existing file */
-
- gtk_tree_model_get(model, iter, 0, &doit, -1);
- if (!doit)
- return FALSE;
-
- gtk_tree_model_get(model, iter, 2, &filename, 3, &ext, 4, &part, -1);
- if (ext == NULL)
- save = g_build_filename(data->path, filename, NULL);
- else
- save = g_strdup_printf("%s%s", data->base, ext);
-
- /* FIXME: if part == data->msg then we need to save this
- * differently, not using the envelope MimePart */
-
- /*
- * The underlying em_utils_save_part_to_file ain't using gnome-vfs. Therefor
- * the POSIX access-call should suffice for checking the file existence.
- */
-
- if (g_access(save, F_OK) == 0)
- doit = e_error_run(NULL, E_ERROR_ASK_FILE_EXISTS_OVERWRITE, save, NULL) == GTK_RESPONSE_OK;
-
- if (doit)
- em_utils_save_part_to_file(NULL, save, part);
-
- g_free(ext);
- g_free(filename);
-
- return FALSE;
-}
-
-static void
-save_response(GtkWidget *d, int id, struct _save_data *data)
-{
- if (id == GTK_RESPONSE_OK) {
- char *tmp;
-
- data->base = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (data->entry));
- data->path = g_strdup(data->base);
- tmp = strrchr(data->path, '/');
- if (tmp)
- *tmp = 0;
- gtk_tree_model_foreach((GtkTreeModel *)data->model, save_part, data);
- }
-
- gtk_widget_destroy(d);
- free_data(data);
-}
-
-static gboolean
-entry_changed_update(GtkTreeModel *model, GtkTreePath *path, GtkTreeIter *iter, void *d)
-{
- const char *name = d;
- char *filename, *ext;
-
- gtk_tree_model_get(model, iter, 3, &ext, -1);
- if (ext) {
- filename = g_strdup_printf("%s%s", name, ext);
- gtk_tree_store_set((GtkTreeStore *)model, iter, 2, filename, -1);
- g_free(filename);
- g_free(ext);
- }
-
- return FALSE;
-}
-
-static void
-entry_changed(GtkWidget *entry, struct _save_data *data)
-{
- char *path;
- char *basename = NULL;
- const char *file;
-
- path = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (data->entry));
- if (path == NULL
- || G_IS_DIR_SEPARATOR (path[strlen(path)-1])
- || (basename = g_path_get_basename(path)) == NULL
- || (basename[0] == '.' && basename[1] == '\0')
- || (g_file_test(path, G_FILE_TEST_IS_DIR)))
- file = "attachment";
- else
- file = basename;
-
- gtk_tree_model_foreach((GtkTreeModel *)data->model, entry_changed_update, (void *)file);
- g_free(path);
- g_free(basename);
-}
-
-static void
-toggle_changed(GtkWidget *entry, const char *spath, struct _save_data *data)
-{
- GtkTreePath *path;
- GtkTreeIter iter;
-
- path = gtk_tree_path_new_from_string(spath);
- if (gtk_tree_model_get_iter((GtkTreeModel *)data->model, &iter, path)) {
- gboolean on;
-
- gtk_tree_model_get((GtkTreeModel *)data->model, &iter, 0, &on, -1);
- gtk_tree_store_set(data->model, &iter, 0, !on, -1);
- }
-
- gtk_tree_path_free (path);
-}
-
-static void
-save_got_message(CamelFolder *folder, const char *uid, CamelMimeMessage *msg, void *d)
-{
- struct _save_data *data = d;
- GtkDialog *dialog;
- GtkWidget *w, *tree;
- GtkTreeStore *model;
- GtkCellRenderer *renderer;
-
- /* not found, the mailer will show an error box for this */
- if (msg == NULL) {
- free_data(data);
- return;
- }
-
- data->msg = msg;
- camel_object_ref(msg);
-
- dialog = (GtkDialog *)gtk_dialog_new_with_buttons(_("Save attachments"),
- NULL, /* target->parent? */
- 0,
- GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
- GTK_STOCK_SAVE, GTK_RESPONSE_OK,
- NULL);
- w = gtk_file_chooser_button_new (_("Select save base name"), GTK_FILE_CHOOSER_ACTION_OPEN);
- data->entry = w;
- g_object_set(w, "filechooser_action", GTK_FILE_CHOOSER_ACTION_SAVE, NULL);
- gtk_widget_show(w);
- gtk_box_pack_start((GtkBox *)dialog->vbox, w, FALSE, TRUE, 6);
-
- g_signal_connect(GTK_FILE_CHOOSER_BUTTON (w), "selection-changed", G_CALLBACK(entry_changed), data);
-
- model = gtk_tree_store_new(5, G_TYPE_BOOLEAN, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_POINTER);
- data->model = model;
- fill_model(msg, model);
-
- tree = gtk_tree_view_new_with_model((GtkTreeModel *)model);
- data->tree = tree;
- gtk_widget_show(tree);
- gtk_tree_view_expand_all((GtkTreeView *)tree);
-
- renderer = gtk_cell_renderer_text_new();
- gtk_tree_view_insert_column_with_attributes((GtkTreeView *)tree, -1,
- _("MIME Type"), renderer, "text", 1, NULL);
- gtk_tree_view_set_expander_column((GtkTreeView *)tree, gtk_tree_view_get_column((GtkTreeView *)tree, 0));
-
- renderer = gtk_cell_renderer_toggle_new();
- g_object_set(renderer, "activatable", TRUE, NULL);
- g_signal_connect(renderer, "toggled", G_CALLBACK(toggle_changed), data);
-
- gtk_tree_view_insert_column_with_attributes((GtkTreeView *)tree, -1,
- _("Save"), renderer, "active", 0, NULL);
- renderer = gtk_cell_renderer_text_new();
- gtk_tree_view_insert_column_with_attributes((GtkTreeView *)tree, -1,
- _("Name"), renderer, "text", 2, NULL);
-
- w = g_object_new(gtk_frame_get_type(),
- "shadow_type", GTK_SHADOW_NONE,
- "label_widget", g_object_new(gtk_label_get_type(),
- "label", "<span weight=\"bold\">Attachments</span>",
- "use_markup", TRUE,
- "xalign", 0.0, NULL),
- "child", g_object_new(gtk_alignment_get_type(),
- "left_padding", 12,
- "top_padding", 6,
- "child", g_object_new(gtk_scrolled_window_get_type(),
- "hscrollbar_policy", GTK_POLICY_AUTOMATIC,
- "vscrollbar_policy", GTK_POLICY_AUTOMATIC,
- "shadow_type", GTK_SHADOW_IN,
- "child", tree,
- NULL),
- NULL),
- NULL);
- gtk_widget_show_all(w);
-
- gtk_box_pack_start((GtkBox *)dialog->vbox, w, TRUE, TRUE, 0);
- g_signal_connect(dialog, "response", G_CALLBACK(save_response), data);
- gtk_window_set_default_size((GtkWindow *)dialog, 500, 500);
- gtk_widget_show((GtkWidget *)dialog);
-}
-
-void
-org_gnome_save_attachments_save(EPlugin *ep, EMMenuTargetSelect *target)
-{
- struct _save_data *data;
-
- if (target->uids->len != 1)
- return;
-
- data = g_malloc0(sizeof(*data));
- data->folder = target->folder;
- camel_object_ref(data->folder);
- data->uid = g_strdup(target->uids->pdata[0]);
-
- mail_get_message(data->folder, data->uid, save_got_message, data, mail_msg_unordered_push);
-}
diff --git a/shell/apps_evolution_shell.schemas.in b/shell/apps_evolution_shell.schemas.in
index 24172f2..c5c6276 100644
--- a/shell/apps_evolution_shell.schemas.in
+++ b/shell/apps_evolution_shell.schemas.in
@@ -41,7 +41,35 @@
</locale>
</schema>
- <!-- Offline Mode -->
+ <!-- Initial attachment view (icon or list) -->
+
+ <schema>
+ <key>/schemas/apps/evolution/shell/attachment_view</key>
+ <applyto>/apps/evolution/shell/attachment_view</applyto>
+ <owner>evolution</owner>
+ <type>int</type>
+ <default>0</default>
+ <locale name="C">
+ <short>Initial attachment view</short>
+ <long>Initial view for attachment bar widgets.
+ "0" is Icon View, "1" is List View.</long>
+ </locale>
+ </schema>
+
+ <!-- Initial GtkFileChooser Folder -->
+
+ <schema>
+ <key>/schemas/apps/evolution/shell/current_folder</key>
+ <applyto>/apps/evolution/shell/current-folder</applyto>
+ <owner>evolution</owner>
+ <type>string</type>
+ <locale name="C">
+ <short>Initial file chooser folder</short>
+ <long>Initial folder for GtkFileChooser dialogs.</long>
+ </locale>
+ </schema>
+
+ <!-- Offline Mode -->
<schema>
<key>/schemas/apps/evolution/shell/start_offline</key>
diff --git a/widgets/misc/Makefile.am b/widgets/misc/Makefile.am
index 95acd8b..3befe12 100644
--- a/widgets/misc/Makefile.am
+++ b/widgets/misc/Makefile.am
@@ -37,7 +37,15 @@ widgetsinclude_HEADERS = \
e-account-combo-box.h \
e-activity-handler.h \
e-attachment.h \
- e-attachment-bar.h \
+ e-attachment-button.h \
+ e-attachment-dialog.h \
+ e-attachment-handler.h \
+ e-attachment-handler-image.h \
+ e-attachment-icon-view.h \
+ e-attachment-paned.h \
+ e-attachment-store.h \
+ e-attachment-tree-view.h \
+ e-attachment-view.h \
e-spinner.c \
e-spinner.h \
e-calendar.h \
@@ -51,7 +59,6 @@ widgetsinclude_HEADERS = \
e-combo-button.h \
e-dateedit.h \
e-dropdown-button.h \
- e-expander.h \
e-icon-entry.h \
e-image-chooser.h \
e-info-label.h \
@@ -88,7 +95,15 @@ libemiscwidgets_la_SOURCES = \
e-activity-handler.c \
e-calendar.c \
e-attachment.c \
- e-attachment-bar.c \
+ e-attachment-button.c \
+ e-attachment-dialog.c \
+ e-attachment-handler.c \
+ e-attachment-handler-image.c \
+ e-attachment-icon-view.c \
+ e-attachment-paned.c \
+ e-attachment-store.c \
+ e-attachment-tree-view.c \
+ e-attachment-view.c \
e-calendar-item.c \
e-cell-date-edit.c \
e-cell-percent.c \
@@ -99,7 +114,6 @@ libemiscwidgets_la_SOURCES = \
e-combo-button.c \
e-dateedit.c \
e-dropdown-button.c \
- e-expander.c \
e-icon-entry.c \
e-image-chooser.c \
e-info-label.c \
diff --git a/widgets/misc/e-attachment-bar.c b/widgets/misc/e-attachment-bar.c
deleted file mode 100644
index 0210d21..0000000
--- a/widgets/misc/e-attachment-bar.c
+++ /dev/null
@@ -1,1504 +0,0 @@
-/*
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) version 3.
- *
- * 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
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with the program; if not, see <http://www.gnu.org/licenses/>
- *
- *
- * Authors:
- * Ettore Perazzoli <ettore ximian com>
- * Jeffrey Stedfast <fejj ximian com>
- * Srinivasa Ragavan <sragavan novell com>
- *
- * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
- *
- */
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include <string.h>
-#include <gtk/gtk.h>
-#include <gio/gio.h>
-#include <glade/glade.h>
-#include <gconf/gconf.h>
-#include <gconf/gconf-client.h>
-#include <gdk/gdkkeysyms.h>
-#include <glib/gi18n.h>
-#include <glib/gstdio.h>
-#include <libgnome/libgnome.h>
-
-#ifdef HAVE_LIBGNOMEUI_GNOME_THUMBNAIL_H
-#include <libgnomeui/gnome-thumbnail.h>
-#endif
-
-#include "e-attachment.h"
-#include "e-attachment-bar.h"
-
-#include <libedataserver/e-data-server-util.h>
-
-#include <camel/camel-data-wrapper.h>
-#include <camel/camel-iconv.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-util.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 */
-
- /* Recent documents. Use this widget directly when bonoboui is obsoleted */
- GtkWidget *recent;
-
- gboolean batch_unref;
- GPtrArray *attachments;
- char *path;
-};
-
-
-enum {
- CHANGED,
- LAST_SIGNAL
-};
-
-static guint signals[LAST_SIGNAL] = { 0 };
-
-
-static void update (EAttachmentBar *bar);
-
-/* Attachment handling functions. */
-
-static void
-attachment_destroy (EAttachmentBar *bar, EAttachment *attachment)
-{
- if (bar->priv->batch_unref)
- return;
-
- if (g_ptr_array_remove (bar->priv->attachments, attachment)) {
- update (bar);
- g_signal_emit (bar, signals[CHANGED], 0);
- }
-}
-
-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_ptr_array_add (bar->priv->attachments, attachment);
- g_object_weak_ref ((GObject *) attachment, (GWeakNotify) attachment_destroy, bar);
- g_signal_connect (attachment, "changed", G_CALLBACK (attachment_changed_cb), bar);
-
- 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);
-
- if ((attachment = e_attachment_new (file_name, disposition, &ex))) {
- 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);
- }
-}
-
-/* get_system_thumbnail:
- * If filled store_uri, then creating thumbnail for it, otherwise, if is_available_local,
- * and attachment is not an application, then save to temp and create a thumbnail for the body.
- * Otherwise returns NULL (or if something goes wrong/library not available).
- */
-static GdkPixbuf *
-get_system_thumbnail (EAttachment *attachment, CamelContentType *content_type)
-{
- GdkPixbuf *pixbuf = NULL;
-#ifdef HAVE_LIBGNOMEUI_GNOME_THUMBNAIL_H
- struct stat file_stat;
- char *file_uri = NULL;
- gboolean is_tmp = FALSE;
-
- if (!attachment || !attachment->is_available_local)
- return NULL;
-
- if (attachment->store_uri && g_str_has_prefix (attachment->store_uri, "file://"))
- file_uri = attachment->store_uri;
- else if (attachment->body) {
- /* save part to the temp directory */
- char *tmp_file;
-
- is_tmp = TRUE;
-
- tmp_file = e_mktemp ("tmp-XXXXXX");
- if (tmp_file) {
- CamelStream *stream;
- char *mfilename = NULL;
- const char * filename;
-
- filename = camel_mime_part_get_filename (attachment->body);
- if (filename == NULL)
- filename = "unknown";
- else {
- char *utf8_mfilename;
-
- utf8_mfilename = g_strdup (filename);
- e_filename_make_safe (utf8_mfilename);
- mfilename = g_filename_from_utf8 ((const char *) utf8_mfilename, -1, NULL, NULL, NULL);
- g_free (utf8_mfilename);
-
- filename = (const char *) mfilename;
- }
-
- file_uri = g_strjoin (NULL, "file://", tmp_file, "-", filename, NULL);
-
- stream = camel_stream_fs_new_with_name (file_uri + 7, O_WRONLY | O_CREAT | O_TRUNC, 0644);
- if (stream) {
- CamelDataWrapper *content;
-
- content = camel_medium_get_content_object (CAMEL_MEDIUM (attachment->body));
-
- if (camel_data_wrapper_decode_to_stream (content, stream) == -1
- || camel_stream_flush (stream) == -1) {
- g_free (file_uri);
- file_uri = NULL;
- }
-
- camel_object_unref (stream);
- } else {
- g_free (file_uri);
- file_uri = NULL;
- }
-
- g_free (mfilename);
- g_free (tmp_file);
- }
- }
-
- if (!file_uri || !g_str_has_prefix (file_uri, "file://")) {
- if (is_tmp)
- g_free (file_uri);
-
- return NULL;
- }
-
- if (stat (file_uri + 7, &file_stat) != -1 && S_ISREG (file_stat.st_mode)) {
- GnomeThumbnailFactory *th_factory;
- char *th_file;
-
- th_factory = gnome_thumbnail_factory_new (GNOME_THUMBNAIL_SIZE_NORMAL);
- th_file = gnome_thumbnail_factory_lookup (th_factory, file_uri, file_stat.st_mtime);
-
- if (th_file) {
- pixbuf = gdk_pixbuf_new_from_file (th_file, NULL);
- g_free (th_file);
- } else if (content_type) {
- char *mime = camel_content_type_simple (content_type);
-
- if (gnome_thumbnail_factory_can_thumbnail (th_factory, file_uri, mime, file_stat.st_mtime)) {
- pixbuf = gnome_thumbnail_factory_generate_thumbnail (th_factory, file_uri, mime);
-
- if (pixbuf && !is_tmp)
- gnome_thumbnail_factory_save_thumbnail (th_factory, pixbuf, file_uri, file_stat.st_mtime);
- }
-
- g_free (mime);
- }
-
- g_object_unref (th_factory);
- }
-
- if (is_tmp) {
- /* clear the temp */
- g_remove (file_uri + 7);
- g_free (file_uri);
- }
-#endif
-
- return pixbuf;
-}
-
-static GdkPixbuf *
-scale_pixbuf (GdkPixbuf *pixbuf)
-{
- int ratio, width, height;
-
- if (!pixbuf)
- return NULL;
-
- 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;
- if (height == 0)
- height = 1;
- }
- } else {
- if (height > 48) {
- ratio = height / 48;
- height = 48;
- width = width / ratio;
- if (width == 0)
- width = 1;
- }
- }
-
- return e_icon_factory_pixbuf_scale (pixbuf, width, height);
-}
-
-/* Icon list contents handling. */
-
-static void
-calculate_height_width(EAttachmentBar *bar, int *new_width, int *new_height)
-{
- int width, height, icon_width;
- PangoFontMetrics *metrics;
- PangoContext *context;
-
- context = gtk_widget_get_pango_context ((GtkWidget *) bar);
- metrics = pango_context_get_metrics (context, ((GtkWidget *) bar)->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;
-
- if (new_width)
- *new_width = MAX (icon_width, width);
-
- if (new_height)
- *new_height = ICON_WIDTH + ICON_SPACING + ICON_BORDER + ICON_TEXT_SPACING + height;
-
- return;
-}
-
-void
-e_attachment_bar_create_attachment_cache (EAttachment *attachment)
-{
-
- CamelContentType *content_type;
-
- if (!attachment->body)
- return;
-
- content_type = camel_mime_part_get_content_type (attachment->body);
-
- if (camel_content_type_is(content_type, "image", "*")) {
- CamelDataWrapper *wrapper;
- CamelStreamMem *mstream;
- GdkPixbufLoader *loader;
- gboolean error = TRUE;
- GdkPixbuf *pixbuf;
-
- 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) {
- pixbuf = gdk_pixbuf_loader_get_pixbuf (loader);
- attachment->pixbuf_cache = scale_pixbuf (pixbuf);
- pixbuf = attachment->pixbuf_cache;
- g_object_ref(pixbuf);
- } else {
- attachment->pixbuf_cache = NULL;
- g_warning ("GdkPixbufLoader Error");
- }
-
- /* Destroy everything */
- g_object_unref (loader);
- camel_object_unref (mstream);
- }
-}
-
-static void
-update (EAttachmentBar *bar)
-{
- struct _EAttachmentBarPrivate *priv;
- GnomeIconList *icon_list;
- int bar_width, bar_height;
- int i;
-
- 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 (i = 0; i < priv->attachments->len; i++) {
- EAttachment *attachment;
- CamelContentType *content_type;
- char *size_string, *label;
- GdkPixbuf *pixbuf = NULL;
- char *desc;
-
- attachment = priv->attachments->pdata[i];
-
- if (!attachment->is_available_local || !attachment->body) {
- if ((pixbuf = e_icon_factory_get_icon("mail-attachment", E_ICON_SIZE_DIALOG))) {
- 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 */
- if ((pixbuf = attachment->pixbuf_cache)) {
- 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) {
- pixbuf = gdk_pixbuf_loader_get_pixbuf (loader);
- attachment->pixbuf_cache = scale_pixbuf (pixbuf);
- 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);
- } else if (!bar->expand && (pixbuf = get_system_thumbnail (attachment, content_type))) {
- attachment->pixbuf_cache = scale_pixbuf (pixbuf);
- pixbuf = attachment->pixbuf_cache;
- g_object_ref (pixbuf);
- }
-
- desc = camel_mime_part_get_description (attachment->body);
-
- if (!desc || *desc == '\0') {
- if (attachment->file_name) {
- desc = g_filename_to_utf8 (attachment->file_name, -1, NULL, NULL, NULL);
- } else {
- desc = camel_mime_part_get_filename (attachment->body);
- if (desc)
- desc = g_strdup (desc);
- }
- } else {
- desc = g_strdup (desc);
- }
-
- if (!desc)
- desc = g_strdup (_("attachment"));
-
- if (attachment->size && (size_string = g_format_size_for_display (attachment->size))) {
- label = g_strdup_printf ("%s (%s)", desc, size_string);
- g_free (desc);
- g_free (size_string);
- } else {
- label = g_strdup (desc);
- g_free (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);
- pixbuf = e_icon_factory_get_icon("mail-attachment", E_ICON_SIZE_DIALOG);
- }
- g_free (mime_type);
-
- /* remember this picture and use it later again */
- if (pixbuf)
- attachment->pixbuf_cache = g_object_ref (pixbuf);
- }
-
- if (pixbuf) {
- GdkPixbuf *pixbuf_orig = pixbuf;
- pixbuf = gdk_pixbuf_add_alpha (pixbuf_orig, TRUE, 255, 255, 255);
-
- /* gdk_pixbuf_add_alpha returns a newly allocated pixbuf,
- free the original one.
- */
- g_object_unref (pixbuf_orig);
-
- /* In case of a attachment bar, in a signed/encrypted part, display the status as a emblem*/
- if (attachment->sign) {
- /* Show the signature status at the right-bottom.*/
- GdkPixbuf *sign = NULL;
- int x, y;
-
- if (attachment->sign == CAMEL_CIPHER_VALIDITY_SIGN_BAD)
- sign = e_icon_factory_get_icon ("stock_signature-bad", E_ICON_SIZE_MENU);
- else if (attachment->sign == CAMEL_CIPHER_VALIDITY_SIGN_GOOD)
- sign = e_icon_factory_get_icon ("stock_signature-ok", E_ICON_SIZE_MENU);
- else
- sign = e_icon_factory_get_icon ("stock_signature", E_ICON_SIZE_MENU);
-
- x = gdk_pixbuf_get_width (pixbuf) - 17;
- y = gdk_pixbuf_get_height (pixbuf) - 17;
-
- gdk_pixbuf_copy_area (sign, 0, 0, 16, 16, pixbuf, x, y);
- g_object_unref (sign);
- }
-
- if (attachment->encrypt) {
- /* Show the encryption status at the top left.*/
- GdkPixbuf *encrypt = e_icon_factory_get_icon ("stock_lock-ok", E_ICON_SIZE_MENU);
-
- gdk_pixbuf_copy_area (encrypt, 0, 0, 16, 16, pixbuf, 1, 1);
- g_object_unref (encrypt);
- }
-
- gnome_icon_list_append_pixbuf (icon_list, pixbuf, NULL, label);
- g_object_unref (pixbuf);
- }
-
- g_free (label);
- }
-
- gnome_icon_list_thaw (icon_list);
-
- /* Resize */
- if (bar->expand) {
- gtk_widget_get_size_request ((GtkWidget *) bar, &bar_width, &bar_height);
-
- if (bar->priv->attachments->len) {
- int per_col, rows, height, width;
-
- calculate_height_width(bar, &width, &height);
- per_col = bar_width / width;
- per_col = (per_col ? per_col : 1);
- rows = (bar->priv->attachments->len + per_col -1) / per_col;
- gtk_widget_set_size_request ((GtkWidget *) bar, bar_width, rows * height);
- }
- }
-}
-
-static void
-update_remote_file (EAttachment *attachment, EAttachmentBar *bar)
-{
- GnomeIconList *icon_list;
- GnomeIconTextItem *item;
- char *msg, *base;
-
- if (attachment->percentage == -1) {
- update (bar);
- return;
- }
-
- base = g_path_get_basename(attachment->file_name);
- msg = g_strdup_printf("%s (%d%%)", base, attachment->percentage);
- g_free(base);
-
- 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)
-{
- struct _EAttachmentBarPrivate *priv;
- EAttachment *attachment;
- int id, left, nrem = 0;
- GList *items;
- GPtrArray *temp_arr;
-
- g_return_if_fail (E_IS_ATTACHMENT_BAR (bar));
-
- priv = bar->priv;
-
- if (!(items = gnome_icon_list_get_selection ((GnomeIconList *) bar)))
- return;
-
- temp_arr = g_ptr_array_new ();
- while (items != NULL) {
- if ((id = GPOINTER_TO_INT (items->data) - nrem) < priv->attachments->len) {
- attachment = E_ATTACHMENT(g_ptr_array_index (priv->attachments, id));
- g_ptr_array_add (temp_arr, (gpointer)attachment);
- g_ptr_array_remove_index (priv->attachments, id);
- nrem++;
- }
-
- items = items->next;
- }
-
- g_ptr_array_foreach (temp_arr, (GFunc)g_object_unref, NULL);
- g_ptr_array_free (temp_arr, TRUE);
-
- update (bar);
-
- g_signal_emit (bar, signals[CHANGED], 0);
-
- id++;
-
- if ((left = gnome_icon_list_get_num_icons ((GnomeIconList *) bar)) > 0)
- gnome_icon_list_focus_icon ((GnomeIconList *) bar, left > id ? id : left - 1);
-}
-
-void
-e_attachment_bar_set_width(EAttachmentBar *bar, int bar_width)
-{
- int per_col, rows, height, width;
-
- calculate_height_width(bar, &width, &height);
- per_col = bar_width / width;
- per_col = (per_col ? per_col : 1);
- rows = (bar->priv->attachments->len + per_col - 1) / per_col;
- gtk_widget_set_size_request ((GtkWidget *)bar, bar_width, rows * height);
-}
-
-void
-e_attachment_bar_edit_selected (EAttachmentBar *bar)
-{
- struct _EAttachmentBarPrivate *priv;
- EAttachment *attachment;
- GList *items;
- int id;
-
- g_return_if_fail (E_IS_ATTACHMENT_BAR (bar));
-
- priv = bar->priv;
-
- items = gnome_icon_list_get_selection ((GnomeIconList *) bar);
- while (items != NULL) {
- if ((id = GPOINTER_TO_INT (items->data)) < priv->attachments->len) {
- attachment = priv->attachments->pdata[id];
- e_attachment_edit (attachment, GTK_WIDGET (bar));
- }
-
- items = items->next;
- }
-}
-
-GtkWidget **
-e_attachment_bar_get_selector(EAttachmentBar *bar)
-{
- g_return_val_if_fail (E_IS_ATTACHMENT_BAR (bar), NULL);
-
- return &bar->priv->attach;
-}
-
-/**
- * e_attachment_bar_get_selected:
- * @bar: an #EAttachmentBar object
- *
- * Returns a newly allocated #GSList of ref'd #EAttachment objects
- * representing the selected items in the #EAttachmentBar Icon List.
- **/
-GSList *
-e_attachment_bar_get_selected (EAttachmentBar *bar)
-{
- struct _EAttachmentBarPrivate *priv;
- GSList *attachments = NULL;
- EAttachment *attachment;
- GList *items;
- int id;
-
- g_return_val_if_fail (E_IS_ATTACHMENT_BAR (bar), NULL);
-
- priv = bar->priv;
-
- items = gnome_icon_list_get_selection ((GnomeIconList *) bar);
-
- while (items != NULL) {
- if ((id = GPOINTER_TO_INT (items->data)) < priv->attachments->len) {
- attachment = priv->attachments->pdata[id];
- attachments = g_slist_prepend (attachments, attachment);
- g_object_ref (attachment);
- }
-
- items = items->next;
- }
-
- attachments = g_slist_reverse (attachments);
-
- return attachments;
-}
-
-/* FIXME: Cleanup this, since there is a api to get selected attachments */
-/**
- * e_attachment_bar_get_attachment:
- * @bar: an #EAttachmentBar object
- * @id: Index of the desired attachment or -1 to request all selected attachments
- *
- * Returns a newly allocated #GSList of ref'd #EAttachment objects
- * representing the requested item(s) in the #EAttachmentBar Icon
- * List.
- **/
-GSList *
-e_attachment_bar_get_attachment (EAttachmentBar *bar, int id)
-{
- struct _EAttachmentBarPrivate *priv;
- EAttachment *attachment;
- GSList *attachments;
-
- g_return_val_if_fail (E_IS_ATTACHMENT_BAR (bar), NULL);
-
- priv = bar->priv;
-
- if (id == -1 || id > priv->attachments->len)
- return e_attachment_bar_get_selected (bar);
-
- attachment = priv->attachments->pdata[id];
- attachments = g_slist_prepend (NULL, attachment);
- g_object_ref (attachment);
-
- return attachments;
-}
-
-
-/**
- * e_attachment_bar_get_all_attachments:
- * @bar: an #EAttachmentBar object
- *
- * Returns a newly allocated #GSList of ref'd #EAttachment objects.
- **/
-GSList *
-e_attachment_bar_get_all_attachments (EAttachmentBar *bar)
-{
- struct _EAttachmentBarPrivate *priv;
- GSList *attachments = NULL;
- EAttachment *attachment;
- int i;
-
- g_return_val_if_fail (E_IS_ATTACHMENT_BAR (bar), NULL);
-
- priv = bar->priv;
-
- for (i = priv->attachments->len - 1; i >= 0; i--) {
- attachment = priv->attachments->pdata[i];
- if (attachment->is_available_local) {
- attachments = g_slist_prepend (attachments, attachment);
- g_object_ref (attachment);
- }
- }
-
- return attachments;
-}
-
-/* Just the GSList has to be freed by the caller */
-GSList *
-e_attachment_bar_get_parts (EAttachmentBar *bar)
-{
- struct _EAttachmentBarPrivate *priv;
- EAttachment *attachment;
- GSList *parts = NULL;
- int i;
-
- g_return_val_if_fail (E_IS_ATTACHMENT_BAR (bar), NULL);
-
- priv = bar->priv;
-
- for (i = 0; i < priv->attachments->len; i++) {
- attachment = priv->attachments->pdata[i];
- if (attachment->is_available_local)
- parts = g_slist_prepend (parts, attachment->body);
- }
-
- return parts;
-}
-
-/* GtkObject methods. */
-
-static void
-destroy (GtkObject *object)
-{
- EAttachmentBar *bar = (EAttachmentBar *) object;
- struct _EAttachmentBarPrivate *priv = bar->priv;
- EAttachment *attachment;
- int i;
-
- if ((priv = bar->priv)) {
- priv->batch_unref = TRUE;
- for (i = 0; i < priv->attachments->len; i++) {
- attachment = priv->attachments->pdata[i];
- g_object_weak_unref ((GObject *) attachment, (GWeakNotify) attachment_destroy, bar);
- g_object_unref (attachment);
- }
- g_ptr_array_free (priv->attachments, TRUE);
-
- if (priv->attach)
- gtk_widget_destroy (priv->attach);
-
- if (priv->recent)
- gtk_widget_destroy (priv->recent);
-
- if (priv->path)
- g_free (priv->path);
-
- g_free (priv);
- bar->priv = NULL;
- }
-
- if (GTK_OBJECT_CLASS (parent_class)->destroy != NULL)
- (* GTK_OBJECT_CLASS (parent_class)->destroy) (object);
-}
-
-static char *
-temp_save_part (CamelMimePart *part, gboolean readonly)
-{
- const char *filename;
- char *tmpdir, *path, *mfilename = NULL, *utf8_mfilename = NULL;
- CamelStream *stream;
- CamelDataWrapper *wrapper;
-
- if (!(tmpdir = e_mkdtemp ("evolution-tmp-XXXXXX")))
- return NULL;
-
- if (!(filename = camel_mime_part_get_filename (part))) {
- /* This is the default filename used for temporary file creation */
- filename = _("Unknown");
- } else {
- utf8_mfilename = g_strdup (filename);
- e_filename_make_safe (utf8_mfilename);
- mfilename = g_filename_from_utf8 ((const char *) utf8_mfilename, -1, NULL, NULL, NULL);
- g_free (utf8_mfilename);
- filename = (const char *) mfilename;
- }
-
- path = g_build_filename (tmpdir, filename, NULL);
- g_free (tmpdir);
- g_free (mfilename);
-
- wrapper = camel_medium_get_content_object (CAMEL_MEDIUM (part));
- if (readonly)
- stream = camel_stream_fs_new_with_name (path, O_RDWR|O_CREAT|O_TRUNC, 0444);
- else
- stream = camel_stream_fs_new_with_name (path, O_RDWR|O_CREAT|O_TRUNC, 0644);
-
- if (!stream) {
- /* TODO handle error conditions */
- g_message ("DEBUG: could not open the file to write\n");
- g_free (path);
- return NULL;
- }
-
- if (camel_data_wrapper_decode_to_stream (wrapper, (CamelStream *) stream) == -1) {
- g_free (path);
- camel_stream_close (stream);
- camel_object_unref (stream);
- g_message ("DEBUG: could not write to file\n");
- return NULL;
- }
-
- camel_stream_close(stream);
- camel_object_unref(stream);
-
- return path;
-}
-
-static void
-eab_drag_data_get(EAttachmentBar *bar, GdkDragContext *drag, GtkSelectionData *data, guint info, guint time)
-{
- struct _EAttachmentBarPrivate *priv = bar->priv;
- EAttachment *attachment;
- char *path, **uris;
- int len, n, i = 0;
- CamelURL *url;
- GList *items;
-
- if (info)
- return;
-
- items = gnome_icon_list_get_selection (GNOME_ICON_LIST (bar));
- len = g_list_length (items);
-
- uris = g_malloc0 (sizeof (char *) * (len + 1));
-
- for ( ; items != NULL; items = items->next) {
- if (!((n = GPOINTER_TO_INT (items->data)) < priv->attachments->len))
- continue;
-
- attachment = priv->attachments->pdata[n];
-
- if (!attachment->is_available_local)
- continue;
-
- if (attachment->store_uri) {
- uris[i++] = attachment->store_uri;
- continue;
- }
-
- /* If we are not able to save, ignore it */
- if (!(path = temp_save_part (attachment->body, FALSE)))
- continue;
-
- url = camel_url_new ("file://", NULL);
- camel_url_set_path (url, path);
- attachment->store_uri = camel_url_to_string (url, 0);
- camel_url_free (url);
- g_free (path);
-
- uris[i++] = attachment->store_uri;
- }
-
- uris[i] = NULL;
-
- gtk_selection_data_set_uris (data, uris);
-
- g_free (uris);
-
- return;
-}
-
-static gboolean
-eab_button_release_event(EAttachmentBar *bar, GdkEventButton *event, gpointer dummy)
-{
- GnomeIconList *icon_list = GNOME_ICON_LIST(bar);
- GList *selected;
- int length;
- GtkTargetEntry drag_types[] = {
- { "text/uri-list", 0, 0 },
- };
-
- if (event && event->button == 1) {
- selected = gnome_icon_list_get_selection(icon_list);
- length = g_list_length (selected);
- if (length)
- gtk_drag_source_set((GtkWidget *)bar, GDK_BUTTON1_MASK, drag_types, G_N_ELEMENTS(drag_types), GDK_ACTION_COPY);
- else
- gtk_drag_source_unset((GtkWidget *)bar);
- }
-
- return FALSE;
-}
-
-static gboolean
-eab_button_press_event(EAttachmentBar *bar, GdkEventButton *event, gpointer dummy)
-{
- GnomeIconList *icon_list = GNOME_ICON_LIST(bar);
- GList *selected = NULL, *tmp;
- int length, icon_number;
- gboolean take_selected = FALSE;
- GtkTargetEntry drag_types[] = {
- { "text/uri-list", 0, 0 },
- };
-
- selected = gnome_icon_list_get_selection(icon_list);
- length = g_list_length (selected);
-
- if (event) {
- icon_number = gnome_icon_list_get_icon_at(icon_list, event->x, event->y);
- if (icon_number < 0) {
- /* When nothing is selected, deselect all */
- gnome_icon_list_unselect_all (icon_list);
- length = 0;
- selected = NULL;
- }
-
- if (event->button == 1) {
- /* If something is selected, then allow drag or else help to select */
- if (length)
- gtk_drag_source_set((GtkWidget *)bar, GDK_BUTTON1_MASK, drag_types, G_N_ELEMENTS(drag_types), GDK_ACTION_COPY);
- else
- gtk_drag_source_unset((GtkWidget *)bar);
- return FALSE;
- }
-
- /* If not r-click dont progress any more.*/
- if (event->button != 3)
- return FALSE;
-
- /* When a r-click on something, if it is in the already selected list, consider a r-click of multiple things
- * or deselect all and select only this for r-click
- */
- if (icon_number >= 0) {
- for (tmp = selected; tmp; tmp = tmp->next) {
- if (GPOINTER_TO_INT(tmp->data) == icon_number)
- take_selected = TRUE;
- }
-
- if (!take_selected) {
- gnome_icon_list_unselect_all(icon_list);
- gnome_icon_list_select_icon(icon_list, icon_number);
- }
- }
- }
-
- return FALSE;
-}
-
-static gboolean
-eab_icon_clicked_cb (EAttachmentBar *bar, GdkEvent *event, gpointer *dummy)
-{
- EAttachment *attachment;
- gboolean ret = FALSE;
- CamelURL *url;
- char *path;
- GSList *p;
-
- if (E_IS_ATTACHMENT_BAR (bar) && event->type == GDK_2BUTTON_PRESS) {
- p = e_attachment_bar_get_selected (bar);
- /* check if has body already, remote files can take longer to fetch */
- if (p && p->next == NULL && ((EAttachment *)p->data)->body) {
- attachment = p->data;
-
- /* Check if the file is stored already */
- if (!attachment->store_uri) {
- path = temp_save_part (attachment->body, TRUE);
- url = camel_url_new ("file://", NULL);
- camel_url_set_path (url, path);
- attachment->store_uri = camel_url_to_string (url, 0);
- camel_url_free (url);
- g_free (path);
- }
-
- /* FIXME Pass a parent window. */
- e_show_uri (NULL, attachment->store_uri);
-
- ret = TRUE;
- }
-
- if (p) {
- g_slist_foreach (p, (GFunc) g_object_unref, NULL);
- g_slist_free (p);
- }
- }
-
- return ret;
-}
-
-/* Initialization. */
-
-static void
-class_init (EAttachmentBarClass *klass)
-{
- GtkObjectClass *object_class;
-
- object_class = GTK_OBJECT_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)
-{
- struct _EAttachmentBarPrivate *priv;
-
- priv = g_new (struct _EAttachmentBarPrivate, 1);
-
- priv->attach = NULL;
- priv->batch_unref = FALSE;
- priv->attachments = g_ptr_array_new ();
-
- priv->recent = gtk_recent_chooser_menu_new ();
- gtk_recent_chooser_menu_set_show_numbers (GTK_RECENT_CHOOSER_MENU (priv->recent), TRUE);
- gtk_recent_chooser_set_sort_type (GTK_RECENT_CHOOSER (priv->recent), GTK_RECENT_SORT_MRU);
- gtk_recent_chooser_set_show_not_found (GTK_RECENT_CHOOSER (priv->recent), FALSE);
- gtk_recent_chooser_set_show_private (GTK_RECENT_CHOOSER (priv->recent), FALSE);
- gtk_recent_chooser_set_show_icons (GTK_RECENT_CHOOSER (priv->recent), TRUE);
- gtk_recent_chooser_set_show_tips (GTK_RECENT_CHOOSER (priv->recent), TRUE);
-
- priv->path = NULL;
-
- bar->priv = priv;
- bar->expand = FALSE;
-}
-
-
-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 icon_width, window_height;
-
- new = g_object_new (e_attachment_bar_get_type (), NULL);
-
- icon_list = GNOME_ICON_LIST (new);
-
- calculate_height_width (new, &icon_width, &window_height);
-
- gnome_icon_list_construct (icon_list, icon_width, adj, 0);
-
- gtk_widget_set_size_request (GTK_WIDGET (new), icon_width * 4, window_height);
-
- GTK_WIDGET_SET_FLAGS (new, GTK_CAN_FOCUS);
-
- 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"));
-
- g_signal_connect (new, "button_release_event", G_CALLBACK(eab_button_release_event), NULL);
- g_signal_connect (new, "button_press_event", G_CALLBACK(eab_button_press_event), NULL);
- g_signal_connect (new, "drag-data-get", G_CALLBACK(eab_drag_data_get), NULL);
- g_signal_connect (icon_list, "event", G_CALLBACK (eab_icon_clicked_cb), NULL);
-
- 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 = camel_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;
-
- if (!attachment->body)
- return;
-
- 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)
-{
- struct _EAttachmentBarPrivate *priv;
- EAttachment *attachment;
- int i;
-
- g_return_if_fail (E_IS_ATTACHMENT_BAR (bar));
- g_return_if_fail (CAMEL_IS_MULTIPART (multipart));
-
- priv = bar->priv;
-
- for (i = 0; i < priv->attachments->len; i++) {
- attachment = priv->attachments->pdata[i];
- 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 (E_IS_ATTACHMENT_BAR (bar), 0);
-
- return bar->priv->attachments->len;
-}
-
-void
-e_attachment_bar_attach (EAttachmentBar *bar, const char *file_name, const 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);
-}
-
-void
-e_attachment_bar_add_attachment (EAttachmentBar *bar, EAttachment *attachment)
-{
- g_return_if_fail (E_IS_ATTACHMENT_BAR (bar));
-
- add_common (bar, attachment);
-}
-
-void
-e_attachment_bar_add_attachment_silent (EAttachmentBar *bar, EAttachment *attachment)
-{
- g_return_if_fail (E_IS_ATTACHMENT_BAR (bar));
- g_return_if_fail (attachment != NULL);
-
- g_ptr_array_add (bar->priv->attachments, attachment);
- g_object_weak_ref ((GObject *) attachment, (GWeakNotify) attachment_destroy, bar);
- g_signal_connect (attachment, "changed", G_CALLBACK (attachment_changed_cb), bar);
-
-
- g_signal_emit (bar, signals[CHANGED], 0);
-}
-
-void
-e_attachment_bar_refresh (EAttachmentBar *bar)
-{
- update (bar);
-
-}
-
-int
-e_attachment_bar_get_download_count (EAttachmentBar *bar)
-{
- struct _EAttachmentBarPrivate *priv;
- EAttachment *attachment;
- int i, n = 0;
-
- g_return_val_if_fail (E_IS_ATTACHMENT_BAR (bar), 0);
-
- priv = bar->priv;
-
- for (i = 0; i < priv->attachments->len; i++) {
- attachment = priv->attachments->pdata[i];
- if (!attachment->is_available_local)
- n++;
- }
-
- return n;
-}
-
-void
-e_attachment_bar_attach_remote_file (EAttachmentBar *bar, const char *url, const char *disposition)
-{
- EAttachment *attachment;
- CamelException ex;
- GtkWindow *parent;
-
- g_return_if_fail (E_IS_ATTACHMENT_BAR (bar));
-
- if (!bar->priv->path)
- bar->priv->path = e_mkdtemp ("attach-XXXXXX");
-
- parent = (GtkWindow *) gtk_widget_get_toplevel ((GtkWidget *) bar);
- camel_exception_init (&ex);
- if ((attachment = e_attachment_new_remote_file (parent, url, disposition, bar->priv->path, &ex))) {
- add_common (bar, attachment);
- g_signal_connect (attachment, "update", G_CALLBACK (update_remote_file), bar);
- } else {
- e_error_run (parent, "mail-composer:no-attach",
- url, camel_exception_get_description (&ex), NULL);
- camel_exception_clear (&ex);
- }
-}
-
-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);
-}
-
-/* FIXME: Remove this API if nobody uses it */
-void
-e_attachment_bar_bonobo_ui_populate_with_recent (BonoboUIComponent *uic, const char *path,
- EAttachmentBar *bar,
- BonoboUIVerbFn verb_cb, gpointer user_data)
-{
- struct _EAttachmentBarPrivate *priv;
- GList *items, *l;
- gint limit, i;
- GString *menuitems;
- char *encoded_label, *label;
-
- g_return_if_fail (E_IS_ATTACHMENT_BAR (bar));
-
- priv = bar->priv;
- limit = gtk_recent_chooser_get_limit (GTK_RECENT_CHOOSER (priv->recent));
- items = gtk_recent_chooser_get_items (GTK_RECENT_CHOOSER (priv->recent));
-
- menuitems = g_string_new ("<submenu");
- g_string_append (menuitems, " name=\"RecentDocsSubmenu\"");
- g_string_append_printf (menuitems, " sensitive=\"%s\"", items ? "1" : "0");
- g_string_append_printf (menuitems, " label=\"%s\"", _("Recent _Documents"));
- g_string_append (menuitems, ">\n");
-
- for (l = g_list_first (items), i = 1; l && i <= limit; l = l->next, ++i) {
- GtkRecentInfo *info = ((GtkRecentInfo *)(l->data));
- const gchar *info_dn = gtk_recent_info_get_display_name (info);
- char *display_name, *u;
-
- /* escape _'s in the display name so that it doesn't become an underline in a GtkLabel */
- if ((u = strchr (info_dn, '_'))) {
- int extra = 1;
- char *d;
- const char *s;
-
- while ((u = strchr (u + 1, '_')))
- extra++;
-
- d = display_name = g_alloca (strlen (info_dn) + extra + 1);
- s = info_dn;
- while (*s != '\0') {
- if (*s == '_')
- *d++ = '_';
- *d++ = *s++;
- }
- *d = '\0';
- } else
- display_name = (char *) info_dn;
-
- /* Add menu item */
- label = g_strdup (display_name);
- encoded_label = bonobo_ui_util_encode_str (label);
- g_string_append_printf (menuitems,
- " <menuitem name=\"Recent-%d\" verb=\"\" label=\"%s\"/>\n",
- i, encoded_label);
- g_free (encoded_label);
- g_free (label);
- }
-
- g_string_append (menuitems, "</submenu>\n");
-
- bonobo_ui_component_set (uic, path, menuitems->str, NULL);
-
- g_string_free (menuitems, TRUE);
-
- /* Add uri prop */
- for (l = g_list_first (items), i = 1; l && i <= limit; l = l->next, ++i) {
- GtkRecentInfo *info = ((GtkRecentInfo *)(l->data));
- const gchar *info_uri = gtk_recent_info_get_uri (info);
- label = g_strdup_printf ("/commands/Recent-%d", i);
- bonobo_ui_component_set_prop (uic, label, "uri", info_uri, NULL);
- g_free (label);
- }
-
- /* Add verb */
- for (l = g_list_first (items), i = 1; l && i <= limit; l = l->next, ++i) {
- label = g_strdup_printf ("Recent-%d", i);
- bonobo_ui_component_add_verb (uic, label, verb_cb, user_data);
- g_free (label);
- }
-
- for (l = g_list_first (items); l; l = l->next)
- gtk_recent_info_unref ((GtkRecentInfo *)(l->data));
- g_list_free (items);
-}
-
-static void
-action_recent_cb (GtkAction *action,
- EAttachmentBar *attachment_bar)
-{
- GtkRecentChooser *chooser;
- GFile *file;
- gchar *uri;
-
- chooser = GTK_RECENT_CHOOSER (action);
-
- /* Wish: gtk_recent_chooser_get_current_file() */
- uri = gtk_recent_chooser_get_current_uri (chooser);
- file = g_file_new_for_uri (uri);
- g_free (uri);
-
- if (g_file_is_native (file))
- e_attachment_bar_attach (
- E_ATTACHMENT_BAR (attachment_bar),
- g_file_get_path (file), "attachment");
- else
- e_attachment_bar_attach_remote_file (
- E_ATTACHMENT_BAR (attachment_bar),
- g_file_get_uri (file), "attachment");
-
- g_object_unref (file);
-}
-
-GtkAction *
-e_attachment_bar_recent_action_new (EAttachmentBar *bar,
- const gchar *action_name,
- const gchar *action_label)
-{
- GtkAction *action;
- GtkRecentChooser *chooser;
-
- g_return_val_if_fail (E_IS_ATTACHMENT_BAR (bar), NULL);
-
- action = gtk_recent_action_new (
- action_name, action_label, NULL, NULL);
- gtk_recent_action_set_show_numbers (GTK_RECENT_ACTION (action), TRUE);
-
- chooser = GTK_RECENT_CHOOSER (action);
- gtk_recent_chooser_set_show_icons (chooser, TRUE);
- gtk_recent_chooser_set_show_not_found (chooser, FALSE);
- gtk_recent_chooser_set_show_private (chooser, FALSE);
- gtk_recent_chooser_set_show_tips (chooser, TRUE);
- gtk_recent_chooser_set_sort_type (chooser, GTK_RECENT_SORT_MRU);
-
- g_signal_connect (
- action, "item-activated",
- G_CALLBACK (action_recent_cb), bar);
-
- return action;
-}
-
diff --git a/widgets/misc/e-attachment-bar.h b/widgets/misc/e-attachment-bar.h
deleted file mode 100644
index 7f8b479..0000000
--- a/widgets/misc/e-attachment-bar.h
+++ /dev/null
@@ -1,105 +0,0 @@
-/*
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) version 3.
- *
- * 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
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with the program; if not, see <http://www.gnu.org/licenses/>
- *
- *
- * Authors:
- * Ettore Perazzoli <ettore ximian com>
- * Srinivasa Ragavan <sragavan novell com>
- *
- * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
- *
- */
-
-#ifndef __E_ATTACHMENT_BAR_H__
-#define __E_ATTACHMENT_BAR_H__
-
-#include <libgnomeui/gnome-icon-list.h>
-
-#include <bonobo/bonobo-ui-node.h>
-#include <bonobo/bonobo-ui-util.h>
-
-#include <camel/camel-multipart.h>
-#include "e-attachment.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;
-
-struct _EAttachmentBar {
- GnomeIconList parent;
- gboolean expand;
-
- struct _EAttachmentBarPrivate *priv;
-};
-
-struct _EAttachmentBarClass {
- GnomeIconListClass parent_class;
-
- void (* changed) (EAttachmentBar *bar);
-};
-
-
-GType 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, const 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 char *url, const char *disposition);
-GSList *e_attachment_bar_get_attachment (EAttachmentBar *bar, int id);
-void e_attachment_bar_add_attachment (EAttachmentBar *bar, EAttachment *attachment);
-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_parts (EAttachmentBar *bar);
-GSList *e_attachment_bar_get_selected (EAttachmentBar *bar);
-void e_attachment_bar_set_width(EAttachmentBar *bar, int bar_width);
-GSList * e_attachment_bar_get_all_attachments (EAttachmentBar *bar);
-void e_attachment_bar_create_attachment_cache (EAttachment *attachment);
-void
-e_attachment_bar_bonobo_ui_populate_with_recent (BonoboUIComponent *uic, const char *path,
- EAttachmentBar *bar,
- BonoboUIVerbFn verb_cb, gpointer user_data);
-GtkAction *
-e_attachment_bar_recent_action_new (EAttachmentBar *bar,
- const gchar *action_name,
- const gchar *action_label);
-void
-e_attachment_bar_add_attachment_silent (EAttachmentBar *bar, EAttachment *attachment);
-void
-e_attachment_bar_refresh (EAttachmentBar *bar);
-
-#ifdef __cplusplus
-}
-#endif /* __cplusplus */
-
-#endif /* __E_ATTACHMENT_BAR_H__ */
diff --git a/widgets/misc/e-attachment.c b/widgets/misc/e-attachment.c
index 4f5e9ac..f472a26 100644
--- a/widgets/misc/e-attachment.c
+++ b/widgets/misc/e-attachment.c
@@ -1,4 +1,5 @@
/*
+ * e-attachment.c
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@@ -14,162 +15,845 @@
* License along with the program; if not, see <http://www.gnu.org/licenses/>
*
*
- * Authors:
- * Ettore Perazzoli <ettore ximian com>
- * Jeffrey Stedfast <fejj ximian com>
- * Srinivasa Ragavan <sragavan novell com>
- *
* Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
*
*/
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#ifdef G_OS_WIN32
-/* Include <windows.h> early (as the gio stuff below will
- * include it anyway, sigh) to workaround the DATADIR problem.
- * <windows.h> (and the headers it includes) stomps all over the
- * namespace like a baboon on crack, and especially the DATADIR enum
- * in objidl.h causes problems.
- */
-#undef DATADIR
-#define DATADIR crap_DATADIR
-#include <windows.h>
-#undef DATADIR
-#endif
+#include "e-attachment.h"
-#include <sys/stat.h>
-#include <string.h>
#include <errno.h>
-
-#include <camel/camel.h>
-
+#include <config.h>
#include <glib/gi18n.h>
-#include <glib/gstdio.h>
-
-#include <libebook/e-vcard.h>
+#include <camel/camel-iconv.h>
+#include <camel/camel-data-wrapper.h>
+#include <camel/camel-mime-message.h>
+#include <camel/camel-stream-filter.h>
+#include <camel/camel-stream-mem.h>
+#include <camel/camel-stream-null.h>
+#include <camel/camel-stream-vfs.h>
#include "e-util/e-util.h"
-#include "e-util/e-error.h"
#include "e-util/e-mktemp.h"
-#include "e-util/e-util-private.h"
-
-#include "e-attachment.h"
+#include "e-attachment-store.h"
+
+#define E_ATTACHMENT_GET_PRIVATE(obj) \
+ (G_TYPE_INSTANCE_GET_PRIVATE \
+ ((obj), E_TYPE_ATTACHMENT, EAttachmentPrivate))
+
+/* Fallback Icon */
+#define DEFAULT_ICON_NAME "mail-attachment"
+
+/* Emblems */
+#define EMBLEM_CANCELLED "gtk-cancel"
+#define EMBLEM_LOADING "emblem-downloads"
+#define EMBLEM_SAVING "document-save"
+#define EMBLEM_ENCRYPT_WEAK "security-low"
+#define EMBLEM_ENCRYPT_STRONG "security-high"
+#define EMBLEM_ENCRYPT_UNKNOWN "security-medium"
+#define EMBLEM_SIGN_BAD "stock_signature_bad"
+#define EMBLEM_SIGN_GOOD "stock_signature-ok"
+#define EMBLEM_SIGN_UNKNOWN "stock_signature"
+
+/* Attributes needed for EAttachmentStore columns. */
+#define ATTACHMENT_QUERY "standard::*,preview::*,thumbnail::*"
+
+struct _EAttachmentPrivate {
+ GFile *file;
+ GFileInfo *file_info;
+ GCancellable *cancellable;
+ CamelMimePart *mime_part;
+ guint emblem_timeout_id;
+ gchar *disposition;
+ gint percent;
+
+ guint can_show : 1;
+ guint loading : 1;
+ guint saving : 1;
+ guint shown : 1;
+
+ camel_cipher_validity_encrypt_t encrypted;
+ camel_cipher_validity_sign_t signed_;
+
+ /* This is a reference to our row in an EAttachmentStore,
+ * serving as a means of broadcasting "row-changed" signals.
+ * If we are removed from the store, we lazily free the
+ * reference when it is found to be to be invalid. */
+ GtkTreeRowReference *reference;
+};
enum {
- CHANGED,
- UPDATE,
- LAST_SIGNAL
+ PROP_0,
+ PROP_CAN_SHOW,
+ PROP_DISPOSITION,
+ PROP_ENCRYPTED,
+ PROP_FILE,
+ PROP_FILE_INFO,
+ PROP_LOADING,
+ PROP_MIME_PART,
+ PROP_PERCENT,
+ PROP_REFERENCE,
+ PROP_SAVING,
+ PROP_SHOWN,
+ PROP_SIGNED
};
-static guint signals[LAST_SIGNAL] = { 0 };
+static gpointer parent_class;
-static GObjectClass *parent_class = NULL;
+static gchar *
+attachment_get_default_charset (void)
+{
+ GConfClient *client;
+ const gchar *key;
+ gchar *charset;
+
+ /* XXX This doesn't really belong here. */
+
+ client = gconf_client_get_default ();
+ key = "/apps/evolution/mail/composer/charset";
+ charset = gconf_client_get_string (client, key, NULL);
+ if (charset == NULL || *charset == '\0') {
+ g_free (charset);
+ key = "/apps/evolution/mail/format/charset";
+ charset = gconf_client_get_string (client, key, NULL);
+ if (charset == NULL || *charset == '\0') {
+ g_free (charset);
+ charset = NULL;
+ }
+ }
+ g_object_unref (client);
+
+ if (charset == NULL)
+ charset = g_strdup (camel_iconv_locale_charset ());
+
+ if (charset == NULL)
+ charset = g_strdup ("us-ascii");
+
+ return charset;
+}
static void
-changed (EAttachment *attachment)
+attachment_update_file_info_columns (EAttachment *attachment)
{
- g_signal_emit (attachment, signals[CHANGED], 0);
-}
+ GtkTreeRowReference *reference;
+ GtkTreeModel *model;
+ GtkTreePath *path;
+ GtkTreeIter iter;
+ GFileInfo *file_info;
+ const gchar *content_type;
+ const gchar *description;
+ const gchar *display_name;
+ gchar *content_desc;
+ gchar *display_size;
+ gchar *caption;
+ goffset size;
+
+ reference = e_attachment_get_reference (attachment);
+ if (!gtk_tree_row_reference_valid (reference))
+ return;
+
+ file_info = e_attachment_get_file_info (attachment);
+ if (file_info == NULL)
+ return;
+
+ model = gtk_tree_row_reference_get_model (reference);
+ path = gtk_tree_row_reference_get_path (reference);
+ gtk_tree_model_get_iter (model, &iter, path);
+ gtk_tree_path_free (path);
+
+ content_type = g_file_info_get_content_type (file_info);
+ display_name = g_file_info_get_display_name (file_info);
+ size = g_file_info_get_size (file_info);
+ content_desc = g_content_type_get_description (content_type);
+ display_size = g_format_size_for_display (size);
-/* GtkObject methods. */
+ description = e_attachment_get_description (attachment);
+ if (description == NULL || *description == '\0')
+ description = display_name;
+
+ if (size > 0)
+ caption = g_strdup_printf (
+ "%s\n(%s)", description, display_size);
+ else
+ caption = g_strdup (description);
+
+ gtk_list_store_set (
+ GTK_LIST_STORE (model), &iter,
+ E_ATTACHMENT_STORE_COLUMN_CAPTION, caption,
+ E_ATTACHMENT_STORE_COLUMN_CONTENT_TYPE, content_desc,
+ E_ATTACHMENT_STORE_COLUMN_DESCRIPTION, description,
+ E_ATTACHMENT_STORE_COLUMN_SIZE, size,
+ -1);
+
+ g_free (content_desc);
+ g_free (display_size);
+ g_free (caption);
+}
static void
-finalise (GObject *object)
+attachment_update_icon_column (EAttachment *attachment)
{
- EAttachment *attachment = (EAttachment *) object;
- GtkWidget *dialog;
+ GtkTreeRowReference *reference;
+ GtkTreeModel *model;
+ GtkTreePath *path;
+ GtkTreeIter iter;
+ GFileInfo *file_info;
+ GCancellable *cancellable;
+ GIcon *icon = NULL;
+ const gchar *emblem_name = NULL;
+ const gchar *thumbnail_path = NULL;
- if (attachment->editor_gui != NULL) {
- dialog = glade_xml_get_widget (attachment->editor_gui, "dialog");
- g_signal_emit_by_name (dialog, "response", GTK_RESPONSE_CLOSE);
+ reference = e_attachment_get_reference (attachment);
+ if (!gtk_tree_row_reference_valid (reference))
+ return;
+
+ model = gtk_tree_row_reference_get_model (reference);
+ path = gtk_tree_row_reference_get_path (reference);
+ gtk_tree_model_get_iter (model, &iter, path);
+ gtk_tree_path_free (path);
+
+ cancellable = attachment->priv->cancellable;
+ file_info = e_attachment_get_file_info (attachment);
+
+ if (file_info != NULL) {
+ icon = g_file_info_get_icon (file_info);
+ thumbnail_path = g_file_info_get_attribute_byte_string (
+ file_info, G_FILE_ATTRIBUTE_THUMBNAIL_PATH);
}
- if (attachment->is_available_local) {
- camel_object_unref (attachment->body);
- if (attachment->pixbuf_cache != NULL)
- g_object_unref (attachment->pixbuf_cache);
- } else {
- if (attachment->cancellable) {
- /* the operation is still running, so cancel it */
- g_cancellable_cancel (attachment->cancellable);
- attachment->cancellable = NULL;
+ /* Prefer the thumbnail if we have one. */
+ if (thumbnail_path != NULL && *thumbnail_path != '\0') {
+ GFile *file;
+
+ file = g_file_new_for_path (thumbnail_path);
+ icon = g_file_icon_new (file);
+ g_object_unref (file);
+
+ /* Else use the standard icon for the content type. */
+ } else if (icon != NULL)
+ g_object_ref (icon);
+
+ /* Last ditch fallback. (GFileInfo not yet loaded?) */
+ else
+ icon = g_themed_icon_new (DEFAULT_ICON_NAME);
+
+ /* Pick an emblem, limit one. Choices listed by priority. */
+
+ if (g_cancellable_is_cancelled (cancellable))
+ emblem_name = EMBLEM_CANCELLED;
+
+ else if (e_attachment_get_loading (attachment))
+ emblem_name = EMBLEM_LOADING;
+
+ else if (e_attachment_get_saving (attachment))
+ emblem_name = EMBLEM_SAVING;
+
+ else if (e_attachment_get_encrypted (attachment))
+ switch (e_attachment_get_encrypted (attachment)) {
+ case CAMEL_CIPHER_VALIDITY_ENCRYPT_WEAK:
+ emblem_name = EMBLEM_ENCRYPT_WEAK;
+ break;
+
+ case CAMEL_CIPHER_VALIDITY_ENCRYPT_ENCRYPTED:
+ emblem_name = EMBLEM_ENCRYPT_UNKNOWN;
+ break;
+
+ case CAMEL_CIPHER_VALIDITY_ENCRYPT_STRONG:
+ emblem_name = EMBLEM_ENCRYPT_STRONG;
+ break;
+
+ default:
+ g_warn_if_reached ();
+ break;
}
- g_free (attachment->description);
+
+ else if (e_attachment_get_signed (attachment))
+ switch (e_attachment_get_signed (attachment)) {
+ case CAMEL_CIPHER_VALIDITY_SIGN_GOOD:
+ emblem_name = EMBLEM_SIGN_GOOD;
+ break;
+
+ case CAMEL_CIPHER_VALIDITY_SIGN_BAD:
+ emblem_name = EMBLEM_SIGN_BAD;
+ break;
+
+ case CAMEL_CIPHER_VALIDITY_SIGN_UNKNOWN:
+ case CAMEL_CIPHER_VALIDITY_SIGN_NEED_PUBLIC_KEY:
+ emblem_name = EMBLEM_SIGN_UNKNOWN;
+ break;
+
+ default:
+ g_warn_if_reached ();
+ break;
+ }
+
+ if (emblem_name != NULL) {
+ GIcon *emblemed_icon;
+ GEmblem *emblem;
+
+ emblemed_icon = g_themed_icon_new (emblem_name);
+ emblem = g_emblem_new (emblemed_icon);
+ g_object_unref (emblemed_icon);
+
+ emblemed_icon = g_emblemed_icon_new (icon, emblem);
+ g_object_unref (emblem);
+ g_object_unref (icon);
+
+ icon = emblemed_icon;
}
- g_free (attachment->file_name);
- g_free (attachment->store_uri);
+ gtk_list_store_set (
+ GTK_LIST_STORE (model), &iter,
+ E_ATTACHMENT_STORE_COLUMN_ICON, icon,
+ -1);
- G_OBJECT_CLASS (parent_class)->finalize (object);
+ g_object_unref (icon);
}
+static void
+attachment_update_progress_columns (EAttachment *attachment)
+{
+ GtkTreeRowReference *reference;
+ GtkTreeModel *model;
+ GtkTreePath *path;
+ GtkTreeIter iter;
+ gboolean loading;
+ gboolean saving;
+ gint percent;
+
+ reference = e_attachment_get_reference (attachment);
+ if (!gtk_tree_row_reference_valid (reference))
+ return;
-/* Signals. */
+ model = gtk_tree_row_reference_get_model (reference);
+ path = gtk_tree_row_reference_get_path (reference);
+ gtk_tree_model_get_iter (model, &iter, path);
+ gtk_tree_path_free (path);
+
+ /* Don't show progress bars until we have progress to report. */
+ percent = e_attachment_get_percent (attachment);
+ loading = e_attachment_get_loading (attachment) && (percent > 0);
+ saving = e_attachment_get_saving (attachment) && (percent > 0);
+
+ gtk_list_store_set (
+ GTK_LIST_STORE (model), &iter,
+ E_ATTACHMENT_STORE_COLUMN_LOADING, loading,
+ E_ATTACHMENT_STORE_COLUMN_PERCENT, percent,
+ E_ATTACHMENT_STORE_COLUMN_SAVING, saving,
+ -1);
+}
static void
-real_changed (EAttachment *attachment)
+attachment_set_file_info (EAttachment *attachment,
+ GFileInfo *file_info)
{
- g_return_if_fail (E_IS_ATTACHMENT (attachment));
+ GtkTreeRowReference *reference;
+ GIcon *icon;
+
+ reference = e_attachment_get_reference (attachment);
+
+ if (file_info != NULL)
+ g_object_ref (file_info);
+
+ if (attachment->priv->file_info != NULL)
+ g_object_unref (attachment->priv->file_info);
+
+ attachment->priv->file_info = file_info;
+
+ /* If the GFileInfo contains a GThemedIcon, append a
+ * fallback icon name to ensure we display something. */
+ icon = g_file_info_get_icon (file_info);
+ if (G_IS_THEMED_ICON (icon))
+ g_themed_icon_append_name (
+ G_THEMED_ICON (icon), DEFAULT_ICON_NAME);
+
+ g_object_notify (G_OBJECT (attachment), "file-info");
+
+ /* Tell the EAttachmentStore its total size changed. */
+ if (gtk_tree_row_reference_valid (reference)) {
+ GtkTreeModel *model;
+ model = gtk_tree_row_reference_get_model (reference);
+ g_object_notify (G_OBJECT (model), "total-size");
+ }
}
static void
-real_update_attachment (EAttachment *attachment, char *msg)
+attachment_set_loading (EAttachment *attachment,
+ gboolean loading)
{
- g_return_if_fail (E_IS_ATTACHMENT (attachment));
+ GtkTreeRowReference *reference;
+
+ reference = e_attachment_get_reference (attachment);
+
+ attachment->priv->percent = 0;
+ attachment->priv->loading = loading;
+
+ g_object_freeze_notify (G_OBJECT (attachment));
+ g_object_notify (G_OBJECT (attachment), "percent");
+ g_object_notify (G_OBJECT (attachment), "loading");
+ g_object_thaw_notify (G_OBJECT (attachment));
+
+ if (gtk_tree_row_reference_valid (reference)) {
+ GtkTreeModel *model;
+ model = gtk_tree_row_reference_get_model (reference);
+ g_object_notify (G_OBJECT (model), "num-loading");
+ }
+}
+
+static void
+attachment_set_saving (EAttachment *attachment,
+ gboolean saving)
+{
+ attachment->priv->percent = 0;
+ attachment->priv->saving = saving;
+
+ g_object_freeze_notify (G_OBJECT (attachment));
+ g_object_notify (G_OBJECT (attachment), "percent");
+ g_object_notify (G_OBJECT (attachment), "saving");
+ g_object_thaw_notify (G_OBJECT (attachment));
+}
+
+static void
+attachment_progress_cb (goffset current_num_bytes,
+ goffset total_num_bytes,
+ EAttachment *attachment)
+{
+ attachment->priv->percent =
+ (current_num_bytes * 100) / total_num_bytes;
+
+ g_object_notify (G_OBJECT (attachment), "percent");
+}
+
+static gboolean
+attachment_cancelled_timeout_cb (EAttachment *attachment)
+{
+ attachment->priv->emblem_timeout_id = 0;
+ g_cancellable_reset (attachment->priv->cancellable);
+
+ attachment_update_icon_column (attachment);
+
+ return FALSE;
+}
+
+static void
+attachment_cancelled_cb (EAttachment *attachment)
+{
+ /* Reset the GCancellable after one second. This causes a
+ * cancel emblem to be briefly shown on the attachment icon
+ * as visual feedback that an operation was cancelled. */
+
+ if (attachment->priv->emblem_timeout_id > 0)
+ g_source_remove (attachment->priv->emblem_timeout_id);
+
+ attachment->priv->emblem_timeout_id = g_timeout_add_seconds (
+ 1, (GSourceFunc) attachment_cancelled_timeout_cb, attachment);
+
+ attachment_update_icon_column (attachment);
+}
+
+static void
+attachment_set_property (GObject *object,
+ guint property_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ switch (property_id) {
+ case PROP_CAN_SHOW:
+ e_attachment_set_can_show (
+ E_ATTACHMENT (object),
+ g_value_get_boolean (value));
+ return;
+
+ case PROP_DISPOSITION:
+ e_attachment_set_disposition (
+ E_ATTACHMENT (object),
+ g_value_get_string (value));
+ return;
+
+ case PROP_ENCRYPTED:
+ e_attachment_set_encrypted (
+ E_ATTACHMENT (object),
+ g_value_get_int (value));
+ return;
+
+ case PROP_FILE:
+ e_attachment_set_file (
+ E_ATTACHMENT (object),
+ g_value_get_object (value));
+ return;
+
+ case PROP_SHOWN:
+ e_attachment_set_shown (
+ E_ATTACHMENT (object),
+ g_value_get_boolean (value));
+ return;
+
+ case PROP_MIME_PART:
+ e_attachment_set_mime_part (
+ E_ATTACHMENT (object),
+ g_value_get_boxed (value));
+ return;
+
+ case PROP_REFERENCE:
+ e_attachment_set_reference (
+ E_ATTACHMENT (object),
+ g_value_get_boxed (value));
+ return;
+
+ case PROP_SIGNED:
+ e_attachment_set_signed (
+ E_ATTACHMENT (object),
+ g_value_get_int (value));
+ return;
+ }
+
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+}
+
+static void
+attachment_get_property (GObject *object,
+ guint property_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ switch (property_id) {
+ case PROP_CAN_SHOW:
+ g_value_set_boolean (
+ value, e_attachment_get_can_show (
+ E_ATTACHMENT (object)));
+ return;
+
+ case PROP_DISPOSITION:
+ g_value_set_string (
+ value, e_attachment_get_disposition (
+ E_ATTACHMENT (object)));
+ return;
+
+ case PROP_ENCRYPTED:
+ g_value_set_int (
+ value, e_attachment_get_encrypted (
+ E_ATTACHMENT (object)));
+ return;
+
+ case PROP_FILE:
+ g_value_set_object (
+ value, e_attachment_get_file (
+ E_ATTACHMENT (object)));
+ return;
+
+ case PROP_FILE_INFO:
+ g_value_set_object (
+ value, e_attachment_get_file_info (
+ E_ATTACHMENT (object)));
+ return;
+
+ case PROP_SHOWN:
+ g_value_set_boolean (
+ value, e_attachment_get_shown (
+ E_ATTACHMENT (object)));
+ return;
+
+ case PROP_LOADING:
+ g_value_set_boolean (
+ value, e_attachment_get_loading (
+ E_ATTACHMENT (object)));
+ return;
+
+ case PROP_MIME_PART:
+ g_value_set_boxed (
+ value, e_attachment_get_mime_part (
+ E_ATTACHMENT (object)));
+ return;
+
+ case PROP_PERCENT:
+ g_value_set_int (
+ value, e_attachment_get_percent (
+ E_ATTACHMENT (object)));
+ return;
+
+ case PROP_REFERENCE:
+ g_value_set_boxed (
+ value, e_attachment_get_reference (
+ E_ATTACHMENT (object)));
+ return;
+
+ case PROP_SAVING:
+ g_value_set_boolean (
+ value, e_attachment_get_saving (
+ E_ATTACHMENT (object)));
+ return;
+
+ case PROP_SIGNED:
+ g_value_set_int (
+ value, e_attachment_get_signed (
+ E_ATTACHMENT (object)));
+ return;
+ }
+
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
}
+static void
+attachment_dispose (GObject *object)
+{
+ EAttachmentPrivate *priv;
+
+ priv = E_ATTACHMENT_GET_PRIVATE (object);
+
+ if (priv->file != NULL) {
+ g_object_unref (priv->file);
+ priv->file = NULL;
+ }
+
+ if (priv->file_info != NULL) {
+ g_object_unref (priv->file_info);
+ priv->file_info = NULL;
+ }
+
+ if (priv->cancellable != NULL) {
+ g_object_unref (priv->cancellable);
+ priv->cancellable = NULL;
+ }
+
+ if (priv->mime_part != NULL) {
+ camel_object_unref (priv->mime_part);
+ priv->mime_part = NULL;
+ }
+
+ if (priv->emblem_timeout_id > 0) {
+ g_source_remove (priv->emblem_timeout_id);
+ priv->emblem_timeout_id = 0;
+ }
+
+ /* This accepts NULL arguments. */
+ gtk_tree_row_reference_free (priv->reference);
+ priv->reference = NULL;
+
+ /* Chain up to parent's dispose() method. */
+ G_OBJECT_CLASS (parent_class)->dispose (object);
+}
static void
-class_init (EAttachmentClass *klass)
+attachment_finalize (GObject *object)
+{
+ EAttachmentPrivate *priv;
+
+ priv = E_ATTACHMENT_GET_PRIVATE (object);
+
+ g_free (priv->disposition);
+
+ /* Chain up to parent's finalize() method. */
+ G_OBJECT_CLASS (parent_class)->finalize (object);
+}
+
+static void
+attachment_class_init (EAttachmentClass *class)
{
GObjectClass *object_class;
- object_class = (GObjectClass*) klass;
- parent_class = g_type_class_ref (G_TYPE_OBJECT);
-
- object_class->finalize = finalise;
- klass->changed = real_changed;
- klass->update = real_update_attachment;
-
- 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);
- signals[UPDATE] = g_signal_new ("update",
- E_TYPE_ATTACHMENT,
- G_SIGNAL_RUN_FIRST,
- G_STRUCT_OFFSET (EAttachmentClass, update),
- 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->percentage = -1;
- attachment->description = NULL;
- attachment->disposition = FALSE;
- attachment->sign = CAMEL_CIPHER_VALIDITY_SIGN_NONE;
- attachment->encrypt = CAMEL_CIPHER_VALIDITY_ENCRYPT_NONE;
- attachment->store_uri = NULL;
- attachment->cancellable = NULL;
+ parent_class = g_type_class_peek_parent (class);
+ g_type_class_add_private (class, sizeof (EAttachmentPrivate));
+
+ object_class = G_OBJECT_CLASS (class);
+ object_class->set_property = attachment_set_property;
+ object_class->get_property = attachment_get_property;
+ object_class->dispose = attachment_dispose;
+ object_class->finalize = attachment_finalize;
+
+ g_object_class_install_property (
+ object_class,
+ PROP_CAN_SHOW,
+ g_param_spec_boolean (
+ "can-show",
+ "Can Show",
+ NULL,
+ FALSE,
+ G_PARAM_READWRITE |
+ G_PARAM_CONSTRUCT));
+
+ g_object_class_install_property (
+ object_class,
+ PROP_DISPOSITION,
+ g_param_spec_string (
+ "disposition",
+ "Disposition",
+ NULL,
+ "attachment",
+ G_PARAM_READWRITE |
+ G_PARAM_CONSTRUCT));
+
+ /* FIXME Define a GEnumClass for this. */
+ g_object_class_install_property (
+ object_class,
+ PROP_ENCRYPTED,
+ g_param_spec_int (
+ "encrypted",
+ "Encrypted",
+ NULL,
+ CAMEL_CIPHER_VALIDITY_ENCRYPT_NONE,
+ CAMEL_CIPHER_VALIDITY_ENCRYPT_STRONG,
+ CAMEL_CIPHER_VALIDITY_ENCRYPT_NONE,
+ G_PARAM_READWRITE |
+ G_PARAM_CONSTRUCT));
+
+ g_object_class_install_property (
+ object_class,
+ PROP_FILE,
+ g_param_spec_object (
+ "file",
+ "File",
+ NULL,
+ G_TYPE_FILE,
+ G_PARAM_READWRITE |
+ G_PARAM_CONSTRUCT));
+
+ g_object_class_install_property (
+ object_class,
+ PROP_FILE_INFO,
+ g_param_spec_object (
+ "file-info",
+ "File Info",
+ NULL,
+ G_TYPE_FILE_INFO,
+ G_PARAM_READABLE));
+
+ g_object_class_install_property (
+ object_class,
+ PROP_LOADING,
+ g_param_spec_boolean (
+ "loading",
+ "Loading",
+ NULL,
+ FALSE,
+ G_PARAM_READABLE));
+
+ g_object_class_install_property (
+ object_class,
+ PROP_MIME_PART,
+ g_param_spec_boxed (
+ "mime-part",
+ "MIME Part",
+ NULL,
+ E_TYPE_CAMEL_OBJECT,
+ G_PARAM_READWRITE));
+
+ g_object_class_install_property (
+ object_class,
+ PROP_PERCENT,
+ g_param_spec_int (
+ "percent",
+ "Percent",
+ NULL,
+ 0,
+ 100,
+ 0,
+ G_PARAM_READABLE));
+
+ g_object_class_install_property (
+ object_class,
+ PROP_REFERENCE,
+ g_param_spec_boxed (
+ "reference",
+ "Reference",
+ NULL,
+ GTK_TYPE_TREE_ROW_REFERENCE,
+ G_PARAM_READWRITE));
+
+ g_object_class_install_property (
+ object_class,
+ PROP_SAVING,
+ g_param_spec_boolean (
+ "saving",
+ "Saving",
+ NULL,
+ FALSE,
+ G_PARAM_READABLE));
+
+ g_object_class_install_property (
+ object_class,
+ PROP_SHOWN,
+ g_param_spec_boolean (
+ "shown",
+ "Shown",
+ NULL,
+ FALSE,
+ G_PARAM_READWRITE |
+ G_PARAM_CONSTRUCT));
+
+ /* FIXME Define a GEnumClass for this. */
+ g_object_class_install_property (
+ object_class,
+ PROP_SIGNED,
+ g_param_spec_int (
+ "signed",
+ "Signed",
+ NULL,
+ CAMEL_CIPHER_VALIDITY_SIGN_NONE,
+ CAMEL_CIPHER_VALIDITY_SIGN_NEED_PUBLIC_KEY,
+ CAMEL_CIPHER_VALIDITY_SIGN_NONE,
+ G_PARAM_READWRITE |
+ G_PARAM_CONSTRUCT));
+}
+
+static void
+attachment_init (EAttachment *attachment)
+{
+ attachment->priv = E_ATTACHMENT_GET_PRIVATE (attachment);
+ attachment->priv->cancellable = g_cancellable_new ();
+ attachment->priv->encrypted = CAMEL_CIPHER_VALIDITY_ENCRYPT_NONE;
+ attachment->priv->signed_ = CAMEL_CIPHER_VALIDITY_SIGN_NONE;
+
+ g_signal_connect (
+ attachment, "notify::encrypted",
+ G_CALLBACK (attachment_update_icon_column), NULL);
+
+ g_signal_connect (
+ attachment, "notify::file-info",
+ G_CALLBACK (attachment_update_file_info_columns), NULL);
+
+ g_signal_connect (
+ attachment, "notify::file-info",
+ G_CALLBACK (attachment_update_icon_column), NULL);
+
+ g_signal_connect (
+ attachment, "notify::loading",
+ G_CALLBACK (attachment_update_icon_column), NULL);
+
+ g_signal_connect (
+ attachment, "notify::loading",
+ G_CALLBACK (attachment_update_progress_columns), NULL);
+
+ g_signal_connect (
+ attachment, "notify::percent",
+ G_CALLBACK (attachment_update_progress_columns), NULL);
+
+ g_signal_connect (
+ attachment, "notify::reference",
+ G_CALLBACK (attachment_update_file_info_columns), NULL);
+
+ g_signal_connect (
+ attachment, "notify::reference",
+ G_CALLBACK (attachment_update_icon_column), NULL);
+
+ g_signal_connect (
+ attachment, "notify::reference",
+ G_CALLBACK (attachment_update_progress_columns), NULL);
+
+ g_signal_connect (
+ attachment, "notify::saving",
+ G_CALLBACK (attachment_update_icon_column), NULL);
+
+ g_signal_connect (
+ attachment, "notify::saving",
+ G_CALLBACK (attachment_update_progress_columns), NULL);
+
+ g_signal_connect (
+ attachment, "notify::signed",
+ G_CALLBACK (attachment_update_icon_column), NULL);
+
+ g_signal_connect_swapped (
+ attachment->priv->cancellable, "cancelled",
+ G_CALLBACK (attachment_cancelled_cb), attachment);
}
GType
@@ -177,707 +861,1814 @@ e_attachment_get_type (void)
{
static GType type = 0;
- if (type == 0) {
- static const GTypeInfo info = {
+ if (G_UNLIKELY (type == 0)) {
+ static const GTypeInfo type_info = {
sizeof (EAttachmentClass),
- NULL,
- NULL,
- (GClassInitFunc) class_init,
- NULL,
- NULL,
+ (GBaseInitFunc) NULL,
+ (GBaseFinalizeFunc) NULL,
+ (GClassInitFunc) attachment_class_init,
+ (GClassFinalizeFunc) NULL,
+ NULL, /* class_data */
sizeof (EAttachment),
- 0,
- (GInstanceInitFunc) init,
+ 0, /* n_preallocs */
+ (GInstanceInitFunc) attachment_init,
+ NULL /* value_table */
};
- type = g_type_register_static (G_TYPE_OBJECT, "EAttachment", &info, 0);
+ type = g_type_register_static (
+ G_TYPE_OBJECT, "EAttachment", &type_info, 0);
}
return type;
}
-/**
- * file_ext_is:
- * @param file_name: path for file
- * @param ext: desired extension, with a dot
- * @return if file_name has extension ext or not
- **/
+EAttachment *
+e_attachment_new (void)
+{
+ return g_object_new (E_TYPE_ATTACHMENT, NULL);
+}
-static gboolean
-file_ext_is (const char *file_name, const char *ext)
+EAttachment *
+e_attachment_new_for_path (const gchar *path)
{
- int i, dot = -1;
+ EAttachment *attachment;
+ GFile *file;
- if (!file_name || !ext)
- return FALSE;
+ g_return_val_if_fail (path != NULL, NULL);
- for (i = 0; file_name[i]; i++) {
- if (file_name [i] == '.')
- dot = i;
- }
+ file = g_file_new_for_path (path);
+ attachment = g_object_new (E_TYPE_ATTACHMENT, "file", file, NULL);
+ g_object_unref (file);
- if (dot > 0) {
- return 0 == g_ascii_strcasecmp (file_name + dot, ext);
- }
+ return attachment;
+}
- return FALSE;
+EAttachment *
+e_attachment_new_for_uri (const gchar *uri)
+{
+ EAttachment *attachment;
+ GFile *file;
+
+ g_return_val_if_fail (uri != NULL, NULL);
+
+ file = g_file_new_for_uri (uri);
+ attachment = g_object_new (E_TYPE_ATTACHMENT, "file", file, NULL);
+ g_object_unref (file);
+
+ return attachment;
}
-static char *
-attachment_guess_mime_type (const char *file_name)
+EAttachment *
+e_attachment_new_for_message (CamelMimeMessage *message)
{
- char *type;
- gchar *content = NULL;
+ CamelDataWrapper *wrapper;
+ CamelMimePart *mime_part;
+ EAttachment *attachment;
+ GString *description;
+ const gchar *subject;
- type = e_util_guess_mime_type (file_name, TRUE);
+ g_return_val_if_fail (CAMEL_IS_MIME_MESSAGE (message), NULL);
- if (type && strcmp (type, "text/directory") == 0 &&
- file_ext_is (file_name, ".vcf") &&
- g_file_get_contents (file_name, &content, NULL, NULL) &&
- content) {
- EVCard *vc = e_vcard_new_from_string (content);
+ mime_part = camel_mime_part_new ();
+ camel_mime_part_set_disposition (mime_part, "inline");
+ subject = camel_mime_message_get_subject (message);
- if (vc) {
- g_free (type);
- g_object_unref (G_OBJECT (vc));
+ description = g_string_new (_("Attached message"));
+ if (subject != NULL)
+ g_string_append_printf (description, " - %s", subject);
+ camel_mime_part_set_description (mime_part, description->str);
+ g_string_free (description, TRUE);
+
+ wrapper = CAMEL_DATA_WRAPPER (message);
+ camel_medium_set_content_object (CAMEL_MEDIUM (mime_part), wrapper);
+ camel_mime_part_set_content_type (mime_part, "message/rfc822");
+
+ attachment = e_attachment_new ();
+ e_attachment_set_mime_part (attachment, mime_part);
+ camel_object_unref (mime_part);
+
+ return attachment;
+}
+
+void
+e_attachment_add_to_multipart (EAttachment *attachment,
+ CamelMultipart *multipart,
+ const gchar *default_charset)
+{
+ CamelContentType *content_type;
+ CamelDataWrapper *wrapper;
+ CamelMimePart *mime_part;
+
+ /* XXX EMsgComposer might be a better place for this function. */
+
+ g_return_if_fail (E_IS_ATTACHMENT (attachment));
+ g_return_if_fail (CAMEL_IS_MULTIPART (multipart));
+
+ /* Still loading? Too bad. */
+ mime_part = e_attachment_get_mime_part (attachment);
+ if (mime_part == NULL)
+ return;
+
+ content_type = camel_mime_part_get_content_type (mime_part);
+ wrapper = camel_medium_get_content_object (CAMEL_MEDIUM (mime_part));
+
+ if (CAMEL_IS_MULTIPART (wrapper))
+ goto exit;
+
+ /* For text content, determine the best encoding and character set. */
+ if (camel_content_type_is (content_type, "text", "*")) {
+ CamelTransferEncoding encoding;
+ CamelStreamFilter *filtered_stream;
+ CamelMimeFilterBestenc *filter;
+ CamelStream *stream;
+ const gchar *charset;
+
+ charset = camel_content_type_param (content_type, "charset");
+
+ /* Determine the best encoding by writing the MIME
+ * part to a NULL stream with a "bestenc" filter. */
+ stream = camel_stream_null_new ();
+ filtered_stream = camel_stream_filter_new_with_stream (stream);
+ filter = camel_mime_filter_bestenc_new (
+ CAMEL_BESTENC_GET_ENCODING);
+ camel_stream_filter_add (
+ filtered_stream, CAMEL_MIME_FILTER (filter));
+ camel_data_wrapper_decode_to_stream (
+ wrapper, CAMEL_STREAM (filtered_stream));
+ camel_object_unref (filtered_stream);
+ camel_object_unref (stream);
+
+ /* Retrieve the best encoding from the filter. */
+ encoding = camel_mime_filter_bestenc_get_best_encoding (
+ filter, CAMEL_BESTENC_8BIT);
+ camel_mime_part_set_encoding (mime_part, encoding);
+ camel_object_unref (filter);
+
+ 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 == NULL && default_charset == NULL) {
+ default_charset = attachment_get_default_charset ();
+ /* FIXME Check that this fits within the
+ * default_charset and if not, find one
+ * that does and/or allow the user to
+ * specify. */
+ }
- type = g_strdup ("text/x-vcard");
+ if (charset == NULL) {
+ gchar *type;
+
+ camel_content_type_set_param (
+ content_type, "charset", default_charset);
+ type = camel_content_type_format (content_type);
+ camel_mime_part_set_content_type (mime_part, type);
+ g_free (type);
}
+ /* Otherwise, unless it's a message/rfc822, Base64 encode it. */
+ } else if (!CAMEL_IS_MIME_MESSAGE (wrapper))
+ camel_mime_part_set_encoding (
+ mime_part, CAMEL_TRANSFER_ENCODING_BASE64);
+
+exit:
+ camel_multipart_add_part (multipart, mime_part);
+}
+
+void
+e_attachment_cancel (EAttachment *attachment)
+{
+ g_return_if_fail (E_IS_ATTACHMENT (attachment));
+
+ g_cancellable_cancel (attachment->priv->cancellable);
+}
+
+gboolean
+e_attachment_get_can_show (EAttachment *attachment)
+{
+ g_return_val_if_fail (E_IS_ATTACHMENT (attachment), FALSE);
+
+ return attachment->priv->can_show;
+}
+
+void
+e_attachment_set_can_show (EAttachment *attachment,
+ gboolean can_show)
+{
+ g_return_if_fail (E_IS_ATTACHMENT (attachment));
+
+ attachment->priv->can_show = can_show;
+
+ g_object_notify (G_OBJECT (attachment), "can-show");
+}
+
+const gchar *
+e_attachment_get_disposition (EAttachment *attachment)
+{
+ g_return_val_if_fail (E_IS_ATTACHMENT (attachment), NULL);
+
+ return attachment->priv->disposition;
+}
+
+void
+e_attachment_set_disposition (EAttachment *attachment,
+ const gchar *disposition)
+{
+ g_return_if_fail (E_IS_ATTACHMENT (attachment));
+
+ g_free (attachment->priv->disposition);
+ attachment->priv->disposition = g_strdup (disposition);
+
+ g_object_notify (G_OBJECT (attachment), "disposition");
+}
+
+GFile *
+e_attachment_get_file (EAttachment *attachment)
+{
+ g_return_val_if_fail (E_IS_ATTACHMENT (attachment), NULL);
+
+ return attachment->priv->file;
+}
+
+void
+e_attachment_set_file (EAttachment *attachment,
+ GFile *file)
+{
+ g_return_if_fail (E_IS_ATTACHMENT (attachment));
+
+ if (file != NULL) {
+ g_return_if_fail (G_IS_FILE (file));
+ g_object_ref (file);
}
- g_free (content);
+ if (attachment->priv->file != NULL)
+ g_object_unref (attachment->priv->file);
- if (type) {
- /* Check if returned mime_type is valid */
- CamelContentType *ctype = camel_content_type_decode (type);
+ attachment->priv->file = file;
- if (!ctype) {
- g_free (type);
- type = NULL;
- } else
- camel_content_type_unref (ctype);
+ g_object_notify (G_OBJECT (attachment), "file");
+}
+
+GFileInfo *
+e_attachment_get_file_info (EAttachment *attachment)
+{
+ g_return_val_if_fail (E_IS_ATTACHMENT (attachment), NULL);
+
+ return attachment->priv->file_info;
+}
+
+gboolean
+e_attachment_get_loading (EAttachment *attachment)
+{
+ g_return_val_if_fail (E_IS_ATTACHMENT (attachment), FALSE);
+
+ return attachment->priv->loading;
+}
+
+CamelMimePart *
+e_attachment_get_mime_part (EAttachment *attachment)
+{
+ g_return_val_if_fail (E_IS_ATTACHMENT (attachment), NULL);
+
+ return attachment->priv->mime_part;
+}
+
+void
+e_attachment_set_mime_part (EAttachment *attachment,
+ CamelMimePart *mime_part)
+{
+ g_return_if_fail (E_IS_ATTACHMENT (attachment));
+
+ if (mime_part != NULL) {
+ g_return_if_fail (CAMEL_IS_MIME_PART (mime_part));
+ camel_object_ref (mime_part);
}
- return type;
+ if (attachment->priv->mime_part != NULL)
+ camel_object_unref (attachment->priv->mime_part);
+
+ attachment->priv->mime_part = mime_part;
+
+ g_object_notify (G_OBJECT (attachment), "mime-part");
}
-
-/**
- * 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)
+gint
+e_attachment_get_percent (EAttachment *attachment)
{
- EAttachment *new;
- CamelMimePart *part;
- CamelDataWrapper *wrapper;
- CamelStream *stream;
- struct stat statbuf;
- char *mime_type;
- char *filename;
- CamelURL *url;
+ g_return_val_if_fail (E_IS_ATTACHMENT (attachment), 0);
+
+ return attachment->priv->percent;
+}
+
+GtkTreeRowReference *
+e_attachment_get_reference (EAttachment *attachment)
+{
+ g_return_val_if_fail (E_IS_ATTACHMENT (attachment), NULL);
+
+ return attachment->priv->reference;
+}
+
+void
+e_attachment_set_reference (EAttachment *attachment,
+ GtkTreeRowReference *reference)
+{
+ g_return_if_fail (E_IS_ATTACHMENT (attachment));
+
+ if (reference != NULL)
+ reference = gtk_tree_row_reference_copy (reference);
+
+ gtk_tree_row_reference_free (attachment->priv->reference);
+ attachment->priv->reference = reference;
+
+ g_object_notify (G_OBJECT (attachment), "reference");
+}
+
+gboolean
+e_attachment_get_saving (EAttachment *attachment)
+{
+ g_return_val_if_fail (E_IS_ATTACHMENT (attachment), FALSE);
+
+ return attachment->priv->saving;
+}
+
+gboolean
+e_attachment_get_shown (EAttachment *attachment)
+{
+ g_return_val_if_fail (E_IS_ATTACHMENT (attachment), FALSE);
+
+ return attachment->priv->shown;
+}
+
+void
+e_attachment_set_shown (EAttachment *attachment,
+ gboolean shown)
+{
+ g_return_if_fail (E_IS_ATTACHMENT (attachment));
+
+ attachment->priv->shown = shown;
+
+ g_object_notify (G_OBJECT (attachment), "shown");
+}
+
+camel_cipher_validity_encrypt_t
+e_attachment_get_encrypted (EAttachment *attachment)
+{
+ g_return_val_if_fail (
+ E_IS_ATTACHMENT (attachment),
+ CAMEL_CIPHER_VALIDITY_ENCRYPT_NONE);
- g_return_val_if_fail (file_name != NULL, NULL);
+ return attachment->priv->encrypted;
+}
+
+void
+e_attachment_set_encrypted (EAttachment *attachment,
+ camel_cipher_validity_encrypt_t encrypted)
+{
+ g_return_if_fail (E_IS_ATTACHMENT (attachment));
+
+ attachment->priv->encrypted = encrypted;
+
+ g_object_notify (G_OBJECT (attachment), "encrypted");
+}
- if (g_stat (file_name, &statbuf) < 0) {
- camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM,
- _("Cannot attach file %s: %s"),
- file_name, g_strerror (errno));
+camel_cipher_validity_sign_t
+e_attachment_get_signed (EAttachment *attachment)
+{
+ g_return_val_if_fail (
+ E_IS_ATTACHMENT (attachment),
+ CAMEL_CIPHER_VALIDITY_SIGN_NONE);
+
+ return attachment->priv->signed_;
+}
+
+void
+e_attachment_set_signed (EAttachment *attachment,
+ camel_cipher_validity_sign_t signed_)
+{
+ g_return_if_fail (E_IS_ATTACHMENT (attachment));
+
+ attachment->priv->signed_ = signed_;
+
+ g_object_notify (G_OBJECT (attachment), "signed");
+}
+
+const gchar *
+e_attachment_get_description (EAttachment *attachment)
+{
+ GFileInfo *file_info;
+ const gchar *attribute;
+
+ g_return_val_if_fail (E_IS_ATTACHMENT (attachment), NULL);
+
+ attribute = G_FILE_ATTRIBUTE_STANDARD_DESCRIPTION;
+ file_info = e_attachment_get_file_info (attachment);
+
+ if (file_info == NULL)
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 g_file_info_get_attribute_string (file_info, attribute);
+}
+
+const gchar *
+e_attachment_get_thumbnail_path (EAttachment *attachment)
+{
+ GFileInfo *file_info;
+ const gchar *attribute;
+
+ g_return_val_if_fail (E_IS_ATTACHMENT (attachment), NULL);
+
+ attribute = G_FILE_ATTRIBUTE_THUMBNAIL_PATH;
+ file_info = e_attachment_get_file_info (attachment);
+
+ if (file_info == NULL)
return NULL;
- }
- if (!(stream = camel_stream_fs_new_with_name (file_name, O_RDONLY, 0))) {
- camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM,
- _("Cannot attach file %s: %s"),
- file_name, g_strerror (errno));
+ return g_file_info_get_attribute_byte_string (file_info, attribute);
+}
+
+gboolean
+e_attachment_is_rfc822 (EAttachment *attachment)
+{
+ GFileInfo *file_info;
+ const gchar *content_type;
+ gchar *mime_type;
+ gboolean is_rfc822;
+
+ g_return_val_if_fail (E_IS_ATTACHMENT (attachment), FALSE);
+
+ file_info = e_attachment_get_file_info (attachment);
+ if (file_info == NULL)
+ return FALSE;
+
+ content_type = g_file_info_get_content_type (file_info);
+ if (content_type == NULL)
+ return FALSE;
+
+ mime_type = g_content_type_get_mime_type (content_type);
+ is_rfc822 = (g_ascii_strcasecmp (mime_type, "message/rfc822") == 0);
+ g_free (mime_type);
+
+ return is_rfc822;
+}
+
+GList *
+e_attachment_list_apps (EAttachment *attachment)
+{
+ GList *app_info_list;
+ GFileInfo *file_info;
+ const gchar *content_type;
+ const gchar *display_name;
+ gchar *allocated;
+
+ g_return_val_if_fail (E_IS_ATTACHMENT (attachment), NULL);
+
+ file_info = e_attachment_get_file_info (attachment);
+ if (file_info == NULL)
return NULL;
- }
- if ((mime_type = attachment_guess_mime_type (file_name))) {
- if (!g_ascii_strcasecmp (mime_type, "message/rfc822")) {
- wrapper = (CamelDataWrapper *) camel_mime_message_new ();
- } else {
- wrapper = camel_data_wrapper_new ();
- }
+ content_type = g_file_info_get_content_type (file_info);
+ display_name = g_file_info_get_display_name (file_info);
+ g_return_val_if_fail (content_type != NULL, NULL);
+
+ app_info_list = g_app_info_get_all_for_type (content_type);
+
+ if (app_info_list != NULL || display_name == NULL)
+ goto exit;
+
+ if (!g_content_type_is_unknown (content_type))
+ goto exit;
- camel_data_wrapper_construct_from_stream (wrapper, stream);
- camel_data_wrapper_set_mime_type (wrapper, mime_type);
- g_free (mime_type);
- } else {
+ allocated = g_content_type_guess (display_name, NULL, 0, NULL);
+ app_info_list = g_app_info_get_all_for_type (allocated);
+ g_free (allocated);
+
+exit:
+ return app_info_list;
+}
+
+/************************* e_attachment_load_async() *************************/
+
+typedef struct _LoadContext LoadContext;
+
+struct _LoadContext {
+ EAttachment *attachment;
+ GSimpleAsyncResult *simple;
+
+ GInputStream *input_stream;
+ GOutputStream *output_stream;
+ GFileInfo *file_info;
+ goffset total_num_bytes;
+ gssize bytes_read;
+ gchar buffer[4096];
+};
+
+/* Forward Declaration */
+static void
+attachment_load_stream_read_cb (GInputStream *input_stream,
+ GAsyncResult *result,
+ LoadContext *load_context);
+
+static LoadContext *
+attachment_load_context_new (EAttachment *attachment,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ LoadContext *load_context;
+ GSimpleAsyncResult *simple;
+
+ simple = g_simple_async_result_new (
+ G_OBJECT (attachment), callback,
+ user_data, e_attachment_load_async);
+
+ load_context = g_slice_new0 (LoadContext);
+ load_context->attachment = g_object_ref (attachment);
+ load_context->simple = simple;
+
+ attachment_set_loading (load_context->attachment, TRUE);
+
+ return load_context;
+}
+
+static void
+attachment_load_context_free (LoadContext *load_context)
+{
+ /* Do not free the GSimpleAsyncResult. */
+ g_object_unref (load_context->attachment);
+
+ if (load_context->input_stream != NULL)
+ g_object_unref (load_context->input_stream);
+
+ if (load_context->output_stream != NULL)
+ g_object_unref (load_context->output_stream);
+
+ if (load_context->file_info != NULL)
+ g_object_unref (load_context->file_info);
+
+ g_slice_free (LoadContext, load_context);
+}
+
+static gboolean
+attachment_load_check_for_error (LoadContext *load_context,
+ GError *error)
+{
+ GSimpleAsyncResult *simple;
+
+ if (error == NULL)
+ return FALSE;
+
+ /* Steal the result. */
+ simple = load_context->simple;
+ load_context->simple = NULL;
+
+ g_simple_async_result_set_from_error (simple, error);
+ g_simple_async_result_complete (simple);
+ g_error_free (error);
+
+ attachment_load_context_free (load_context);
+
+ return TRUE;
+}
+
+static void
+attachment_load_finish (LoadContext *load_context)
+{
+ GFileInfo *file_info;
+ EAttachment *attachment;
+ GMemoryOutputStream *output_stream;
+ GSimpleAsyncResult *simple;
+ CamelDataWrapper *wrapper;
+ CamelMimePart *mime_part;
+ CamelStream *stream;
+ const gchar *attribute;
+ const gchar *content_type;
+ const gchar *display_name;
+ const gchar *description;
+ const gchar *disposition;
+ gchar *mime_type;
+ gpointer data;
+ gsize size;
+
+ /* Steal the result. */
+ simple = load_context->simple;
+ load_context->simple = NULL;
+
+ file_info = load_context->file_info;
+ attachment = load_context->attachment;
+ output_stream = G_MEMORY_OUTPUT_STREAM (load_context->output_stream);
+
+ if (e_attachment_is_rfc822 (attachment))
+ 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, "application/octet-stream");
- }
+ content_type = g_file_info_get_content_type (file_info);
+ mime_type = g_content_type_get_mime_type (content_type);
+
+ data = g_memory_output_stream_get_data (output_stream);
+ size = g_memory_output_stream_get_data_size (output_stream);
+
+ stream = camel_stream_mem_new_with_buffer (data, size);
+ camel_data_wrapper_construct_from_stream (wrapper, stream);
+ camel_data_wrapper_set_mime_type (wrapper, mime_type);
+ camel_stream_close (stream);
camel_object_unref (stream);
- part = camel_mime_part_new ();
- camel_medium_set_content_object (CAMEL_MEDIUM (part), wrapper);
+ mime_part = camel_mime_part_new ();
+ camel_medium_set_content_object (CAMEL_MEDIUM (mime_part), wrapper);
+
camel_object_unref (wrapper);
+ g_free (mime_type);
- camel_mime_part_set_disposition (part, disposition);
- filename = g_path_get_basename (file_name);
- camel_mime_part_set_filename (part, 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
+ display_name = g_file_info_get_display_name (file_info);
+ if (display_name != NULL)
+ camel_mime_part_set_filename (mime_part, display_name);
- 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->cancellable = NULL;
- new->is_available_local = TRUE;
- new->file_name = filename;
+ attribute = G_FILE_ATTRIBUTE_STANDARD_DESCRIPTION;
+ description = g_file_info_get_attribute_string (file_info, attribute);
+ if (description != NULL)
+ camel_mime_part_set_description (mime_part, description);
- url = camel_url_new ("file://", NULL);
- camel_url_set_path (url, file_name);
- new->store_uri = camel_url_to_string (url, 0);
- camel_url_free (url);
+ disposition = e_attachment_get_disposition (attachment);
+ if (disposition != NULL)
+ camel_mime_part_set_disposition (mime_part, disposition);
- return new;
-}
+ g_simple_async_result_set_op_res_gpointer (
+ simple, mime_part, (GDestroyNotify) camel_object_unref);
+
+ g_simple_async_result_complete (simple);
+ attachment_load_context_free (load_context);
+}
-typedef struct {
+static void
+attachment_load_write_cb (GOutputStream *output_stream,
+ GAsyncResult *result,
+ LoadContext *load_context)
+{
EAttachment *attachment;
- char *file_name;
- char *uri;
- GtkWindow *parent; /* for error dialog */
-
- guint64 file_size; /* zero indicates unknown size */
- GInputStream *istream; /* read from here ... */
- GOutputStream *ostream; /* ...and write into this. */
- gboolean was_error;
GCancellable *cancellable;
+ GInputStream *input_stream;
+ gssize bytes_written;
+ GError *error = NULL;
+
+ bytes_written = g_output_stream_write_finish (
+ output_stream, result, &error);
- void *buffer; /* read into this, not more than buffer_size bytes */
- gsize buffer_size;
-} DownloadInfo;
+ if (attachment_load_check_for_error (load_context, error))
+ return;
+
+ attachment = load_context->attachment;
+ cancellable = attachment->priv->cancellable;
+ input_stream = load_context->input_stream;
+
+ attachment_progress_cb (
+ g_seekable_tell (G_SEEKABLE (output_stream)),
+ load_context->total_num_bytes, attachment);
+
+ if (bytes_written < load_context->bytes_read) {
+ g_memmove (
+ load_context->buffer,
+ load_context->buffer + bytes_written,
+ load_context->bytes_read - bytes_written);
+ load_context->bytes_read -= bytes_written;
+
+ g_output_stream_write_async (
+ output_stream,
+ load_context->buffer,
+ load_context->bytes_read,
+ G_PRIORITY_DEFAULT, cancellable,
+ (GAsyncReadyCallback) attachment_load_write_cb,
+ load_context);
+ } else
+ g_input_stream_read_async (
+ input_stream,
+ load_context->buffer,
+ sizeof (load_context->buffer),
+ G_PRIORITY_DEFAULT, cancellable,
+ (GAsyncReadyCallback) attachment_load_stream_read_cb,
+ load_context);
+}
static void
-download_info_free (DownloadInfo *download_info)
+attachment_load_stream_read_cb (GInputStream *input_stream,
+ GAsyncResult *result,
+ LoadContext *load_context)
{
- /* if there was an error, then free attachment too */
- if (download_info->was_error)
- g_object_unref (download_info->attachment);
+ EAttachment *attachment;
+ GCancellable *cancellable;
+ GOutputStream *output_stream;
+ gssize bytes_read;
+ GError *error = NULL;
- if (download_info->ostream)
- g_object_unref (download_info->ostream);
+ bytes_read = g_input_stream_read_finish (
+ input_stream, result, &error);
- if (download_info->istream)
- g_object_unref (download_info->istream);
+ if (attachment_load_check_for_error (load_context, error))
+ return;
- if (download_info->cancellable)
- g_object_unref (download_info->cancellable);
+ if (bytes_read == 0) {
+ attachment_load_finish (load_context);
+ return;
+ }
- g_free (download_info->file_name);
- g_free (download_info->uri);
- g_free (download_info->buffer);
- g_free (download_info);
+ attachment = load_context->attachment;
+ cancellable = attachment->priv->cancellable;
+ output_stream = load_context->output_stream;
+ load_context->bytes_read = bytes_read;
+
+ g_output_stream_write_async (
+ output_stream,
+ load_context->buffer,
+ load_context->bytes_read,
+ G_PRIORITY_DEFAULT, cancellable,
+ (GAsyncReadyCallback) attachment_load_write_cb,
+ load_context);
}
static void
-data_ready_cb (GObject *source_object, GAsyncResult *res, gpointer user_data)
+attachment_load_file_read_cb (GFile *file,
+ GAsyncResult *result,
+ LoadContext *load_context)
{
- DownloadInfo *download_info = (DownloadInfo *)user_data;
+ EAttachment *attachment;
+ GCancellable *cancellable;
+ GFileInputStream *input_stream;
+ GOutputStream *output_stream;
GError *error = NULL;
- gssize read;
- g_return_if_fail (download_info != NULL);
+ /* Input stream might be NULL, so don't use cast macro. */
+ input_stream = g_file_read_finish (file, result, &error);
+ load_context->input_stream = (GInputStream *) input_stream;
- if (g_cancellable_is_cancelled (download_info->cancellable)) {
- /* finish the operation and close both streams */
- g_input_stream_read_finish (G_INPUT_STREAM (source_object), res, NULL);
+ if (attachment_load_check_for_error (load_context, error))
+ return;
- g_output_stream_close (download_info->ostream, NULL, NULL);
- g_input_stream_close (download_info->istream, NULL, NULL);
+ /* Load the contents into a GMemoryOutputStream. */
+ output_stream = g_memory_output_stream_new (
+ NULL, 0, g_realloc, g_free);
+
+ attachment = load_context->attachment;
+ cancellable = attachment->priv->cancellable;
+ load_context->output_stream = output_stream;
+
+ g_input_stream_read_async (
+ load_context->input_stream,
+ load_context->buffer,
+ sizeof (load_context->buffer),
+ G_PRIORITY_DEFAULT, cancellable,
+ (GAsyncReadyCallback) attachment_load_stream_read_cb,
+ load_context);
+}
- /* The only way how to get this canceled is in EAttachment's finalize method,
- and because the download_info_free free's the attachment on error,
- then do not consider cancellation as an error. */
- download_info_free (download_info);
+static void
+attachment_load_query_info_cb (GFile *file,
+ GAsyncResult *result,
+ LoadContext *load_context)
+{
+ EAttachment *attachment;
+ GCancellable *cancellable;
+ GFileInfo *file_info;
+ GError *error = NULL;
+
+ attachment = load_context->attachment;
+ cancellable = attachment->priv->cancellable;
+
+ file_info = g_file_query_info_finish (file, result, &error);
+ attachment_set_file_info (attachment, file_info);
+ load_context->file_info = file_info;
+
+ if (attachment_load_check_for_error (load_context, error))
return;
+
+ load_context->total_num_bytes = g_file_info_get_size (file_info);
+
+ g_file_read_async (
+ file, G_PRIORITY_DEFAULT,
+ cancellable, (GAsyncReadyCallback)
+ attachment_load_file_read_cb, load_context);
+}
+
+static void
+attachment_load_from_mime_part (LoadContext *load_context)
+{
+ GFileInfo *file_info;
+ EAttachment *attachment;
+ GSimpleAsyncResult *simple;
+ CamelContentType *content_type;
+ CamelMimePart *mime_part;
+ const gchar *attribute;
+ const gchar *string;
+ gchar *allocated;
+ goffset size;
+
+ attachment = load_context->attachment;
+ mime_part = e_attachment_get_mime_part (attachment);
+
+ file_info = g_file_info_new ();
+ load_context->file_info = file_info;
+
+ content_type = camel_mime_part_get_content_type (mime_part);
+ allocated = camel_content_type_simple (content_type);
+ if (allocated != NULL) {
+ GIcon *icon;
+ gchar *cp;
+
+ /* GIO expects lowercase MIME types. */
+ for (cp = allocated; *cp != '\0'; cp++)
+ *cp = g_ascii_tolower (*cp);
+
+ /* Swap the MIME type for a content type. */
+ cp = g_content_type_from_mime_type (allocated);
+ g_free (allocated);
+ allocated = cp;
+
+ /* Use the MIME part's filename if we have to. */
+ if (g_content_type_is_unknown (allocated)) {
+ string = camel_mime_part_get_filename (mime_part);
+ if (string != NULL) {
+ g_free (allocated);
+ allocated = g_content_type_guess (
+ string, NULL, 0, NULL);
+ }
+ }
+
+ g_file_info_set_content_type (file_info, allocated);
+
+ icon = g_content_type_get_icon (allocated);
+ if (icon != NULL) {
+ g_file_info_set_icon (file_info, icon);
+ g_object_unref (icon);
+ }
}
+ g_free (allocated);
- read = g_input_stream_read_finish (G_INPUT_STREAM (source_object), res, &error);
+ string = camel_mime_part_get_filename (mime_part);
+ if (string == NULL)
+ /* Translators: Default attachment filename. */
+ string = _("attachment.dat");
+ g_file_info_set_display_name (file_info, string);
- if (!error)
- g_output_stream_write_all (download_info->ostream, download_info->buffer, read, NULL, download_info->cancellable, &error);
+ attribute = G_FILE_ATTRIBUTE_STANDARD_DESCRIPTION;
+ string = camel_mime_part_get_description (mime_part);
+ if (string != NULL)
+ g_file_info_set_attribute_string (
+ file_info, attribute, string);
- if (error) {
- download_info->was_error = error->domain != G_IO_ERROR || error->code != G_IO_ERROR_CANCELLED;
- if (download_info->was_error)
- e_error_run (download_info->parent, "mail-composer:no-attach", download_info->uri, error->message, NULL);
+ size = (goffset) camel_mime_part_get_content_size (mime_part);
+ g_file_info_set_size (file_info, size);
- g_error_free (error);
+ string = camel_mime_part_get_disposition (mime_part);
+ e_attachment_set_disposition (attachment, string);
+
+ attachment_set_file_info (attachment, file_info);
- download_info->attachment->cancellable = NULL;
- download_info_free (download_info);
+ /* Steal the result. */
+ simple = load_context->simple;
+ load_context->simple = NULL;
+
+ camel_object_ref (mime_part);
+ g_simple_async_result_set_op_res_gpointer (
+ simple, mime_part,
+ (GDestroyNotify) camel_object_unref);
+ g_simple_async_result_complete_in_idle (simple);
+
+ attachment_load_context_free (load_context);
+}
+
+void
+e_attachment_load_async (EAttachment *attachment,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ LoadContext *load_context;
+ GCancellable *cancellable;
+ CamelMimePart *mime_part;
+ GFile *file;
+
+ g_return_if_fail (E_IS_ATTACHMENT (attachment));
+ g_return_if_fail (callback != NULL);
+
+ if (e_attachment_get_loading (attachment)) {
+ g_simple_async_report_error_in_idle (
+ G_OBJECT (attachment), callback, user_data,
+ G_IO_ERROR, G_IO_ERROR_BUSY,
+ _("A load operation is already in progress"));
+ return;
+ }
+
+ if (e_attachment_get_saving (attachment)) {
+ g_simple_async_report_error_in_idle (
+ G_OBJECT (attachment), callback, user_data,
+ G_IO_ERROR, G_IO_ERROR_BUSY,
+ _("A save operation is already in progress"));
return;
}
- if (read == 0) {
- CamelException ex;
+ file = e_attachment_get_file (attachment);
+ mime_part = e_attachment_get_mime_part (attachment);
+ g_return_if_fail (file != NULL || mime_part != NULL);
- /* done with reading */
- g_output_stream_close (download_info->ostream, NULL, NULL);
- g_input_stream_close (download_info->istream, NULL, NULL);
+ load_context = attachment_load_context_new (
+ attachment, callback, user_data);
- download_info->attachment->cancellable = NULL;
+ cancellable = attachment->priv->cancellable;
+ g_cancellable_reset (cancellable);
- camel_exception_init (&ex);
- e_attachment_build_remote_file (download_info->file_name, download_info->attachment, "attachment", &ex);
+ if (file != NULL)
+ g_file_query_info_async (
+ file, ATTACHMENT_QUERY,
+ G_FILE_QUERY_INFO_NONE,G_PRIORITY_DEFAULT,
+ cancellable, (GAsyncReadyCallback)
+ attachment_load_query_info_cb, load_context);
- if (camel_exception_is_set (&ex)) {
- download_info->was_error = TRUE;
- e_error_run (download_info->parent, "mail-composer:no-attach", download_info->uri, camel_exception_get_description (&ex), NULL);
- camel_exception_clear (&ex);
- }
+ else if (mime_part != NULL)
+ attachment_load_from_mime_part (load_context);
+
+}
+
+gboolean
+e_attachment_load_finish (EAttachment *attachment,
+ GAsyncResult *result,
+ GError **error)
+{
+ GSimpleAsyncResult *simple;
+ CamelMimePart *mime_part;
+
+ g_return_val_if_fail (E_IS_ATTACHMENT (attachment), FALSE);
+ g_return_val_if_fail (G_IS_SIMPLE_ASYNC_RESULT (result), FALSE);
+
+ simple = G_SIMPLE_ASYNC_RESULT (result);
+ mime_part = g_simple_async_result_get_op_res_gpointer (simple);
+ if (mime_part != NULL)
+ e_attachment_set_mime_part (attachment, mime_part);
+ g_simple_async_result_propagate_error (simple, error);
+ g_object_unref (simple);
+
+ attachment_set_loading (attachment, FALSE);
+
+ return (mime_part != NULL);
+}
- download_info->attachment->percentage = -1;
- download_info->attachment->is_available_local = TRUE;
- g_signal_emit (download_info->attachment, signals[UPDATE], 0);
+void
+e_attachment_load_handle_error (EAttachment *attachment,
+ GAsyncResult *result,
+ GtkWindow *parent)
+{
+ GtkWidget *dialog;
+ GFileInfo *file_info;
+ GtkTreeRowReference *reference;
+ const gchar *display_name;
+ const gchar *primary_text;
+ GError *error = NULL;
- download_info_free (download_info);
+ g_return_if_fail (E_IS_ATTACHMENT (attachment));
+ g_return_if_fail (G_IS_ASYNC_RESULT (result));
+ g_return_if_fail (GTK_IS_WINDOW (parent));
+
+ if (e_attachment_load_finish (attachment, result, &error))
return;
- } else if (download_info->file_size) {
- download_info->attachment->percentage = read * 100 / download_info->file_size;
- download_info->file_size -= MIN (download_info->file_size, read);
- g_signal_emit (download_info->attachment, signals[UPDATE], 0);
- } else {
- download_info->attachment->percentage = 0;
- g_signal_emit (download_info->attachment, signals[UPDATE], 0);
+
+ /* XXX Calling EAttachmentStore functions from here violates
+ * the abstraction, but for now it's not hurting anything. */
+ reference = e_attachment_get_reference (attachment);
+ if (gtk_tree_row_reference_valid (reference)) {
+ GtkTreeModel *model;
+
+ model = gtk_tree_row_reference_get_model (reference);
+
+ e_attachment_store_remove_attachment (
+ E_ATTACHMENT_STORE (model), attachment);
}
- /* read next chunk */
- g_input_stream_read_async (download_info->istream, download_info->buffer, download_info->buffer_size, G_PRIORITY_DEFAULT, download_info->cancellable, data_ready_cb, download_info);
+ /* Ignore cancellations. */
+ if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
+ return;
+
+ file_info = e_attachment_get_file_info (attachment);
+
+ if (file_info != NULL)
+ display_name = g_file_info_get_display_name (file_info);
+ else
+ display_name = NULL;
+
+ if (display_name != NULL)
+ primary_text = g_strdup_printf (
+ _("Could not load '%s'"), display_name);
+ else
+ primary_text = g_strdup_printf (
+ _("Could not load the attachment"));
+
+ dialog = gtk_message_dialog_new_with_markup (
+ parent, GTK_DIALOG_DESTROY_WITH_PARENT,
+ GTK_MESSAGE_ERROR, GTK_BUTTONS_OK,
+ "<big><b>%s</b></big>", primary_text);
+
+ gtk_message_dialog_format_secondary_text (
+ GTK_MESSAGE_DIALOG (dialog), "%s", error->message);
+
+ gtk_dialog_run (GTK_DIALOG (dialog));
+
+ gtk_widget_destroy (dialog);
+ g_error_free (error);
+}
+
+/************************* e_attachment_open_async() *************************/
+
+typedef struct _OpenContext OpenContext;
+
+struct _OpenContext {
+ EAttachment *attachment;
+ GSimpleAsyncResult *simple;
+
+ GAppInfo *app_info;
+};
+
+static OpenContext *
+attachment_open_context_new (EAttachment *attachment,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ OpenContext *open_context;
+ GSimpleAsyncResult *simple;
+
+ simple = g_simple_async_result_new (
+ G_OBJECT (attachment), callback,
+ user_data, e_attachment_open_async);
+
+ open_context = g_slice_new0 (OpenContext);
+ open_context->attachment = g_object_ref (attachment);
+ open_context->simple = simple;
+
+ return open_context;
+}
+
+static void
+attachment_open_context_free (OpenContext *open_context)
+{
+ /* Do not free the GSimpleAsyncResult. */
+ g_object_unref (open_context->attachment);
+
+ if (open_context->app_info != NULL)
+ g_object_unref (open_context->app_info);
+
+ g_slice_free (OpenContext, open_context);
}
static gboolean
-download_to_local_path (DownloadInfo *download_info, CamelException *ex)
+attachment_open_check_for_error (OpenContext *open_context,
+ GError *error)
{
- GError *error = NULL;
- GFile *src = g_file_new_for_uri (download_info->uri);
- GFile *des = g_file_new_for_path (download_info->file_name);
- gboolean res = FALSE;
+ GSimpleAsyncResult *simple;
- g_return_val_if_fail (src != NULL && des != NULL, FALSE);
+ if (error == NULL)
+ return FALSE;
- download_info->ostream = G_OUTPUT_STREAM (g_file_replace (des, NULL, FALSE, G_FILE_CREATE_NONE, NULL, &error));
+ /* Steal the result. */
+ simple = open_context->simple;
+ open_context->simple = NULL;
- if (download_info->ostream && !error) {
- GFileInfo *fi;
+ g_simple_async_result_set_from_error (simple, error);
+ g_simple_async_result_complete (simple);
+ g_error_free (error);
- fi = g_file_query_info (src, G_FILE_ATTRIBUTE_STANDARD_SIZE, G_FILE_QUERY_INFO_NONE, NULL, NULL);
+ attachment_open_context_free (open_context);
- if (fi) {
- download_info->file_size = g_file_info_get_attribute_uint64 (fi, G_FILE_ATTRIBUTE_STANDARD_SIZE);
- g_object_unref (fi);
- } else {
- download_info->file_size = 0;
- }
+ return TRUE;
+}
- download_info->istream = G_INPUT_STREAM (g_file_read (src, NULL, &error));
+static void
+attachment_open_file (GFile *file,
+ OpenContext *open_context)
+{
+ GdkAppLaunchContext *context;
+ GSimpleAsyncResult *simple;
+ GList *file_list;
+ gboolean success;
+ GError *error = NULL;
- if (download_info->istream && !error) {
- download_info->cancellable = g_cancellable_new ();
- download_info->attachment->cancellable = download_info->cancellable;
- download_info->buffer_size = 10240; /* max 10KB chunk */
- download_info->buffer = g_malloc (sizeof (char) * download_info->buffer_size);
+ /* Steal the result. */
+ simple = open_context->simple;
+ open_context->simple = NULL;
- g_input_stream_read_async (download_info->istream, download_info->buffer, download_info->buffer_size, G_PRIORITY_DEFAULT, download_info->cancellable, data_ready_cb, download_info);
+ /* Find a default app based on content type. */
+ if (open_context->app_info == NULL) {
+ EAttachment *attachment;
+ GFileInfo *file_info;
+ const gchar *content_type;
- res = TRUE;
- }
+ attachment = open_context->attachment;
+ file_info = e_attachment_get_file_info (attachment);
+ if (file_info == NULL)
+ goto exit;
+
+ content_type = g_file_info_get_content_type (file_info);
+ if (content_type == NULL)
+ goto exit;
+
+ open_context->app_info = g_app_info_get_default_for_type (
+ content_type, FALSE);
}
- if (error) {
- /* propagate error */
- if (ex)
- camel_exception_set (ex, CAMEL_EXCEPTION_SYSTEM, error->message);
+ if (open_context->app_info == NULL)
+ goto exit;
+
+ context = gdk_app_launch_context_new ();
+ file_list = g_list_prepend (NULL, file);
+
+ success = g_app_info_launch (
+ open_context->app_info, file_list,
+ G_APP_LAUNCH_CONTEXT (context), &error);
+ g_simple_async_result_set_op_res_gboolean (simple, success);
+
+ g_list_free (file_list);
+ g_object_unref (context);
+
+exit:
+ if (error != NULL) {
+ g_simple_async_result_set_from_error (simple, error);
g_error_free (error);
- download_info->was_error = TRUE;
- download_info_free (download_info);
}
- g_object_unref (src);
- g_object_unref (des);
+ g_simple_async_result_complete (simple);
+ attachment_open_context_free (open_context);
+}
- return res;
+static void
+attachment_open_save_finished_cb (EAttachment *attachment,
+ GAsyncResult *result,
+ OpenContext *open_context)
+{
+ GFile *file;
+ GError *error = NULL;
+
+ file = e_attachment_save_finish (attachment, result, &error);
+
+ if (attachment_open_check_for_error (open_context, error))
+ return;
+
+ attachment_open_file (file, open_context);
+ g_object_unref (file);
}
-EAttachment *
-e_attachment_new_remote_file (GtkWindow *error_dlg_parent, const char *uri, const char *disposition, const char *path, CamelException *ex)
+static void
+attachment_open_save_temporary (OpenContext *open_context)
{
- EAttachment *new;
- DownloadInfo *download_info;
- CamelURL *url;
- char *base;
+ GFile *file;
+ gchar *template;
+ gchar *path;
+ GError *error = NULL;
- g_return_val_if_fail (uri != NULL, NULL);
+ errno = 0;
- url = camel_url_new (uri, NULL);
- base = g_path_get_basename (url->path);
- camel_url_free (url);
-
- new = g_object_new (E_TYPE_ATTACHMENT, NULL);
- new->editor_gui = NULL;
- new->body = NULL;
- new->size = 0;
- new->guessed_type = FALSE;
- new->cancellable = NULL;
- new->is_available_local = FALSE;
- new->percentage = 0;
- new->file_name = g_build_filename (path, base, NULL);
-
- g_free (base);
-
- download_info = g_new0 (DownloadInfo, 1);
- download_info->attachment = new;
- download_info->file_name = g_strdup (new->file_name);
- download_info->uri = g_strdup (uri);
- download_info->parent = error_dlg_parent;
- download_info->was_error = FALSE;
-
- /* it frees all on the error, so do not free it twice */
- if (!download_to_local_path (download_info, ex))
- return NULL;
+ /* XXX This could trigger a blocking temp directory cleanup. */
+ template = g_strdup_printf (PACKAGE "-%s-XXXXXX", g_get_user_name ());
+ path = e_mktemp (template);
+ g_free (template);
- return new;
+ /* XXX Let's hope errno got set properly. */
+ if (path == NULL)
+ g_set_error (
+ &error, G_FILE_ERROR,
+ g_file_error_from_errno (errno),
+ "%s", g_strerror (errno));
+
+ /* We already know if there's an error, but this does the cleanup. */
+ if (attachment_open_check_for_error (open_context, error))
+ return;
+
+ file = g_file_new_for_path (path);
+
+ g_free (path);
+
+ e_attachment_save_async (
+ open_context->attachment, file, (GAsyncReadyCallback)
+ attachment_open_save_finished_cb, open_context);
+
+ g_object_unref (file);
+}
+
+void
+e_attachment_open_async (EAttachment *attachment,
+ GAppInfo *app_info,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ OpenContext *open_context;
+ CamelMimePart *mime_part;
+ GFile *file;
+
+ g_return_if_fail (E_IS_ATTACHMENT (attachment));
+ g_return_if_fail (callback != NULL);
+
+ file = e_attachment_get_file (attachment);
+ mime_part = e_attachment_get_mime_part (attachment);
+ g_return_if_fail (file != NULL || mime_part != NULL);
+
+ open_context = attachment_open_context_new (
+ attachment, callback, user_data);
+
+ if (G_IS_APP_INFO (app_info))
+ open_context->app_info = g_object_ref (app_info);
+
+ /* If the attachment already references a GFile, we can launch
+ * the application directly. Otherwise we have to save the MIME
+ * part to a temporary file and launch the application from that. */
+ if (file != NULL) {
+ attachment_open_file (file, open_context);
+
+ } else if (mime_part != NULL)
+ attachment_open_save_temporary (open_context);
}
+gboolean
+e_attachment_open_finish (EAttachment *attachment,
+ GAsyncResult *result,
+ GError **error)
+{
+ GSimpleAsyncResult *simple;
+ gboolean success;
+
+ g_return_val_if_fail (E_IS_ATTACHMENT (attachment), FALSE);
+ g_return_val_if_fail (G_IS_SIMPLE_ASYNC_RESULT (result), FALSE);
+
+ simple = G_SIMPLE_ASYNC_RESULT (result);
+ success = g_simple_async_result_get_op_res_gboolean (simple);
+ g_simple_async_result_propagate_error (simple, error);
+ g_object_unref (simple);
+
+ return success;
+}
void
-e_attachment_build_remote_file (const char *file_name, EAttachment *attachment, const char *disposition, CamelException *ex)
+e_attachment_open_handle_error (EAttachment *attachment,
+ GAsyncResult *result,
+ GtkWindow *parent)
{
- CamelMimePart *part;
- CamelDataWrapper *wrapper;
- CamelStream *stream;
- struct stat statbuf;
- char *mime_type;
- char *filename;
- CamelURL *url;
-
- g_return_if_fail (file_name != NULL);
-
- if (g_stat (file_name, &statbuf) == -1) {
- camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM,
- _("Cannot attach file %s: %s"),
- file_name, g_strerror (errno));
- g_message ("Cannot attach file %s: %s\n", file_name, g_strerror (errno));
- return;
- }
+ GtkWidget *dialog;
+ GFileInfo *file_info;
+ const gchar *display_name;
+ const gchar *primary_text;
+ GError *error = 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);
- g_message ("Cannot attach file %s: not a regular file", file_name);
+ g_return_if_fail (E_IS_ATTACHMENT (attachment));
+ g_return_if_fail (G_IS_ASYNC_RESULT (result));
+ g_return_if_fail (GTK_IS_WINDOW (parent));
+
+ if (e_attachment_open_finish (attachment, result, &error))
return;
- }
- if (!(stream = camel_stream_fs_new_with_name (file_name, O_RDONLY, 0))) {
- camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM,
- _("Cannot attach file %s: %s"),
- file_name, g_strerror (errno));
+ /* Ignore cancellations. */
+ if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
return;
- }
- if ((mime_type = attachment_guess_mime_type (file_name))) {
- if (!g_ascii_strcasecmp (mime_type, "message/rfc822")) {
- wrapper = (CamelDataWrapper *) camel_mime_message_new ();
- } else {
- wrapper = camel_data_wrapper_new ();
- }
+ file_info = e_attachment_get_file_info (attachment);
- 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");
- }
+ if (file_info != NULL)
+ display_name = g_file_info_get_display_name (file_info);
+ else
+ display_name = NULL;
- camel_object_unref (stream);
+ if (display_name != NULL)
+ primary_text = g_strdup_printf (
+ _("Could not open '%s'"), display_name);
+ else
+ primary_text = g_strdup_printf (
+ _("Could not open the attachment"));
- part = camel_mime_part_new ();
- camel_medium_set_content_object (CAMEL_MEDIUM (part), wrapper);
- camel_object_unref (wrapper);
+ dialog = gtk_message_dialog_new_with_markup (
+ parent, GTK_DIALOG_DESTROY_WITH_PARENT,
+ GTK_MESSAGE_ERROR, GTK_BUTTONS_OK,
+ "<big><b>%s</b></big>", primary_text);
- if (attachment->disposition)
- camel_mime_part_set_disposition (part, "inline");
- else
- camel_mime_part_set_disposition (part, "attachment");
+ gtk_message_dialog_format_secondary_text (
+ GTK_MESSAGE_DIALOG (dialog), "%s", error->message);
- if (!attachment->file_name)
- filename = g_path_get_basename (file_name);
- else
- filename = g_path_get_basename (attachment->file_name);
+ gtk_dialog_run (GTK_DIALOG (dialog));
- camel_mime_part_set_filename (part, filename);
+ gtk_widget_destroy (dialog);
+ g_error_free (error);
+}
- if (attachment->description) {
- camel_mime_part_set_description (part, attachment->description);
- g_free (attachment->description);
- attachment->description = NULL;
- }
+/************************* e_attachment_save_async() *************************/
- attachment->editor_gui = NULL;
- attachment->body = part;
- attachment->size = statbuf.st_size;
- attachment->guessed_type = TRUE;
- g_free (attachment->file_name);
- attachment->file_name = filename;
+typedef struct _SaveContext SaveContext;
- url = camel_url_new ("file://", NULL);
- camel_url_set_path (url, file_name);
- attachment->store_uri = camel_url_to_string (url, 0);
- camel_url_free (url);
+struct _SaveContext {
+ EAttachment *attachment;
+ GSimpleAsyncResult *simple;
+
+ GFile *directory;
+ GFile *destination;
+ GInputStream *input_stream;
+ GOutputStream *output_stream;
+ goffset total_num_bytes;
+ gssize bytes_read;
+ gchar buffer[4096];
+ gint count;
+};
-}
+/* Forward Declaration */
+static void
+attachment_save_read_cb (GInputStream *input_stream,
+ GAsyncResult *result,
+ SaveContext *save_context);
+
+static SaveContext *
+attachment_save_context_new (EAttachment *attachment,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ SaveContext *save_context;
+ GSimpleAsyncResult *simple;
+ simple = g_simple_async_result_new (
+ G_OBJECT (attachment), callback,
+ user_data, e_attachment_save_async);
-/**
- * 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)
+ save_context = g_slice_new0 (SaveContext);
+ save_context->attachment = g_object_ref (attachment);
+ save_context->simple = simple;
+
+ attachment_set_saving (save_context->attachment, TRUE);
+
+ return save_context;
+}
+
+static void
+attachment_save_context_free (SaveContext *save_context)
{
- EAttachment *new;
+ /* Do not free the GSimpleAsyncResult. */
+ g_object_unref (save_context->attachment);
- g_return_val_if_fail (CAMEL_IS_MIME_PART (part), NULL);
+ if (save_context->directory != NULL)
+ g_object_unref (save_context->directory);
- new = g_object_new (E_TYPE_ATTACHMENT, NULL);
- new->editor_gui = NULL;
- camel_object_ref (part);
- new->body = part;
- new->guessed_type = FALSE;
- new->is_available_local = TRUE;
- new->size = camel_mime_part_get_content_size (part);
- new->file_name = g_strdup (camel_mime_part_get_filename(part));
+ if (save_context->destination != NULL)
+ g_object_unref (save_context->destination);
- return new;
+ if (save_context->input_stream != NULL)
+ g_object_unref (save_context->input_stream);
+
+ if (save_context->output_stream != NULL)
+ g_object_unref (save_context->output_stream);
+
+ g_slice_free (SaveContext, save_context);
}
-
-/* The attachment property dialog. */
+static gboolean
+attachment_save_check_for_error (SaveContext *save_context,
+ GError *error)
+{
+ GSimpleAsyncResult *simple;
-typedef struct {
- GtkWidget *dialog;
- GtkEntry *file_name_entry;
- GtkEntry *description_entry;
- GtkEntry *mime_type_entry;
- GtkToggleButton *disposition_checkbox;
+ if (error == NULL)
+ return FALSE;
+
+ /* Steal the result. */
+ simple = save_context->simple;
+ save_context->simple = NULL;
+
+ g_simple_async_result_set_from_error (simple, error);
+ g_simple_async_result_complete (simple);
+ g_error_free (error);
+
+ attachment_save_context_free (save_context);
+
+ return TRUE;
+}
+
+static GFile *
+attachment_save_new_candidate (SaveContext *save_context)
+{
+ GFile *candidate;
+ GFileInfo *file_info;
EAttachment *attachment;
-} DialogData;
+ const gchar *display_name;
+ gchar *basename;
+
+ attachment = save_context->attachment;
+ file_info = e_attachment_get_file_info (attachment);
+
+ if (file_info != NULL)
+ display_name = g_file_info_get_display_name (file_info);
+ if (display_name == NULL)
+ /* Translators: Default attachment filename. */
+ display_name = _("attachment.dat");
+
+ if (save_context->count == 0)
+ basename = g_strdup (display_name);
+ else {
+ GString *string;
+ const gchar *ext;
+ gsize length;
+
+ string = g_string_sized_new (strlen (display_name));
+ ext = g_utf8_strchr (display_name, -1, '.');
+
+ if (ext != NULL)
+ length = ext - display_name;
+ else
+ length = strlen (display_name);
+
+ g_string_append_len (string, display_name, length);
+ g_string_append_printf (string, " (%d)", save_context->count);
+ g_string_append (string, (ext != NULL) ? ext : "");
+
+ basename = g_string_free (string, FALSE);
+ }
+
+ save_context->count++;
+
+ candidate = g_file_get_child (save_context->directory, basename);
+
+ g_free (basename);
+
+ return candidate;
+}
static void
-destroy_dialog_data (DialogData *data)
+attachment_save_write_cb (GOutputStream *output_stream,
+ GAsyncResult *result,
+ SaveContext *save_context)
{
- g_free (data);
-}
+ EAttachment *attachment;
+ GCancellable *cancellable;
+ GInputStream *input_stream;
+ gssize bytes_written;
+ GError *error = NULL;
-/*
- * 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.
- */
+ bytes_written = g_output_stream_write_finish (
+ output_stream, result, &error);
+
+ if (attachment_save_check_for_error (save_context, error))
+ return;
+
+ attachment = save_context->attachment;
+ cancellable = attachment->priv->cancellable;
+ input_stream = save_context->input_stream;
+
+ if (bytes_written < save_context->bytes_read) {
+ g_memmove (
+ save_context->buffer,
+ save_context->buffer + bytes_written,
+ save_context->bytes_read - bytes_written);
+ save_context->bytes_read -= bytes_written;
+
+ g_output_stream_write_async (
+ output_stream,
+ save_context->buffer,
+ save_context->bytes_read,
+ G_PRIORITY_DEFAULT, cancellable,
+ (GAsyncReadyCallback) attachment_save_write_cb,
+ save_context);
+ } else
+ g_input_stream_read_async (
+ input_stream,
+ save_context->buffer,
+ sizeof (save_context->buffer),
+ G_PRIORITY_DEFAULT, cancellable,
+ (GAsyncReadyCallback) attachment_save_read_cb,
+ save_context);
+}
static void
-set_entry (GladeXML *xml, const char *widget_name, const char *value)
+attachment_save_read_cb (GInputStream *input_stream,
+ GAsyncResult *result,
+ SaveContext *save_context)
{
- GtkEntry *entry;
+ EAttachment *attachment;
+ GCancellable *cancellable;
+ GOutputStream *output_stream;
+ gssize bytes_read;
+ GError *error = NULL;
- 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 : "");
+ bytes_read = g_input_stream_read_finish (
+ input_stream, result, &error);
+
+ if (attachment_save_check_for_error (save_context, error))
+ return;
+
+ if (bytes_read == 0) {
+ GSimpleAsyncResult *simple;
+ GFile *destination;
+
+ /* Steal the result. */
+ simple = save_context->simple;
+ save_context->simple = NULL;
+
+ /* Steal the destination. */
+ destination = save_context->destination;
+ save_context->destination = NULL;
+
+ g_simple_async_result_set_op_res_gpointer (
+ simple, destination, (GDestroyNotify) g_object_unref);
+ g_simple_async_result_complete (simple);
+
+ attachment_save_context_free (save_context);
+
+ return;
+ }
+
+ attachment = save_context->attachment;
+ cancellable = attachment->priv->cancellable;
+ output_stream = save_context->output_stream;
+ save_context->bytes_read = bytes_read;
+
+ attachment_progress_cb (
+ g_seekable_tell (G_SEEKABLE (input_stream)),
+ save_context->total_num_bytes, attachment);
+
+ g_output_stream_write_async (
+ output_stream,
+ save_context->buffer,
+ save_context->bytes_read,
+ G_PRIORITY_DEFAULT, cancellable,
+ (GAsyncReadyCallback) attachment_save_write_cb,
+ save_context);
}
static void
-connect_widget (GladeXML *gui, const char *name, const char *signal_name,
- GCallback func, gpointer data)
+attachment_save_got_output_stream (SaveContext *save_context)
{
- GtkWidget *widget;
+ GCancellable *cancellable;
+ GInputStream *input_stream;
+ CamelDataWrapper *wrapper;
+ CamelMimePart *mime_part;
+ CamelStream *stream;
+ EAttachment *attachment;
+ GByteArray *buffer;
+
+ attachment = save_context->attachment;
+ cancellable = attachment->priv->cancellable;
+ mime_part = e_attachment_get_mime_part (attachment);
+
+ /* Decode the MIME part to an in-memory buffer. We have to do
+ * this because CamelStream is synchronous-only, and using threads
+ * is dangerous because CamelDataWrapper is not reentrant. */
+ buffer = g_byte_array_new ();
+ stream = camel_stream_mem_new ();
+ camel_stream_mem_set_byte_array (CAMEL_STREAM_MEM (stream), buffer);
+ wrapper = camel_medium_get_content_object (CAMEL_MEDIUM (mime_part));
+ camel_data_wrapper_decode_to_stream (wrapper, stream);
+ camel_object_unref (stream);
- widget = glade_xml_get_widget (gui, name);
- g_signal_connect (widget, signal_name, func, data);
+ /* Load the buffer into a GMemoryInputStream. */
+ input_stream = g_memory_input_stream_new_from_data (
+ buffer->data, (gssize) buffer->len,
+ (GDestroyNotify) g_free);
+ save_context->input_stream = input_stream;
+ save_context->total_num_bytes = (goffset) buffer->len;
+ g_byte_array_free (buffer, FALSE);
+
+ g_input_stream_read_async (
+ input_stream,
+ save_context->buffer,
+ sizeof (save_context->buffer),
+ G_PRIORITY_DEFAULT, cancellable,
+ (GAsyncReadyCallback) attachment_save_read_cb,
+ save_context);
}
static void
-close_cb (GtkWidget *widget, gpointer data)
+attachment_save_create_cb (GFile *destination,
+ GAsyncResult *result,
+ SaveContext *save_context)
{
EAttachment *attachment;
- DialogData *dialog_data;
+ GCancellable *cancellable;
+ GFileOutputStream *output_stream;
+ GError *error = NULL;
+
+ /* Output stream might be NULL, so don't use cast macro. */
+ output_stream = g_file_create_finish (destination, result, &error);
+ save_context->output_stream = (GOutputStream *) output_stream;
+
+ attachment = save_context->attachment;
+ cancellable = attachment->priv->cancellable;
+
+ if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_EXISTS)) {
+ destination = attachment_save_new_candidate (save_context);
- dialog_data = (DialogData *) data;
- attachment = dialog_data->attachment;
+ g_file_create_async (
+ destination, G_FILE_CREATE_NONE,
+ G_PRIORITY_DEFAULT, cancellable,
+ (GAsyncReadyCallback) attachment_save_create_cb,
+ save_context);
- gtk_widget_destroy (dialog_data->dialog);
- g_object_unref (attachment->editor_gui);
- attachment->editor_gui = NULL;
+ g_object_unref (destination);
+ g_error_free (error);
+ return;
+ }
+
+ if (attachment_save_check_for_error (save_context, error))
+ return;
+
+ save_context->destination = g_object_ref (destination);
+ attachment_save_got_output_stream (save_context);
+}
+
+static void
+attachment_save_replace_cb (GFile *destination,
+ GAsyncResult *result,
+ SaveContext *save_context)
+{
+ GFileOutputStream *output_stream;
+ GError *error = NULL;
- destroy_dialog_data (dialog_data);
+ /* Output stream might be NULL, so don't use cast macro. */
+ output_stream = g_file_replace_finish (destination, result, &error);
+ save_context->output_stream = (GOutputStream *) output_stream;
+
+ if (attachment_save_check_for_error (save_context, error))
+ return;
+
+ save_context->destination = g_object_ref (destination);
+ attachment_save_got_output_stream (save_context);
}
static void
-ok_cb (GtkWidget *widget, gpointer data)
+attachment_save_query_info_cb (GFile *destination,
+ GAsyncResult *result,
+ SaveContext *save_context)
{
- 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);
- 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 {
- g_free (attachment->description);
- attachment->description = g_strdup (str);
+ GCancellable *cancellable;
+ GFileInfo *file_info;
+ GFileType file_type;
+ GError *error = NULL;
+
+ attachment = save_context->attachment;
+ cancellable = attachment->priv->cancellable;
+
+ file_info = g_file_query_info_finish (destination, result, &error);
+
+ /* G_IO_ERROR_NOT_FOUND just means we're creating a new file. */
+ if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_NOT_FOUND)) {
+ g_error_free (error);
+ goto replace;
}
- 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_save_check_for_error (save_context, error))
+ return;
+
+ file_type = g_file_info_get_file_type (file_info);
+ g_object_unref (file_info);
+
+ if (file_type == G_FILE_TYPE_DIRECTORY) {
+ save_context->directory = g_object_ref (destination);
+ destination = attachment_save_new_candidate (save_context);
+
+ g_file_create_async (
+ destination, G_FILE_CREATE_NONE,
+ G_PRIORITY_DEFAULT, cancellable,
+ (GAsyncReadyCallback) attachment_save_create_cb,
+ save_context);
+
+ g_object_unref (destination);
+
+ return;
}
- 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);
+replace:
+ g_file_replace_async (
+ destination, NULL, FALSE,
+#if GLIB_CHECK_VERSION(2,20,0)
+ G_FILE_CREATE_REPLACE_DESTINATION,
+#else
+ G_FILE_CREATE_NONE,
+#endif
+ G_PRIORITY_DEFAULT, cancellable,
+ (GAsyncReadyCallback) attachment_save_replace_cb,
+ save_context);
+}
+
+void
+e_attachment_save_async (EAttachment *attachment,
+ GFile *destination,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ SaveContext *save_context;
+ GCancellable *cancellable;
+
+ g_return_if_fail (E_IS_ATTACHMENT (attachment));
+ g_return_if_fail (G_IS_FILE (destination));
+ g_return_if_fail (callback != NULL);
+
+ if (e_attachment_get_loading (attachment)) {
+ g_simple_async_report_error_in_idle (
+ G_OBJECT (attachment), callback, user_data,
+ G_IO_ERROR, G_IO_ERROR_BUSY,
+ _("A load operation is already in progress"));
+ return;
}
- changed (attachment);
- close_cb (widget, data);
+ if (e_attachment_get_saving (attachment)) {
+ g_simple_async_report_error_in_idle (
+ G_OBJECT (attachment), callback, user_data,
+ G_IO_ERROR, G_IO_ERROR_BUSY,
+ _("A save operation is already in progress"));
+ return;
+ }
+
+ if (e_attachment_get_mime_part (attachment) == NULL) {
+ g_simple_async_report_error_in_idle (
+ G_OBJECT (attachment), callback, user_data,
+ G_IO_ERROR, G_IO_ERROR_INVALID_ARGUMENT,
+ _("Attachment contents not loaded"));
+ return;
+ }
+
+ save_context = attachment_save_context_new (
+ attachment, callback, user_data);
+
+ cancellable = attachment->priv->cancellable;
+ g_cancellable_reset (cancellable);
+
+ /* First we need to know if destination is a directory. */
+ g_file_query_info_async (
+ destination, G_FILE_ATTRIBUTE_STANDARD_TYPE,
+ G_FILE_QUERY_INFO_NONE, G_PRIORITY_DEFAULT,
+ cancellable, (GAsyncReadyCallback)
+ attachment_save_query_info_cb, save_context);
}
-static void
-response_cb (GtkWidget *widget, gint response, gpointer data)
+GFile *
+e_attachment_save_finish (EAttachment *attachment,
+ GAsyncResult *result,
+ GError **error)
{
- if (response == GTK_RESPONSE_OK)
- ok_cb (widget, data);
- else
- close_cb (widget, data);
+ GSimpleAsyncResult *simple;
+ GFile *destination;
+
+ g_return_val_if_fail (E_IS_ATTACHMENT (attachment), FALSE);
+ g_return_val_if_fail (G_IS_SIMPLE_ASYNC_RESULT (result), FALSE);
+
+ simple = G_SIMPLE_ASYNC_RESULT (result);
+ destination = g_simple_async_result_get_op_res_gpointer (simple);
+ if (destination != NULL)
+ g_object_ref (destination);
+ g_simple_async_result_propagate_error (simple, error);
+ g_object_unref (simple);
+
+ attachment_set_saving (attachment, FALSE);
+
+ return destination;
}
void
-e_attachment_edit (EAttachment *attachment, GtkWidget *parent)
+e_attachment_save_handle_error (EAttachment *attachment,
+ GAsyncResult *result,
+ GtkWindow *parent)
{
- CamelContentType *content_type;
- const char *disposition;
- DialogData *dialog_data;
- GladeXML *editor_gui;
- GtkWidget *window;
- char *type;
- char *filename;
+ GFile *file;
+ GFileInfo *file_info;
+ GtkWidget *dialog;
+ const gchar *display_name;
+ const gchar *primary_text;
+ GError *error = NULL;
g_return_if_fail (E_IS_ATTACHMENT (attachment));
+ g_return_if_fail (G_IS_ASYNC_RESULT (result));
+ g_return_if_fail (GTK_IS_WINDOW (parent));
+
+ file = e_attachment_save_finish (attachment, result, &error);
- if (attachment->editor_gui != NULL) {
- window = glade_xml_get_widget (attachment->editor_gui, "dialog");
- gdk_window_show (window->window);
+ if (file != NULL) {
+ g_object_unref (file);
return;
}
- filename = g_build_filename (EVOLUTION_GLADEDIR, "e-attachment.glade", NULL);
- editor_gui = glade_xml_new (filename, NULL, NULL);
- g_free (filename);
-
- if (editor_gui == NULL) {
- g_warning ("Cannot load `e-attachment.glade'");
+ /* Ignore cancellations. */
+ if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
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);
- 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 && attachment->body) {
- 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);
- if ((type = attachment_guess_mime_type (attachment->file_name))) {
- set_entry (editor_gui, "mime_type_entry", type);
- g_free (type);
- } else {
- set_entry (editor_gui, "mime_type_entry", "");
- }
+ file_info = e_attachment_get_file_info (attachment);
- gtk_toggle_button_set_active (dialog_data->disposition_checkbox, attachment->disposition);
- }
+ if (file_info != NULL)
+ display_name = g_file_info_get_display_name (file_info);
+ else
+ display_name = NULL;
+
+ if (display_name != NULL)
+ primary_text = g_strdup_printf (
+ _("Could not save '%s'"), display_name);
+ else
+ primary_text = g_strdup_printf (
+ _("Could not save the attachment"));
+
+ dialog = gtk_message_dialog_new_with_markup (
+ parent, GTK_DIALOG_DESTROY_WITH_PARENT,
+ GTK_MESSAGE_ERROR, GTK_BUTTONS_OK,
+ "<big><b>%s</b></big>", primary_text);
+
+ gtk_message_dialog_format_secondary_text (
+ GTK_MESSAGE_DIALOG (dialog), "%s", error->message);
- connect_widget (editor_gui, "dialog", "response", (GCallback)response_cb, dialog_data);
+ gtk_dialog_run (GTK_DIALOG (dialog));
- /* make sure that when the parent gets hidden/closed that our windows also close */
- parent = gtk_widget_get_toplevel (parent);
- gtk_window_set_destroy_with_parent (GTK_WINDOW (dialog_data->dialog), TRUE);
+ gtk_widget_destroy (dialog);
+ g_error_free (error);
}
diff --git a/widgets/misc/e-attachment.h b/widgets/misc/e-attachment.h
index 7b45f24..934e1e0 100644
--- a/widgets/misc/e-attachment.h
+++ b/widgets/misc/e-attachment.h
@@ -1,4 +1,6 @@
/*
+ * e-attachment.h
+ *
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
@@ -13,91 +15,131 @@
* License along with the program; if not, see <http://www.gnu.org/licenses/>
*
*
- * Authors:
- * Ettore Perazzoli <ettore ximian com>
- * Srinivasa Ragavan <sragavan novell com>
- *
* Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
*
*/
-#ifndef __E_ATTACHMENT_H__
-#define __E_ATTACHMENT_H__
+#ifndef E_ATTACHMENT_H
+#define E_ATTACHMENT_H
-#include <gio/gio.h>
#include <gtk/gtk.h>
-#include <glade/glade-xml.h>
-#include <camel/camel-mime-part.h>
-#include <camel/camel-exception.h>
#include <camel/camel-cipher-context.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;
+#include <camel/camel-mime-part.h>
+#include <camel/camel-mime-message.h>
+#include <camel/camel-multipart.h>
+
+/* Standard GObject macros */
+#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(cls) \
+ (G_TYPE_CHECK_CLASS_CAST \
+ ((cls), E_TYPE_ATTACHMENT, EAttachmentClass))
+#define E_IS_ATTACHMENT(obj) \
+ (G_TYPE_CHECK_INSTANCE_TYPE \
+ ((obj), E_TYPE_ATTACHMENT))
+#define E_IS_ATTACHMENT_CLASS(cls) \
+ (G_TYPE_CHECK_CLASS_TYPE \
+ ((cls), E_TYPE_ATTACHMENT))
+#define E_ATTACHMENT_GET_CLASS(obj) \
+ (G_TYPE_INSTANCE_GET_CLASS \
+ ((obj), E_TYPE_ATTACHMENT, EAttachmentClass))
+
+G_BEGIN_DECLS
+
+typedef struct _EAttachment EAttachment;
+typedef struct _EAttachmentClass EAttachmentClass;
+typedef struct _EAttachmentPrivate EAttachmentPrivate;
struct _EAttachment {
GObject parent;
-
- GladeXML *editor_gui;
-
- CamelMimePart *body;
- gboolean guessed_type;
- gulong size;
-
- GdkPixbuf *pixbuf_cache;
-
- GCancellable *cancellable;
-
- gboolean is_available_local;
- int percentage;
- char *file_name;
- char *description;
- gboolean disposition;
- int index;
- char *store_uri;
-
- /* Status of signed/encrypted attachments */
- camel_cipher_validity_sign_t sign;
- camel_cipher_validity_encrypt_t encrypt;
+ EAttachmentPrivate *priv;
};
struct _EAttachmentClass {
GObjectClass parent_class;
-
- void (*changed) (EAttachment *attachment);
- void (*update) (EAttachment *attachment, char *msg);
};
-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 (GtkWindow *error_dlg_parent,
- const char *url,
- const char *disposition,
- const char *path,
- 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__ */
+GType e_attachment_get_type (void);
+EAttachment * e_attachment_new (void);
+EAttachment * e_attachment_new_for_path (const gchar *path);
+EAttachment * e_attachment_new_for_uri (const gchar *uri);
+EAttachment * e_attachment_new_for_message (CamelMimeMessage *message);
+void e_attachment_add_to_multipart (EAttachment *attachment,
+ CamelMultipart *multipart,
+ const gchar *default_charset);
+void e_attachment_cancel (EAttachment *attachment);
+gboolean e_attachment_get_can_show (EAttachment *attachment);
+void e_attachment_set_can_show (EAttachment *attachment,
+ gboolean can_show);
+const gchar * e_attachment_get_disposition (EAttachment *attachment);
+void e_attachment_set_disposition (EAttachment *attachment,
+ const gchar *disposition);
+GFile * e_attachment_get_file (EAttachment *attachment);
+void e_attachment_set_file (EAttachment *attachment,
+ GFile *file);
+GFileInfo * e_attachment_get_file_info (EAttachment *attachment);
+gboolean e_attachment_get_loading (EAttachment *attachment);
+CamelMimePart * e_attachment_get_mime_part (EAttachment *attachment);
+void e_attachment_set_mime_part (EAttachment *attachment,
+ CamelMimePart *mime_part);
+gint e_attachment_get_percent (EAttachment *attachment);
+GtkTreeRowReference *
+ e_attachment_get_reference (EAttachment *attachment);
+void e_attachment_set_reference (EAttachment *attachment,
+ GtkTreeRowReference *reference);
+gboolean e_attachment_get_saving (EAttachment *attachment);
+gboolean e_attachment_get_shown (EAttachment *attachment);
+void e_attachment_set_shown (EAttachment *attachment,
+ gboolean shown);
+camel_cipher_validity_encrypt_t
+ e_attachment_get_encrypted (EAttachment *attachment);
+void e_attachment_set_encrypted (EAttachment *attachment,
+ camel_cipher_validity_encrypt_t encrypted);
+camel_cipher_validity_sign_t
+ e_attachment_get_signed (EAttachment *attachment);
+void e_attachment_set_signed (EAttachment *attachment,
+ camel_cipher_validity_sign_t signed_);
+const gchar * e_attachment_get_description (EAttachment *attachment);
+const gchar * e_attachment_get_thumbnail_path (EAttachment *attachment);
+gboolean e_attachment_is_rfc822 (EAttachment *attachment);
+GList * e_attachment_list_apps (EAttachment *attachment);
+
+/* Asynchronous Operations */
+void e_attachment_load_async (EAttachment *attachment,
+ GAsyncReadyCallback callback,
+ gpointer user_data);
+gboolean e_attachment_load_finish (EAttachment *attachment,
+ GAsyncResult *result,
+ GError **error);
+void e_attachment_open_async (EAttachment *attachment,
+ GAppInfo *app_info,
+ GAsyncReadyCallback callback,
+ gpointer user_data);
+gboolean e_attachment_open_finish (EAttachment *attachment,
+ GAsyncResult *result,
+ GError **error);
+void e_attachment_save_async (EAttachment *attachment,
+ GFile *destination,
+ GAsyncReadyCallback callback,
+ gpointer user_data);
+GFile * e_attachment_save_finish (EAttachment *attachment,
+ GAsyncResult *result,
+ GError **error);
+
+/* Handy GAsyncReadyCallback Functions */
+void e_attachment_load_handle_error (EAttachment *attachment,
+ GAsyncResult *result,
+ GtkWindow *parent);
+void e_attachment_open_handle_error (EAttachment *attachment,
+ GAsyncResult *result,
+ GtkWindow *parent);
+void e_attachment_save_handle_error (EAttachment *attachment,
+ GAsyncResult *result,
+ GtkWindow *parent);
+
+G_END_DECLS
+
+#endif /* E_ATTACHMENT_H */
diff --git a/widgets/misc/e-expander.c b/widgets/misc/e-expander.c
deleted file mode 100644
index 7715987..0000000
--- a/widgets/misc/e-expander.c
+++ /dev/null
@@ -1,1341 +0,0 @@
-/*
- * GTK - The GIMP Toolkit
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) version 3.
- *
- * 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
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with the program; if not, see <http://www.gnu.org/licenses/>
- *
- *
- * Authors:
- * Mark McLoughlin <mark skynet ie>
- *
- * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
- * Copyright (C) 2003 Sun Microsystems, Inc.
- *
- */
-
-#include <config.h>
-
-#include "e-expander.h"
-#include "ea-widgets.h"
-
-#include <gdk/gdkkeysyms.h>
-
-#define DEFAULT_EXPANDER_SIZE 10
-#define DEFAULT_EXPANDER_SPACING 2
-
-/* ESTUFF */
-#ifndef _
-#define _(x) (x)
-#endif
-#define E_EXPANDER_GET_PRIVATE(expander) ((EExpanderPrivate *)g_object_get_data (G_OBJECT (expander), "e-expander-priv"))
-
-enum {
- PROP_0,
- PROP_EXPANDED,
- PROP_LABEL,
- PROP_USE_UNDERLINE,
- PROP_PADDING,
- PROP_LABEL_WIDGET
-};
-
-typedef struct {
- GtkWidget *label_widget;
- gint spacing;
-
- GtkExpanderStyle expander_style;
- guint animation_timeout;
-
- guint expanded : 1;
- guint use_underline : 1;
- guint button_down : 1;
-} EExpanderPrivate;
-
-static void e_expander_class_init (EExpanderClass *klass);
-static void e_expander_init (EExpander *expander);
-
-static void e_expander_set_property (GObject *object,
- guint prop_id,
- const GValue *value,
- GParamSpec *pspec);
-static void e_expander_get_property (GObject *object,
- guint prop_id,
- GValue *value,
- GParamSpec *pspec);
-
-static void e_expander_destroy (GtkObject *object);
-
-static void e_expander_realize (GtkWidget *widget);
-static void e_expander_size_request (GtkWidget *widget,
- GtkRequisition *requisition);
-static void e_expander_size_allocate (GtkWidget *widget,
- GtkAllocation *allocation);
-static void e_expander_map (GtkWidget *widget);
-static gboolean e_expander_expose (GtkWidget *widget,
- GdkEventExpose *event);
-static gboolean e_expander_button_press (GtkWidget *widget,
- GdkEventButton *event);
-static gboolean e_expander_button_release (GtkWidget *widget,
- GdkEventButton *event);
-static gboolean e_expander_motion_notify (GtkWidget *widget,
- GdkEventMotion *event);
-static gboolean e_expander_enter_notify (GtkWidget *widget,
- GdkEventCrossing *event);
-static gboolean e_expander_leave_notify (GtkWidget *widget,
- GdkEventCrossing *event);
-static gboolean e_expander_focus (GtkWidget *widget,
- GtkDirectionType direction);
-
-static void e_expander_add (GtkContainer *container,
- GtkWidget *widget);
-static void e_expander_remove (GtkContainer *container,
- GtkWidget *widget);
-static void e_expander_forall (GtkContainer *container,
- gboolean include_internals,
- GtkCallback callback,
- gpointer callback_data);
-
-static void e_expander_activate (EExpander *expander);
-
-static GtkBinClass *parent_class = NULL;
-
-GType
-e_expander_get_type (void)
-{
- static GType expander_type = 0;
-
- if (!expander_type)
- {
- static const GTypeInfo expander_info =
- {
- sizeof (EExpanderClass),
- NULL, /* base_init */
- NULL, /* base_finalize */
- (GClassInitFunc) e_expander_class_init,
- NULL, /* class_finalize */
- NULL, /* class_data */
- sizeof (EExpander),
- 0, /* n_preallocs */
- (GInstanceInitFunc) e_expander_init,
- };
-
- expander_type = g_type_register_static (GTK_TYPE_BIN,
- "EExpander",
- &expander_info, 0);
- }
-
- return expander_type;
-}
-
-static void
-e_expander_class_init (EExpanderClass *klass)
-{
- GObjectClass *gobject_class;
- GtkObjectClass *gtkobject_class;
- GtkWidgetClass *widget_class;
- GtkContainerClass *container_class;
-
- parent_class = g_type_class_peek_parent (klass);
-
- gobject_class = (GObjectClass *) klass;
- gtkobject_class = (GtkObjectClass *) klass;
- widget_class = (GtkWidgetClass *) klass;
- container_class = (GtkContainerClass *) klass;
-
- gobject_class->set_property = e_expander_set_property;
- gobject_class->get_property = e_expander_get_property;
-
- gtkobject_class->destroy = e_expander_destroy;
-
- widget_class->realize = e_expander_realize;
- widget_class->size_request = e_expander_size_request;
- widget_class->size_allocate = e_expander_size_allocate;
- widget_class->map = e_expander_map;
- widget_class->expose_event = e_expander_expose;
- widget_class->button_press_event = e_expander_button_press;
- widget_class->button_release_event = e_expander_button_release;
- widget_class->motion_notify_event = e_expander_motion_notify;
- widget_class->enter_notify_event = e_expander_enter_notify;
- widget_class->leave_notify_event = e_expander_leave_notify;
- widget_class->focus = e_expander_focus;
-
- container_class->add = e_expander_add;
- container_class->remove = e_expander_remove;
- container_class->forall = e_expander_forall;
-
- klass->activate = e_expander_activate;
-
- /* ESTUFF g_type_class_add_private (klass, sizeof (EExpanderPrivate)); */
-
- g_object_class_install_property (gobject_class,
- PROP_EXPANDED,
- g_param_spec_boolean ("expanded",
- _("Expanded"),
- _("Whether or not the expander is expanded"),
- FALSE,
- G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
-
- g_object_class_install_property (gobject_class,
- PROP_LABEL,
- g_param_spec_string ("label",
- _("Label"),
- _("Text of the expander's label"),
- NULL,
- G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
-
- g_object_class_install_property (gobject_class,
- PROP_USE_UNDERLINE,
- g_param_spec_boolean ("use_underline",
- _("Use underline"),
- _("If set, an underline in the text indicates the next character should be used for the mnemonic accelerator key"),
- FALSE,
- G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
-
- g_object_class_install_property (gobject_class,
- PROP_PADDING,
- g_param_spec_int ("spacing",
- _("Spacing"),
- _("Space to put between the label and the child"),
- 0,
- G_MAXINT,
- 0,
- G_PARAM_READWRITE));
-
- g_object_class_install_property (gobject_class,
- PROP_LABEL_WIDGET,
- g_param_spec_object ("label_widget",
- _("Label widget"),
- _("A widget to display in place of the usual expander label"),
- GTK_TYPE_WIDGET,
- G_PARAM_READWRITE));
-
- gtk_widget_class_install_style_property (widget_class,
- g_param_spec_int ("expander-size",
- _("Expander Size"),
- _("Size of the expander arrow"),
- 0,
- G_MAXINT,
- DEFAULT_EXPANDER_SIZE,
- G_PARAM_READABLE));
-
- gtk_widget_class_install_style_property (widget_class,
- g_param_spec_int ("expander-spacing",
- _("Indicator Spacing"),
- _("Spacing around expander arrow"),
- 0,
- G_MAXINT,
- DEFAULT_EXPANDER_SPACING,
- G_PARAM_READABLE));
-
- widget_class->activate_signal =
- g_signal_new ("activate",
- G_TYPE_FROM_CLASS (gobject_class),
- G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
- G_STRUCT_OFFSET (EExpanderClass, activate),
- NULL, NULL,
- g_cclosure_marshal_VOID__VOID,
- G_TYPE_NONE, 0);
-
- e_expander_a11y_init();
-}
-
-static void
-e_expander_init (EExpander *expander)
-{
- EExpanderPrivate *priv;
-
- /* ESTUFF */
- priv = g_new0 (EExpanderPrivate, 1);
- g_object_set_data_full (G_OBJECT (expander), "e-expander-priv", priv, g_free);
-
- /* ESTUFF priv = E_EXPANDER_GET_PRIVATE (expander); */
-
- GTK_WIDGET_SET_FLAGS (expander, GTK_CAN_FOCUS);
- GTK_WIDGET_UNSET_FLAGS (expander, GTK_NO_WINDOW);
-
- priv->label_widget = NULL;
- priv->spacing = 0;
-
- priv->expander_style = GTK_EXPANDER_COLLAPSED;
- priv->animation_timeout = 0;
-
- priv->expanded = FALSE;
- priv->use_underline = FALSE;
- priv->button_down = FALSE;
-
-}
-
-static void
-e_expander_set_property (GObject *object,
- guint prop_id,
- const GValue *value,
- GParamSpec *pspec)
-{
- EExpander *expander = E_EXPANDER (object);
-
- switch (prop_id)
- {
- case PROP_EXPANDED:
- e_expander_set_expanded (expander, g_value_get_boolean (value));
- break;
- case PROP_LABEL:
- e_expander_set_label (expander, g_value_get_string (value));
- break;
- case PROP_USE_UNDERLINE:
- e_expander_set_use_underline (expander, g_value_get_boolean (value));
- break;
- case PROP_PADDING:
- e_expander_set_spacing (expander, g_value_get_int (value));
- break;
- case PROP_LABEL_WIDGET:
- e_expander_set_label_widget (expander, g_value_get_object (value));
- break;
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
- break;
- }
-}
-
-static void
-e_expander_get_property (GObject *object,
- guint prop_id,
- GValue *value,
- GParamSpec *pspec)
-{
- EExpander *expander = E_EXPANDER (object);
- EExpanderPrivate *priv;
-
- priv = E_EXPANDER_GET_PRIVATE (expander);
-
- switch (prop_id)
- {
- case PROP_EXPANDED:
- g_value_set_boolean (value, priv->expanded);
- break;
- case PROP_LABEL:
- g_value_set_string (value, e_expander_get_label (expander));
- break;
- case PROP_USE_UNDERLINE:
- g_value_set_boolean (value, priv->use_underline);
- break;
- case PROP_PADDING:
- g_value_set_int (value, priv->spacing);
- break;
- case PROP_LABEL_WIDGET:
- g_value_set_object (value,
- priv->label_widget ?
- G_OBJECT (priv->label_widget) : NULL);
- break;
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
- break;
- }
-}
-
-static void
-e_expander_destroy (GtkObject *object)
-{
- EExpander *expander = E_EXPANDER (object);
- EExpanderPrivate *priv;
-
- priv = E_EXPANDER_GET_PRIVATE (expander);
-
- if (priv->animation_timeout)
- g_source_remove (priv->animation_timeout);
- priv->animation_timeout = 0;
-
- GTK_OBJECT_CLASS (parent_class)->destroy (object);
-}
-
-static void
-e_expander_realize (GtkWidget *widget)
-{
- GdkWindowAttr attributes;
- gint attributes_mask;
- gint border_width;
-
- GTK_WIDGET_SET_FLAGS (widget, GTK_REALIZED);
-
- border_width = GTK_CONTAINER (widget)->border_width;
-
- attributes.x = widget->allocation.x + border_width;
- attributes.y = widget->allocation.y + border_width;
- attributes.width = widget->allocation.width - 2 * border_width;
- attributes.height = widget->allocation.height - 2 * border_width;
- attributes.window_type = GDK_WINDOW_CHILD;
- attributes.wclass = GDK_INPUT_OUTPUT;
- attributes.visual = gtk_widget_get_visual (widget);
- attributes.colormap = gtk_widget_get_colormap (widget);
- attributes.event_mask = gtk_widget_get_events (widget) |
- GDK_POINTER_MOTION_MASK |
- GDK_POINTER_MOTION_HINT_MASK |
- GDK_BUTTON_PRESS_MASK |
- GDK_BUTTON_RELEASE_MASK |
- GDK_EXPOSURE_MASK |
- GDK_ENTER_NOTIFY_MASK |
- GDK_LEAVE_NOTIFY_MASK;
-
- attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP;
-
- widget->window = gdk_window_new (gtk_widget_get_parent_window (widget),
- &attributes, attributes_mask);
- gdk_window_set_user_data (widget->window, widget);
-
- widget->style = gtk_style_attach (widget->style, widget->window);
- gtk_style_set_background (widget->style, widget->window, GTK_STATE_NORMAL);
-}
-
-static void
-e_expander_size_request (GtkWidget *widget,
- GtkRequisition *requisition)
-{
- EExpander *expander;
- GtkBin *bin;
- EExpanderPrivate *priv;
- gint border_width;
- gint expander_size;
- gint expander_spacing;
- gboolean interior_focus;
- gint focus_width;
- gint focus_pad;
-
- expander = E_EXPANDER (widget);
- bin = GTK_BIN (widget);
-
- priv = E_EXPANDER_GET_PRIVATE (expander);
-
- border_width = GTK_CONTAINER (widget)->border_width;
-
- gtk_widget_style_get (widget,
- "interior-focus", &interior_focus,
- "focus-line-width", &focus_width,
- "focus-padding", &focus_pad,
- "expander-size", &expander_size,
- "expander-spacing", &expander_spacing,
- NULL);
-
- requisition->width = expander_size + 2 * expander_spacing +
- 2 * focus_width + 2 * focus_pad;
- requisition->height = interior_focus ? (2 * focus_width + 2 * focus_pad) : 0;
-
- if (priv->label_widget && GTK_WIDGET_VISIBLE (priv->label_widget))
- {
- GtkRequisition label_requisition;
-
- gtk_widget_size_request (priv->label_widget, &label_requisition);
-
- requisition->width += label_requisition.width;
- requisition->height += label_requisition.height;
- }
-
- requisition->height = MAX (expander_size + 2 * expander_spacing, requisition->height);
-
- if (!interior_focus)
- requisition->height += 2 * focus_width + 2 * focus_pad;
-
- if (bin->child && GTK_WIDGET_VISIBLE (bin->child))
- {
- GtkRequisition child_requisition;
-
- gtk_widget_size_request (bin->child, &child_requisition);
-
- if (!interior_focus)
- child_requisition.width += 2 * focus_width + 2 * focus_pad;
-
- requisition->width = MAX (requisition->width, child_requisition.width);
- requisition->height += child_requisition.height + priv->spacing;
- }
-
- requisition->width += 2 * border_width;
- requisition->height += 2 * border_width + 2 * priv->spacing;
-}
-
-static void
-e_expander_size_allocate (GtkWidget *widget,
- GtkAllocation *allocation)
-{
- EExpander *expander;
- GtkBin *bin;
- EExpanderPrivate *priv;
- GtkRequisition child_requisition;
- gboolean child_visible = FALSE;
- gint border_width;
- gint expander_size;
- gint expander_spacing;
- gboolean interior_focus;
- gint focus_width;
- gint focus_pad;
- gint label_height;
-
- expander = E_EXPANDER (widget);
- bin = GTK_BIN (widget);
-
- priv = E_EXPANDER_GET_PRIVATE (expander);
-
- border_width = GTK_CONTAINER (widget)->border_width;
-
- gtk_widget_style_get (widget,
- "interior-focus", &interior_focus,
- "focus-line-width", &focus_width,
- "focus-padding", &focus_pad,
- "expander-size", &expander_size,
- "expander-spacing", &expander_spacing,
- NULL);
-
- child_requisition.width = 0;
- child_requisition.height = 0;
- if (bin->child && GTK_WIDGET_VISIBLE (bin->child))
- {
- child_visible = TRUE;
- gtk_widget_get_child_requisition (bin->child, &child_requisition);
- }
-
- widget->allocation = *allocation;
-
- if (GTK_WIDGET_REALIZED (widget))
- gdk_window_move_resize (widget->window,
- allocation->x + border_width,
- allocation->y + border_width,
- MAX (allocation->width - 2 * border_width, 0),
- MAX (allocation->height - 2 * border_width, 0));
-
- if (priv->label_widget && GTK_WIDGET_VISIBLE (priv->label_widget))
- {
- GtkAllocation label_allocation;
- GtkRequisition label_requisition;
- gboolean ltr;
-
- gtk_widget_get_child_requisition (priv->label_widget, &label_requisition);
-
- ltr = gtk_widget_get_direction (widget) != GTK_TEXT_DIR_RTL;
-
- label_allocation.x = focus_width + focus_pad;
- if (ltr)
- label_allocation.x += expander_size + 2 * expander_spacing;
- label_allocation.y = priv->spacing + focus_width + focus_pad;
-
- label_allocation.width = MIN (label_requisition.width,
- allocation->width - 2 * border_width -
- expander_size - 2 * expander_spacing -
- 2 * focus_width - 2 * focus_pad);
- label_allocation.width = MAX (label_allocation.width, 1);
-
- label_allocation.height = MIN (label_requisition.height,
- allocation->height - 2 * border_width -
- 2 * priv->spacing -
- 2 * focus_width - 2 * focus_pad -
- child_requisition.height -
- (child_visible ? priv->spacing : 0));
- label_allocation.height = MAX (label_allocation.height, 1);
-
- gtk_widget_size_allocate (priv->label_widget, &label_allocation);
-
- label_height = label_allocation.height;
- }
- else
- {
- label_height = 0;
- }
-
- if (child_visible)
- {
- GtkAllocation child_allocation;
- gint top_height;
-
- top_height = MAX (2 * expander_spacing + expander_size,
- label_height +
- (interior_focus ? 2 * focus_width + 2 * focus_pad : 0));
-
- child_allocation.x = 0;
- child_allocation.y = 2 * priv->spacing + top_height;
-
- if (!interior_focus)
- {
- child_allocation.x += focus_width + focus_pad;
- child_allocation.y += focus_width + focus_pad;
- }
-
- child_allocation.width = allocation->width - 2 * border_width -
- (!interior_focus ? 2 * focus_width + 2 * focus_pad : 0);
- child_allocation.width = MAX (child_allocation.width, 1);
-
- child_allocation.height = allocation->height - top_height -
- 2 * border_width -
- 3 * priv->spacing -
- (!interior_focus ? 2 * focus_width + 2 * focus_pad : 0);
- child_allocation.height = MAX (child_allocation.height, 1);
-
- gtk_widget_size_allocate (bin->child, &child_allocation);
- }
-}
-
-static void
-e_expander_map (GtkWidget *widget)
-{
- EExpanderPrivate *priv;
-
- priv = E_EXPANDER_GET_PRIVATE (widget);
-
- if (priv->label_widget)
- gtk_widget_map (priv->label_widget);
-
- GTK_WIDGET_CLASS (parent_class)->map (widget);
-}
-
-static GdkRectangle
-get_expander_bounds (EExpander *expander)
-{
- GtkWidget *widget;
- EExpanderPrivate *priv;
- GdkRectangle bounds;
- gint border_width;
- gint expander_size;
- gint expander_spacing;
- gboolean interior_focus;
- gint focus_width;
- gint focus_pad;
- gboolean ltr;
-
- widget = GTK_WIDGET (expander);
-
- priv = E_EXPANDER_GET_PRIVATE (expander);
-
- border_width = GTK_CONTAINER (expander)->border_width;
-
- gtk_widget_style_get (widget,
- "interior-focus", &interior_focus,
- "focus-line-width", &focus_width,
- "focus-padding", &focus_pad,
- "expander-size", &expander_size,
- "expander-spacing", &expander_spacing,
- NULL);
-
- ltr = gtk_widget_get_direction (widget) != GTK_TEXT_DIR_RTL;
-
-
- if (ltr)
- bounds.x = expander_spacing;
- else
- bounds.x = widget->allocation.width - 2 * border_width -
- expander_spacing - expander_size;
-
- if (priv->label_widget && GTK_WIDGET_VISIBLE (priv->label_widget))
- {
- GtkAllocation label_allocation;
-
- label_allocation = priv->label_widget->allocation;
-
- if (expander_size < label_allocation.height)
- bounds.y = label_allocation.y + (label_allocation.height - expander_size) / 2;
- else
- bounds.y = priv->spacing + expander_spacing;
- }
- else
- {
- bounds.y = priv->spacing + expander_spacing;
- }
-
- if (!interior_focus)
- {
- if (ltr)
- bounds.x += focus_width + focus_pad;
- else
- bounds.x -= focus_width + focus_pad;
- bounds.y += focus_width + focus_pad;
- }
-
- bounds.width = bounds.height = expander_size;
-
- return bounds;
-}
-
-static void
-e_expander_paint (EExpander *expander)
-{
- GtkWidget *widget;
- EExpanderPrivate *priv;
- gint x, y;
- GtkStateType state;
- GdkRectangle clip;
-
- widget = GTK_WIDGET (expander);
-
- priv = E_EXPANDER_GET_PRIVATE (expander);
-
- clip = get_expander_bounds (expander);
-
- x = clip.x + clip.width / 2;
- y = clip.y + clip.height / 2;
-
- state = widget->state;
- if (state != GTK_STATE_PRELIGHT)
- state = GTK_STATE_NORMAL;
-
- gtk_paint_expander (widget->style,
- widget->window,
- state,
- &clip,
- widget,
- "expander",
- x,
- y,
- priv->expander_style);
-}
-
-static void
-e_expander_paint_focus (EExpander *expander,
- GdkRectangle *area)
-{
- GtkWidget *widget;
- EExpanderPrivate *priv;
- gint x, y, width, height;
- gboolean interior_focus;
- gint focus_width;
- gint focus_pad;
- gint expander_size;
- gint expander_spacing;
- gboolean ltr;
-
- widget = GTK_WIDGET (expander);
-
- priv = E_EXPANDER_GET_PRIVATE (expander);
-
- gtk_widget_style_get (widget,
- "interior-focus", &interior_focus,
- "focus-line-width", &focus_width,
- "focus-padding", &focus_pad,
- "expander-size", &expander_size,
- "expander-spacing", &expander_spacing,
- NULL);
-
- ltr = gtk_widget_get_direction (widget) != GTK_TEXT_DIR_RTL;
-
- if (interior_focus)
- {
- if (ltr)
- x = expander_spacing * 2 + expander_size;
- else
- x = 0;
- y = priv->spacing;
-
- width = height = 2 * focus_pad + 2 * focus_width;
-
- if (priv->label_widget && GTK_WIDGET_VISIBLE (priv->label_widget))
- {
- GtkAllocation label_allocation = priv->label_widget->allocation;
-
- width += label_allocation.width;
- height += label_allocation.height;
- }
- }
- else
- {
- x = y = 0;
- width = widget->allocation.width - 2 * GTK_CONTAINER (widget)->border_width;
- height = widget->allocation.height - 2 * GTK_CONTAINER (widget)->border_width;
- }
-
- gtk_paint_focus (widget->style, widget->window, GTK_WIDGET_STATE (widget),
- area, widget, "expander",
- x, y, width, height);
-}
-
-static gboolean
-e_expander_expose (GtkWidget *widget,
- GdkEventExpose *event)
-{
- if (GTK_WIDGET_DRAWABLE (widget))
- {
- EExpander *expander = E_EXPANDER (widget);
-
- e_expander_paint (expander);
-
- if (GTK_WIDGET_HAS_FOCUS (expander))
- e_expander_paint_focus (expander, &event->area);
-
- GTK_WIDGET_CLASS (parent_class)->expose_event (widget, event);
- }
-
- return FALSE;
-}
-
-static gboolean
-is_in_expander_panel (EExpander *expander,
- GdkWindow *window,
- gint x,
- gint y)
-{
- GtkWidget *widget;
- GdkRectangle area;
-
- widget = GTK_WIDGET (expander);
-
- area = get_expander_bounds (expander);
-
- area.x = 0;
- area.width = widget->allocation.width;
-
- if (widget->window == window)
- {
- if (x >= area.x && x <= (area.x + area.width) &&
- y >= area.y && y <= (area.y + area.height))
- return TRUE;
- }
-
- return FALSE;
-}
-
-static gboolean
-e_expander_button_press (GtkWidget *widget,
- GdkEventButton *event)
-{
- EExpander *expander = E_EXPANDER (widget);
- EExpanderPrivate *priv;
-
- priv = E_EXPANDER_GET_PRIVATE (expander);
-
- if (event->button == 1 && !priv->button_down)
- {
- if (is_in_expander_panel (expander, event->window, event->x, event->y))
- {
- priv->button_down = TRUE;
- return TRUE;
- }
- }
-
- return FALSE;
-}
-
-static gboolean
-e_expander_button_release (GtkWidget *widget,
- GdkEventButton *event)
-{
- EExpander *expander = E_EXPANDER (widget);
- EExpanderPrivate *priv;
-
- priv = E_EXPANDER_GET_PRIVATE (expander);
-
- if (event->button == 1 && priv->button_down)
- {
- g_signal_emit_by_name (expander, "activate");
-
- priv->button_down = FALSE;
- return TRUE;
- }
-
- return FALSE;
-}
-
-static void
-e_expander_maybe_prelight (EExpander *expander)
-{
- GtkWidget *widget;
- EExpanderPrivate *priv;
- GtkStateType state = GTK_STATE_NORMAL;
-
- widget = GTK_WIDGET (expander);
-
- priv = E_EXPANDER_GET_PRIVATE (expander);
-
- if (!priv->button_down)
- {
- gint x, y;
-
- gdk_window_get_pointer (widget->window, &x, &y, NULL);
-
- if (is_in_expander_panel (expander, widget->window, x, y))
- state = GTK_STATE_PRELIGHT;
- }
-
- gtk_widget_set_state (widget, state);
-}
-
-static gboolean
-e_expander_motion_notify (GtkWidget *widget,
- GdkEventMotion *event)
-{
- e_expander_maybe_prelight (E_EXPANDER (widget));
-
- return FALSE;
-}
-
-static gboolean
-e_expander_enter_notify (GtkWidget *widget,
- GdkEventCrossing *event)
-{
- e_expander_maybe_prelight (E_EXPANDER (widget));
-
- return FALSE;
-}
-
-static gboolean
-e_expander_leave_notify (GtkWidget *widget,
- GdkEventCrossing *event)
-{
- gtk_widget_set_state (widget, GTK_STATE_NORMAL);
-
- return FALSE;
-}
-
-static gboolean
-focus_child_in (GtkWidget *widget,
- GtkDirectionType direction)
-{
- GtkWidget *child = gtk_bin_get_child (GTK_BIN (widget));
-
- if (!child)
- return FALSE;
-
- return gtk_widget_child_focus (child, direction);
-}
-
-static gboolean
-e_expander_focus (GtkWidget *widget,
- GtkDirectionType direction)
-{
- EExpanderPrivate *priv;
- GtkWidget *old_focus_child;
- gboolean widget_is_focus;
- gboolean label_can_focus;
-
- priv = E_EXPANDER_GET_PRIVATE (widget);
-
- widget_is_focus = gtk_widget_is_focus (widget);
- old_focus_child = GTK_CONTAINER (widget)->focus_child;
- label_can_focus = priv->label_widget && GTK_WIDGET_CAN_FOCUS (priv->label_widget);
-
- if (old_focus_child && old_focus_child == priv->label_widget)
- {
- switch (direction)
- {
- case GTK_DIR_TAB_BACKWARD:
- case GTK_DIR_LEFT:
- case GTK_DIR_UP:
- gtk_widget_grab_focus (widget);
- return TRUE;
- case GTK_DIR_DOWN:
- case GTK_DIR_TAB_FORWARD:
- case GTK_DIR_RIGHT:
- return focus_child_in (widget, direction);
- }
- }
- else if (old_focus_child)
- {
- if (gtk_widget_child_focus (old_focus_child, direction))
- return TRUE;
-
- switch (direction)
- {
- case GTK_DIR_TAB_BACKWARD:
- case GTK_DIR_LEFT:
- case GTK_DIR_UP:
- if (label_can_focus)
- gtk_widget_grab_focus (priv->label_widget);
- else
- gtk_widget_grab_focus (widget);
- return TRUE;
- case GTK_DIR_DOWN:
- case GTK_DIR_TAB_FORWARD:
- case GTK_DIR_RIGHT:
- return FALSE;
- }
- }
- else if (widget_is_focus)
- {
- switch (direction)
- {
- case GTK_DIR_TAB_BACKWARD:
- case GTK_DIR_LEFT:
- case GTK_DIR_UP:
- return FALSE;
- case GTK_DIR_DOWN:
- case GTK_DIR_TAB_FORWARD:
- case GTK_DIR_RIGHT:
- if (label_can_focus)
- {
- gtk_widget_grab_focus (priv->label_widget);
- return TRUE;
- }
-
- return focus_child_in (widget, direction);
- }
- }
- else
- {
- switch (direction)
- {
- case GTK_DIR_DOWN:
- case GTK_DIR_TAB_FORWARD:
- case GTK_DIR_TAB_BACKWARD:
- gtk_widget_grab_focus (widget);
- return TRUE;
- case GTK_DIR_UP:
- case GTK_DIR_LEFT:
- case GTK_DIR_RIGHT:
- if (!focus_child_in (widget, direction))
- {
- gtk_widget_grab_focus (widget);
- }
- return TRUE;
- }
- }
-
- g_return_val_if_reached(FALSE);
-}
-
-static void
-e_expander_add (GtkContainer *container,
- GtkWidget *widget)
-{
- GTK_CONTAINER_CLASS (parent_class)->add (container, widget);
-
- g_object_set (G_OBJECT (widget),
- "visible", E_EXPANDER_GET_PRIVATE (container)->expanded,
- NULL);
-}
-
-static void
-e_expander_remove (GtkContainer *container,
- GtkWidget *widget)
-{
- EExpander *expander = E_EXPANDER (container);
-
- if (E_EXPANDER_GET_PRIVATE (expander)->label_widget == widget)
- e_expander_set_label_widget (expander, NULL);
- else
- GTK_CONTAINER_CLASS (parent_class)->remove (container, widget);
-}
-
-static void
-e_expander_forall (GtkContainer *container,
- gboolean include_internals,
- GtkCallback callback,
- gpointer callback_data)
-{
- GtkBin *bin = GTK_BIN (container);
- EExpanderPrivate *priv;
-
- priv = E_EXPANDER_GET_PRIVATE (container);
-
- if (bin->child)
- (* callback) (bin->child, callback_data);
-
- if (priv->label_widget)
- (* callback) (priv->label_widget, callback_data);
-}
-
-static void
-e_expander_activate (EExpander *expander)
-{
- e_expander_set_expanded (expander,
- !E_EXPANDER_GET_PRIVATE (expander)->expanded);
-}
-
-GtkWidget *
-e_expander_new (const gchar *label)
-{
- return g_object_new (E_TYPE_EXPANDER, "label", label, NULL);
-}
-
-GtkWidget *
-e_expander_new_with_mnemonic (const gchar *label)
-{
- return g_object_new (E_TYPE_EXPANDER,
- "label", label,
- "use_underline", TRUE,
- NULL);
-}
-
-static gboolean
-e_expander_animation_timeout (EExpander *expander)
-{
- EExpanderPrivate *priv;
- GdkRectangle area;
- gboolean finish = FALSE;
-
- priv = E_EXPANDER_GET_PRIVATE (expander);
-
- if (GTK_WIDGET_REALIZED (expander))
- {
- area = get_expander_bounds (expander);
- gdk_window_invalidate_rect (GTK_WIDGET (expander)->window, &area, TRUE);
- }
-
- if (priv->expanded)
- {
- if (priv->expander_style == GTK_EXPANDER_COLLAPSED)
- {
- priv->expander_style = GTK_EXPANDER_SEMI_EXPANDED;
- }
- else
- {
- priv->expander_style = GTK_EXPANDER_EXPANDED;
- finish = TRUE;
- }
- }
- else
- {
- if (priv->expander_style == GTK_EXPANDER_EXPANDED)
- {
- priv->expander_style = GTK_EXPANDER_SEMI_COLLAPSED;
- }
- else
- {
- priv->expander_style = GTK_EXPANDER_COLLAPSED;
- finish = TRUE;
- }
- }
-
- if (finish)
- {
- priv->animation_timeout = 0;
- g_object_set (G_OBJECT (GTK_BIN (expander)->child),
- "visible", priv->expanded,
- NULL);
- }
-
- return !finish;
-}
-
-static void
-e_expander_start_animation (EExpander *expander)
-{
- EExpanderPrivate *priv;
-
- priv = E_EXPANDER_GET_PRIVATE (expander);
-
- if (priv->animation_timeout)
- g_source_remove (priv->animation_timeout);
-
- priv->animation_timeout =
- g_timeout_add (50,
- (GSourceFunc) e_expander_animation_timeout,
- expander);
-}
-
-void
-e_expander_set_expanded (EExpander *expander,
- gboolean expanded)
-{
- EExpanderPrivate *priv;
-
- g_return_if_fail (E_IS_EXPANDER (expander));
-
- priv = E_EXPANDER_GET_PRIVATE (expander);
-
- expanded = expanded != FALSE;
-
- if (priv->expanded != expanded)
- {
- priv->expanded = expanded;
-
- if (GTK_WIDGET_VISIBLE (expander))
- e_expander_start_animation (expander);
-
- else if (GTK_BIN (expander)->child)
- {
- priv->expander_style = expanded ? GTK_EXPANDER_EXPANDED :
- GTK_EXPANDER_COLLAPSED;
- g_object_set (G_OBJECT (GTK_BIN (expander)->child),
- "visible", priv->expanded,
- NULL);
- }
-
- gtk_widget_queue_resize (GTK_WIDGET (expander));
-
- g_object_notify (G_OBJECT (expander), "expanded");
- }
-}
-
-gboolean
-e_expander_get_expanded (EExpander *expander)
-{
- g_return_val_if_fail (E_IS_EXPANDER (expander), FALSE);
-
- return E_EXPANDER_GET_PRIVATE (expander)->expanded;
-}
-
-void
-e_expander_set_spacing (EExpander *expander,
- gint spacing)
-{
- EExpanderPrivate *priv;
-
- g_return_if_fail (E_IS_EXPANDER (expander));
- g_return_if_fail (spacing >= 0);
-
- priv = E_EXPANDER_GET_PRIVATE (expander);
-
- if (priv->spacing != spacing)
- {
- priv->spacing = spacing;
-
- gtk_widget_queue_resize (GTK_WIDGET (expander));
-
- g_object_notify (G_OBJECT (expander), "spacing");
- }
-}
-
-gint
-e_expander_get_spacing (EExpander *expander)
-{
- g_return_val_if_fail (E_IS_EXPANDER (expander), 0);
-
- return E_EXPANDER_GET_PRIVATE (expander)->spacing;
-}
-
-void
-e_expander_set_label (EExpander *expander,
- const gchar *label)
-{
- g_return_if_fail (E_IS_EXPANDER (expander));
-
- if (!label)
- {
- e_expander_set_label_widget (expander, NULL);
- }
- else
- {
- GtkWidget *child;
-
- child = gtk_label_new (label);
- gtk_label_set_use_underline (GTK_LABEL (child),
- E_EXPANDER_GET_PRIVATE (expander)->use_underline);
- gtk_widget_show (child);
-
- e_expander_set_label_widget (expander, child);
- }
-
- g_object_notify (G_OBJECT (expander), "label");
-}
-
-/**
- * e_expander_get_label:
- * @expander: a #EExpander
- *
- * If the expander's label widget is a #GtkLabel, return the
- * text in the label widget. (The frame will have a #GtkLabel
- * for the label widget if a non-%NULL argument was passed
- * to e_expander_new().)
- *
- * Return value: the text in the label, or %NULL if there
- * was no label widget or the lable widget was not
- * a #GtkLabel. This string is owned by GTK+ and
- * must not be modified or freed.
- **/
-G_CONST_RETURN char *
-e_expander_get_label (EExpander *expander)
-{
- EExpanderPrivate *priv;
-
- g_return_val_if_fail (E_IS_EXPANDER (expander), NULL);
-
- priv = E_EXPANDER_GET_PRIVATE (expander);
-
- if (priv->label_widget && GTK_IS_LABEL (priv->label_widget))
- return gtk_label_get_text (GTK_LABEL (priv->label_widget));
- else
- return NULL;
-}
-
-void
-e_expander_set_use_underline (EExpander *expander,
- gboolean use_underline)
-{
- EExpanderPrivate *priv;
-
- g_return_if_fail (E_IS_EXPANDER (expander));
-
- priv = E_EXPANDER_GET_PRIVATE (expander);
-
- use_underline = use_underline != FALSE;
-
- if (priv->use_underline != use_underline)
- {
- priv->use_underline = use_underline;
-
- if (priv->label_widget && GTK_IS_LABEL (priv->label_widget))
- gtk_label_set_use_underline (GTK_LABEL (priv->label_widget), use_underline);
-
- g_object_notify (G_OBJECT (expander), "use_underline");
- }
-}
-
-gboolean
-e_expander_get_use_underline (EExpander *expander)
-{
- g_return_val_if_fail (E_IS_EXPANDER (expander), FALSE);
-
- return E_EXPANDER_GET_PRIVATE (expander)->use_underline;
-}
-
-/**
- * e_expander_set_label_widget:
- * @expander: a #EExpander
- * @label_widget: the new label widget
- *
- * Set the label widget for the expander. This is the widget
- * that will appear embedded alongside the expander arrow.
- **/
-void
-e_expander_set_label_widget (EExpander *expander,
- GtkWidget *label_widget)
-{
- EExpanderPrivate *priv;
- gboolean need_resize = FALSE;
-
- g_return_if_fail (E_IS_EXPANDER (expander));
- g_return_if_fail (label_widget == NULL || GTK_IS_WIDGET (label_widget));
- g_return_if_fail (label_widget == NULL || label_widget->parent == NULL);
-
- priv = E_EXPANDER_GET_PRIVATE (expander);
-
- if (priv->label_widget == label_widget)
- return;
-
- if (priv->label_widget)
- {
- need_resize = GTK_WIDGET_VISIBLE (priv->label_widget);
- gtk_widget_unparent (priv->label_widget);
- }
-
- priv->label_widget = label_widget;
-
- if (label_widget)
- {
- priv->label_widget = label_widget;
- gtk_widget_set_parent (label_widget, GTK_WIDGET (expander));
- need_resize |= GTK_WIDGET_VISIBLE (label_widget);
- }
-
- if (GTK_WIDGET_VISIBLE (expander) && need_resize)
- gtk_widget_queue_resize (GTK_WIDGET (expander));
-
- g_object_notify (G_OBJECT (expander), "label_widget");
-}
-
-/**
- * e_expander_get_label_widget:
- * @expander: a #EExpander
- *
- * Retrieves the label widget for the frame. See
- * e_expander_set_label_widget().
- *
- * Return value: the label widget, or %NULL if there is none.
- **/
-GtkWidget *
-e_expander_get_label_widget (EExpander *expander)
-{
- g_return_val_if_fail (E_IS_EXPANDER (expander), NULL);
-
- return E_EXPANDER_GET_PRIVATE (expander)->label_widget;
-}
diff --git a/widgets/misc/e-expander.h b/widgets/misc/e-expander.h
deleted file mode 100644
index 6ddb680..0000000
--- a/widgets/misc/e-expander.h
+++ /dev/null
@@ -1,82 +0,0 @@
-/*
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) version 3.
- *
- * 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
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with the program; if not, see <http://www.gnu.org/licenses/>
- *
- *
- * Authors:
- * Mark McLoughlin <mark skynet ie>
- *
- * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
- * Copyright (C) 2003 Sun Microsystems, Inc.
- *
- */
-
-#ifndef _E_EXPANDER_H_
-#define _E_EXPANDER_H_
-
-#include <gtk/gtk.h>
-
-G_BEGIN_DECLS
-
-#define E_TYPE_EXPANDER (e_expander_get_type ())
-#define E_EXPANDER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), E_TYPE_EXPANDER, EExpander))
-#define E_EXPANDER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), E_TYPE_EXPANDER, EExpanderClass))
-#define E_IS_EXPANDER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), E_TYPE_EXPANDER))
-#define E_IS_EXPANDER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), E_TYPE_EXPANDER))
-#define E_EXPANDER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), E_TYPE_EXPANDER, EExpanderClass))
-/* ESTUFF #define E_EXPANDER_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), E_TYPE_EXPANDER, EExpanderPrivate)) */
-
-typedef struct _EExpander EExpander;
-typedef struct _EExpanderClass EExpanderClass;
-
-struct _EExpander
-{
- GtkBin bin;
-};
-
-struct _EExpanderClass
-{
- GtkBinClass parent_class;
-
- void (* activate) (EExpander *expander);
-};
-
-GType e_expander_get_type (void);
-
-GtkWidget *e_expander_new (const gchar *label);
-GtkWidget *e_expander_new_with_mnemonic (const gchar *label);
-
-void e_expander_set_expanded (EExpander *expander,
- gboolean expanded);
-gboolean e_expander_get_expanded (EExpander *expander);
-
-/* Spacing between the expander/label and the child */
-void e_expander_set_spacing (EExpander *expander,
- gint spacing);
-gint e_expander_get_spacing (EExpander *expander);
-
-void e_expander_set_label (EExpander *expander,
- const gchar *label);
-G_CONST_RETURN gchar *e_expander_get_label (EExpander *expander);
-
-void e_expander_set_use_underline (EExpander *expander,
- gboolean use_underline);
-gboolean e_expander_get_use_underline (EExpander *expander);
-
-void e_expander_set_label_widget (EExpander *expander,
- GtkWidget *label_widget);
-GtkWidget *e_expander_get_label_widget (EExpander *expander);
-
-G_END_DECLS
-
-#endif /* _E_EXPANDER_H_ */
diff --git a/widgets/text/Makefile.am b/widgets/text/Makefile.am
index df2b02c..565ec4e 100644
--- a/widgets/text/Makefile.am
+++ b/widgets/text/Makefile.am
@@ -5,6 +5,7 @@ endif
INCLUDES = \
-I$(top_srcdir) \
-I$(top_srcdir)/widgets \
+ $(E_UTIL_CFLAGS) \
$(GNOME_PLATFORM_CFLAGS) \
-DG_LOG_DOMAIN=\"e-text\"
@@ -30,5 +31,6 @@ libetext_la_LIBADD = \
$(top_builddir)/e-util/libeutil.la \
$(top_builddir)/a11y/libevolution-a11y.la \
$(top_builddir)/widgets/table/libetable.la \
+ $(E_UTIL_LIBS) \
$(GNOME_PLATFORM_LIBS) \
$(REGEX_LIBS)
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]