[evolution/wip/webkit2] Finish the second leftover (of 2) from the EAttachmentBar changes (Do not access EAttachmentStore fr



commit 57075d5c68f223de2e9aac1fc4731446f84a310f
Author: Milan Crha <mcrha redhat com>
Date:   Thu Jun 2 19:57:05 2016 +0200

    Finish the second leftover (of 2) from the EAttachmentBar changes (Do not access EAttachmentStore from 
EAttachment)
    
    Storing the GtkTreeReference on the attachment works only if
    the attachment is inside a single store. When it is in multiple
    stores, then the changes done on the attachment "view-related"
    properties are propagated to all windows, which is not as it
    should be. Also the GtkTreeReference is overwritten with the latest
    store, thus it breaks other things too.

 calendar/gui/e-comp-editor-page-attachments.c |   12 +-
 e-util/e-attachment-store.c                   |  174 +++++++++-
 e-util/e-attachment-store.h                   |    4 +
 e-util/e-attachment-view.c                    |  242 +------------
 e-util/e-attachment.c                         |  303 +++++------------
 e-util/e-attachment.h                         |   29 +-
 em-format/e-mail-formatter-attachment.c       |    2 +-
 em-format/e-mail-parser-text-plain.c          |    2 +-
 em-format/e-mail-parser.c                     |    2 +-
 mail/e-mail-display.c                         |  478 ++++++++++++++++++++----
 mail/e-mail-request.c                         |   30 +-
 11 files changed, 693 insertions(+), 585 deletions(-)
---
diff --git a/calendar/gui/e-comp-editor-page-attachments.c b/calendar/gui/e-comp-editor-page-attachments.c
index 4b6276f..3d1db6d 100644
--- a/calendar/gui/e-comp-editor-page-attachments.c
+++ b/calendar/gui/e-comp-editor-page-attachments.c
@@ -177,17 +177,7 @@ ecep_attachments_attachment_loaded_cb (EAttachment *attachment,
        }
 
        if (!e_attachment_load_finish (attachment, result, &error)) {
-               GtkTreeRowReference *reference;
-
-               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);
-               }
+               g_signal_emit_by_name (attachment, "load-failed", NULL);
 
                /* Ignore cancellations. */
                if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) {
diff --git a/e-util/e-attachment-store.c b/e-util/e-attachment-store.c
index ab6247d..85fa19a 100644
--- a/e-util/e-attachment-store.c
+++ b/e-util/e-attachment-store.c
@@ -67,6 +67,143 @@ G_DEFINE_TYPE (
        GTK_TYPE_LIST_STORE)
 
 static void
+attachment_store_update_file_info_cb (EAttachment *attachment,
+                                     const gchar *caption,
+                                     const gchar *content_type,
+                                     const gchar *description,
+                                     gint64 size,
+                                     gpointer user_data)
+{
+       EAttachmentStore *store = user_data;
+       GtkTreeIter iter;
+
+       g_return_if_fail (E_IS_ATTACHMENT (attachment));
+       g_return_if_fail (E_IS_ATTACHMENT_STORE (store));
+
+       if (e_attachment_store_find_attachment_iter (store, attachment, &iter)) {
+               gtk_list_store_set (
+                       GTK_LIST_STORE (store), &iter,
+                       E_ATTACHMENT_STORE_COLUMN_CAPTION, caption,
+                       E_ATTACHMENT_STORE_COLUMN_CONTENT_TYPE, content_type,
+                       E_ATTACHMENT_STORE_COLUMN_DESCRIPTION, description,
+                       E_ATTACHMENT_STORE_COLUMN_SIZE, size,
+                       -1);
+       }
+}
+
+static void
+attachment_store_update_icon_cb (EAttachment *attachment,
+                                GIcon *icon,
+                                gpointer user_data)
+{
+       EAttachmentStore *store = user_data;
+       GtkTreeIter iter;
+
+       g_return_if_fail (E_IS_ATTACHMENT (attachment));
+       g_return_if_fail (E_IS_ATTACHMENT_STORE (store));
+
+       if (e_attachment_store_find_attachment_iter (store, attachment, &iter)) {
+               gtk_list_store_set (
+                       GTK_LIST_STORE (store), &iter,
+                       E_ATTACHMENT_STORE_COLUMN_ICON, icon,
+                       -1);
+       }
+}
+
+static void
+attachment_store_update_progress_cb (EAttachment *attachment,
+                                    gboolean loading,
+                                    gboolean saving,
+                                    gint percent,
+                                    gpointer user_data)
+{
+       EAttachmentStore *store = user_data;
+       GtkTreeIter iter;
+
+       g_return_if_fail (E_IS_ATTACHMENT (attachment));
+       g_return_if_fail (E_IS_ATTACHMENT_STORE (store));
+
+       if (e_attachment_store_find_attachment_iter (store, attachment, &iter)) {
+               gtk_list_store_set (
+                       GTK_LIST_STORE (store), &iter,
+                       E_ATTACHMENT_STORE_COLUMN_LOADING, loading,
+                       E_ATTACHMENT_STORE_COLUMN_SAVING, saving,
+                       E_ATTACHMENT_STORE_COLUMN_PERCENT, percent,
+                       -1);
+       }
+}
+
+static void
+attachment_store_load_failed_cb (EAttachment *attachment,
+                                gpointer user_data)
+{
+       EAttachmentStore *store = user_data;
+
+       g_return_if_fail (E_IS_ATTACHMENT (attachment));
+       g_return_if_fail (E_IS_ATTACHMENT_STORE (store));
+
+       e_attachment_store_remove_attachment (store, attachment);
+}
+
+static void
+attachment_store_attachment_notify_cb (GObject *attachment,
+                                      GParamSpec *param,
+                                      gpointer user_data)
+{
+       EAttachmentStore *store = user_data;
+
+       g_return_if_fail (E_IS_ATTACHMENT (attachment));
+       g_return_if_fail (param != NULL);
+       g_return_if_fail (E_IS_ATTACHMENT_STORE (store));
+
+       if (g_str_equal (param->name, "loading")) {
+               g_object_notify (G_OBJECT (store), "num-loading");
+       } else if (g_str_equal (param->name, "file-info")) {
+               g_object_notify (G_OBJECT (store), "total-size");
+       }
+}
+
+static void
+attachment_store_attachment_added (EAttachmentStore *store,
+                                  EAttachment *attachment)
+{
+       g_return_if_fail (E_IS_ATTACHMENT_STORE (store));
+       g_return_if_fail (E_IS_ATTACHMENT (attachment));
+
+       g_signal_connect (attachment, "update-file-info",
+               G_CALLBACK (attachment_store_update_file_info_cb), store);
+       g_signal_connect (attachment, "update-icon",
+               G_CALLBACK (attachment_store_update_icon_cb), store);
+       g_signal_connect (attachment, "update-progress",
+               G_CALLBACK (attachment_store_update_progress_cb), store);
+       g_signal_connect (attachment, "load-failed",
+               G_CALLBACK (attachment_store_load_failed_cb), store);
+       g_signal_connect (attachment, "notify",
+               G_CALLBACK (attachment_store_attachment_notify_cb), store);
+
+       e_attachment_update_store_columns (attachment);
+}
+
+static void
+attachment_store_attachment_removed (EAttachmentStore *store,
+                                    EAttachment *attachment)
+{
+       g_return_if_fail (E_IS_ATTACHMENT_STORE (store));
+       g_return_if_fail (E_IS_ATTACHMENT (attachment));
+
+       g_signal_handlers_disconnect_by_func (attachment,
+               G_CALLBACK (attachment_store_update_file_info_cb), store);
+       g_signal_handlers_disconnect_by_func (attachment,
+               G_CALLBACK (attachment_store_update_icon_cb), store);
+       g_signal_handlers_disconnect_by_func (attachment,
+               G_CALLBACK (attachment_store_update_progress_cb), store);
+       g_signal_handlers_disconnect_by_func (attachment,
+               G_CALLBACK (attachment_store_load_failed_cb), store);
+       g_signal_handlers_disconnect_by_func (attachment,
+               G_CALLBACK (attachment_store_attachment_notify_cb), store);
+}
+
+static void
 attachment_store_get_property (GObject *object,
                                guint property_id,
                                GValue *value,
@@ -132,6 +269,9 @@ e_attachment_store_class_init (EAttachmentStoreClass *class)
        object_class->dispose = attachment_store_dispose;
        object_class->finalize = attachment_store_finalize;
 
+       class->attachment_added = attachment_store_attachment_added;
+       class->attachment_removed = attachment_store_attachment_removed;
+
        g_object_class_install_property (
                object_class,
                PROP_NUM_ATTACHMENTS,
@@ -249,9 +389,6 @@ e_attachment_store_add_attachment (EAttachmentStore *store,
                store->priv->attachment_index,
                g_object_ref (attachment), reference);
 
-       /* This lets the attachment tell us when to update. */
-       e_attachment_set_reference (attachment, reference);
-
        g_object_freeze_notify (G_OBJECT (store));
        g_object_notify (G_OBJECT (store), "num-attachments");
        g_object_notify (G_OBJECT (store), "total-size");
@@ -287,7 +424,6 @@ e_attachment_store_remove_attachment (EAttachmentStore *store,
        }
 
        e_attachment_cancel (attachment);
-       e_attachment_set_reference (attachment, NULL);
 
        model = gtk_tree_row_reference_get_model (reference);
        path = gtk_tree_row_reference_get_path (reference);
@@ -335,7 +471,6 @@ e_attachment_store_remove_all (EAttachmentStore *store)
                EAttachment *attachment = iter->data;
 
                e_attachment_cancel (attachment);
-               e_attachment_set_reference (attachment, NULL);
 
                g_warn_if_fail (g_hash_table_remove (store->priv->attachment_index, attachment));
 
@@ -829,6 +964,35 @@ e_attachment_store_transform_num_attachments_to_visible_boolean (GBinding *bindi
        return TRUE;
 }
 
+gboolean
+e_attachment_store_find_attachment_iter (EAttachmentStore *store,
+                                        EAttachment *attachment,
+                                        GtkTreeIter *out_iter)
+{
+       GtkTreeRowReference *reference;
+       GtkTreeModel *model;
+       GtkTreePath *path;
+       gboolean found;
+
+       g_return_val_if_fail (E_IS_ATTACHMENT_STORE (store), FALSE);
+       g_return_val_if_fail (E_IS_ATTACHMENT (attachment), FALSE);
+       g_return_val_if_fail (out_iter != NULL, FALSE);
+
+       reference = g_hash_table_lookup (store->priv->attachment_index, attachment);
+
+       if (!reference || !gtk_tree_row_reference_valid (reference))
+               return FALSE;
+
+       model = gtk_tree_row_reference_get_model (reference);
+       g_return_val_if_fail (model == GTK_TREE_MODEL (store), FALSE);
+
+       path = gtk_tree_row_reference_get_path (reference);
+       found = gtk_tree_model_get_iter (model, out_iter, path);
+       gtk_tree_path_free (path);
+
+       return found;
+}
+
 /******************** e_attachment_store_get_uris_async() ********************/
 
 typedef struct _UriContext UriContext;
diff --git a/e-util/e-attachment-store.h b/e-util/e-attachment-store.h
index 2e68aa9..1f15f5d 100644
--- a/e-util/e-attachment-store.h
+++ b/e-util/e-attachment-store.h
@@ -115,6 +115,10 @@ gboolean   e_attachment_store_transform_num_attachments_to_visible_boolean
                                                 const GValue *from_value,
                                                 GValue *to_value,
                                                 gpointer user_data);
+gboolean       e_attachment_store_find_attachment_iter
+                                               (EAttachmentStore *store,
+                                                EAttachment *attachment,
+                                                GtkTreeIter *out_iter);
 /* Asynchronous Operations */
 void           e_attachment_store_get_uris_async
                                                (EAttachmentStore *store,
diff --git a/e-util/e-attachment-view.c b/e-util/e-attachment-view.c
index 7020ab8..00b17df 100644
--- a/e-util/e-attachment-view.c
+++ b/e-util/e-attachment-view.c
@@ -50,15 +50,7 @@ static const gchar *ui =
 "    <menuitem action='remove'/>"
 "    <menuitem action='properties'/>"
 "    <separator/>"
-"    <placeholder name='inline-actions'>"
-"      <menuitem action='zoom-to-100'/>"
-"      <menuitem action='zoom-to-window'/>"
-"      <menuitem action='show'/>"
-"      <menuitem action='show-all'/>"
-"      <separator/>"
-"      <menuitem action='hide'/>"
-"      <menuitem action='hide-all'/>"
-"    </placeholder>"
+"    <placeholder name='inline-actions'/>"
 "    <separator/>"
 "    <placeholder name='custom-actions'/>"
 "    <separator/>"
@@ -108,44 +100,6 @@ action_cancel_cb (GtkAction *action,
 }
 
 static void
-action_hide_cb (GtkAction *action,
-                EAttachmentView *view)
-{
-       EAttachment *attachment;
-       GList *list;
-
-       list = e_attachment_view_get_selected_attachments (view);
-       g_return_if_fail (g_list_length (list) == 1);
-       attachment = list->data;
-
-       e_attachment_set_shown (attachment, FALSE);
-
-       g_list_foreach (list, (GFunc) g_object_unref, NULL);
-       g_list_free (list);
-}
-
-static void
-action_hide_all_cb (GtkAction *action,
-                    EAttachmentView *view)
-{
-       EAttachmentStore *store;
-       GList *list, *iter;
-
-       store = e_attachment_view_get_store (view);
-       list = e_attachment_store_get_attachments (store);
-
-       for (iter = list; iter != NULL; iter = iter->next) {
-               EAttachment *attachment;
-
-               attachment = E_ATTACHMENT (iter->data);
-               e_attachment_set_shown (attachment, FALSE);
-       }
-
-       g_list_foreach (list, (GFunc) g_object_unref, NULL);
-       g_list_free (list);
-}
-
-static void
 action_open_with_cb (GtkAction *action,
                      EAttachmentView *view)
 {
@@ -342,78 +296,6 @@ exit:
        g_list_free (list);
 }
 
-static void
-action_show_cb (GtkAction *action,
-                EAttachmentView *view)
-{
-       EAttachment *attachment;
-       GList *list;
-
-       list = e_attachment_view_get_selected_attachments (view);
-       g_return_if_fail (g_list_length (list) == 1);
-       attachment = list->data;
-
-       e_attachment_set_shown (attachment, TRUE);
-
-       g_list_foreach (list, (GFunc) g_object_unref, NULL);
-       g_list_free (list);
-}
-
-static void
-action_show_all_cb (GtkAction *action,
-                    EAttachmentView *view)
-{
-       EAttachmentStore *store;
-       GList *list, *iter;
-
-       store = e_attachment_view_get_store (view);
-       list = e_attachment_store_get_attachments (store);
-
-       for (iter = list; iter != NULL; iter = iter->next) {
-               EAttachment *attachment;
-
-               attachment = E_ATTACHMENT (iter->data);
-               e_attachment_set_shown (attachment, TRUE);
-       }
-
-       g_list_foreach (list, (GFunc) g_object_unref, NULL);
-       g_list_free (list);
-}
-
-static void
-action_zoom_to_100_cb (GtkAction *action,
-                      EAttachmentView *view)
-{
-       EAttachment *attachment;
-       GList *list;
-
-       list = e_attachment_view_get_selected_attachments (view);
-       g_return_if_fail (g_list_length (list) == 1);
-       attachment = list->data;
-
-       e_attachment_set_zoom_to_window (attachment, FALSE);
-
-       g_list_foreach (list, (GFunc) g_object_unref, NULL);
-       g_list_free (list);
-}
-
-static void
-action_zoom_to_window_cb (GtkAction *action,
-                         EAttachmentView *view)
-{
-       EAttachment *attachment;
-       GList *list;
-
-       list = e_attachment_view_get_selected_attachments (view);
-       g_return_if_fail (g_list_length (list) == 1);
-       attachment = list->data;
-
-       e_attachment_set_zoom_to_window (attachment, TRUE);
-
-       g_list_foreach (list, (GFunc) g_object_unref, NULL);
-       g_list_free (list);
-}
-
 static GtkActionEntry standard_entries[] = {
 
        { "cancel",
@@ -478,51 +360,6 @@ static GtkActionEntry editable_entries[] = {
          G_CALLBACK (action_remove_cb) }
 };
 
-static GtkActionEntry inline_entries[] = {
-
-       { "hide",
-         NULL,
-         N_("_Hide"),
-         NULL,
-         NULL,  /* XXX Add a tooltip! */
-         G_CALLBACK (action_hide_cb) },
-
-       { "hide-all",
-         NULL,
-         N_("Hid_e All"),
-         NULL,
-         NULL,  /* XXX Add a tooltip! */
-         G_CALLBACK (action_hide_all_cb) },
-
-       { "show",
-         NULL,
-         N_("_View Inline"),
-         NULL,
-         NULL,  /* XXX Add a tooltip! */
-         G_CALLBACK (action_show_cb) },
-
-       { "show-all",
-         NULL,
-         N_("Vie_w All Inline"),
-         NULL,
-         NULL,  /* XXX Add a tooltip! */
-         G_CALLBACK (action_show_all_cb) },
-
-       { "zoom-to-100",
-         NULL,
-         N_("_Zoom to 100%"),
-         NULL,
-         N_("Zoom the image to its natural size"),
-         G_CALLBACK (action_zoom_to_100_cb) },
-
-       { "zoom-to-window",
-         NULL,
-         N_("_Zoom to window"),
-         NULL,
-         N_("Zoom large images to not be wider than the window width"),
-         G_CALLBACK (action_zoom_to_window_cb) }
-};
-
 static void
 call_attachment_load_handle_error (GObject *source_object,
                                   GAsyncResult *result,
@@ -745,76 +582,32 @@ attachment_view_update_actions (EAttachmentView *view)
 {
        EAttachmentViewPrivate *priv;
        EAttachment *attachment;
-       EAttachmentStore *store;
        GtkActionGroup *action_group;
        GtkAction *action;
        GList *list, *iter;
-       guint n_shown = 0;
-       guint n_hidden = 0;
        guint n_selected;
        gboolean busy = FALSE;
-       gboolean can_show = FALSE;
-       gboolean shown = FALSE;
-       gboolean is_image = FALSE;
-       gboolean zoom_to_window = FALSE;
-       gboolean visible;
 
        g_return_if_fail (E_IS_ATTACHMENT_VIEW (view));
 
        priv = e_attachment_view_get_private (view);
 
-       store = e_attachment_view_get_store (view);
-       list = e_attachment_store_get_attachments (store);
-
-       for (iter = list; iter != NULL; iter = iter->next) {
-               attachment = iter->data;
-
-               if (!e_attachment_get_can_show (attachment))
-                       continue;
-
-               if (e_attachment_get_shown (attachment))
-                       n_shown++;
-               else
-                       n_hidden++;
-       }
-
-       g_list_foreach (list, (GFunc) g_object_unref, NULL);
-       g_list_free (list);
-
        list = e_attachment_view_get_selected_attachments (view);
        n_selected = g_list_length (list);
 
        if (n_selected == 1) {
-               gchar *mime_type;
-
                attachment = g_object_ref (list->data);
-               mime_type = e_attachment_dup_mime_type (attachment);
+
                busy |= e_attachment_get_loading (attachment);
                busy |= e_attachment_get_saving (attachment);
-               can_show = e_attachment_get_can_show (attachment);
-               shown = e_attachment_get_shown (attachment);
-               zoom_to_window = e_attachment_get_zoom_to_window (attachment);
-               is_image = can_show && mime_type && g_ascii_strncasecmp (mime_type, "image/", 6) == 0;
-
-               g_free (mime_type);
        } else
                attachment = NULL;
 
-       g_list_foreach (list, (GFunc) g_object_unref, NULL);
-       g_list_free (list);
+       g_list_free_full (list, g_object_unref);
 
        action = e_attachment_view_get_action (view, "cancel");
        gtk_action_set_visible (action, busy);
 
-       action = e_attachment_view_get_action (view, "hide");
-       gtk_action_set_visible (action, can_show && shown);
-
-       /* Show this action if there are multiple viewable
-        * attachments, and at least one of them is shown. */
-       visible = (n_shown + n_hidden > 1) && (n_shown > 0);
-       action = e_attachment_view_get_action (view, "hide-all");
-       gtk_action_set_visible (action, visible);
-
        action = e_attachment_view_get_action (view, "open-with");
        gtk_action_set_visible (action, !busy && n_selected == 1);
 
@@ -827,29 +620,16 @@ attachment_view_update_actions (EAttachmentView *view)
        action = e_attachment_view_get_action (view, "save-as");
        gtk_action_set_visible (action, !busy && n_selected > 0);
 
-       action = e_attachment_view_get_action (view, "show");
-       gtk_action_set_visible (action, can_show && !shown);
-
-       action = e_attachment_view_get_action (view, "zoom-to-100");
-       gtk_action_set_visible (action, can_show && shown && is_image && zoom_to_window);
-
-       action = e_attachment_view_get_action (view, "zoom-to-window");
-       gtk_action_set_visible (action, can_show && shown && is_image && !zoom_to_window);
-
-       /* Show this action if there are multiple viewable
-        * attachments, and at least one of them is hidden. */
-       visible = (n_shown + n_hidden > 1) && (n_hidden > 0);
-       action = e_attachment_view_get_action (view, "show-all");
-       gtk_action_set_visible (action, visible);
-
        /* Clear out the "openwith" action group. */
        gtk_ui_manager_remove_ui (priv->ui_manager, priv->merge_id);
        action_group = e_attachment_view_get_action_group (view, "openwith");
        e_action_group_remove_all_actions (action_group);
        gtk_ui_manager_ensure_update (priv->ui_manager);
 
-       if (attachment == NULL || busy)
+       if (!attachment || busy) {
+               g_clear_object (&attachment);
                return;
+       }
 
        list = e_attachment_list_apps (attachment);
 
@@ -913,9 +693,8 @@ attachment_view_update_actions (EAttachmentView *view)
                g_free (action_tooltip);
        }
 
+       g_list_free_full (list, g_object_unref);
        g_object_unref (attachment);
-       g_list_foreach (list, (GFunc) g_object_unref, NULL);
-       g_list_free (list);
 }
 
 static void
@@ -1005,13 +784,6 @@ e_attachment_view_init (EAttachmentView *view)
                action_group, editable_entries,
                G_N_ELEMENTS (editable_entries), view);
 
-       action_group = e_attachment_view_add_action_group (view, "inline");
-
-       gtk_action_group_add_actions (
-               action_group, inline_entries,
-               G_N_ELEMENTS (inline_entries), view);
-       gtk_action_group_set_visible (action_group, FALSE);
-
        e_attachment_view_add_action_group (view, "openwith");
 
        /* Because we are loading from a hard-coded string, there is
diff --git a/e-util/e-attachment.c b/e-util/e-attachment.c
index df39795..ef01bc3 100644
--- a/e-util/e-attachment.c
+++ b/e-util/e-attachment.c
@@ -35,7 +35,6 @@
 
 #include <libedataserver/libedataserver.h>
 
-#include "e-attachment-store.h"
 #include "e-icon-factory.h"
 #include "e-mktemp.h"
 #include "e-misc-utils.h"
@@ -77,8 +76,7 @@ struct _EAttachmentPrivate {
        guint can_show : 1;
        guint loading : 1;
        guint saving : 1;
-       guint shown : 1;
-       guint zoom_to_window : 1;
+       guint initially_shown : 1;
 
        guint save_self      : 1;
        guint save_extracted : 1;
@@ -86,12 +84,6 @@ struct _EAttachmentPrivate {
        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;
-
        /* These are IDs for idle callbacks,
         * protected by the idle_lock mutex. */
        GMutex idle_lock;
@@ -111,15 +103,23 @@ enum {
        PROP_LOADING,
        PROP_MIME_PART,
        PROP_PERCENT,
-       PROP_REFERENCE,
        PROP_SAVE_SELF,
        PROP_SAVE_EXTRACTED,
        PROP_SAVING,
-       PROP_SHOWN,
-       PROP_SIGNED,
-       PROP_ZOOM_TO_WINDOW
+       PROP_INITIALLY_SHOWN,
+       PROP_SIGNED
+};
+
+enum {
+       LOAD_FAILED,
+       UPDATE_FILE_INFO,
+       UPDATE_ICON,
+       UPDATE_PROGRESS,
+       LAST_SIGNAL
 };
 
+static guint signals[LAST_SIGNAL];
+
 G_DEFINE_TYPE (
        EAttachment,
        e_attachment,
@@ -250,10 +250,6 @@ static gboolean
 attachment_update_file_info_columns_idle_cb (gpointer weak_ref)
 {
        EAttachment *attachment;
-       GtkTreeRowReference *reference;
-       GtkTreeModel *model;
-       GtkTreePath *path;
-       GtkTreeIter iter;
        GFileInfo *file_info;
        const gchar *content_type;
        const gchar *display_name;
@@ -271,19 +267,10 @@ attachment_update_file_info_columns_idle_cb (gpointer weak_ref)
        attachment->priv->update_file_info_columns_idle_id = 0;
        g_mutex_unlock (&attachment->priv->idle_lock);
 
-       reference = e_attachment_get_reference (attachment);
-       if (!gtk_tree_row_reference_valid (reference))
-               goto exit;
-
        file_info = e_attachment_ref_file_info (attachment);
        if (file_info == NULL)
                goto exit;
 
-       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);
@@ -298,18 +285,11 @@ attachment_update_file_info_columns_idle_cb (gpointer weak_ref)
        }
 
        if (size > 0)
-               caption = g_strdup_printf (
-                       "%s\n(%s)", description, display_size);
+               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_signal_emit (attachment, signals[UPDATE_FILE_INFO], 0, caption, content_desc, description, (gint64) 
size);
 
        g_free (content_desc);
        g_free (display_size);
@@ -347,10 +327,6 @@ static gboolean
 attachment_update_icon_column_idle_cb (gpointer weak_ref)
 {
        EAttachment *attachment;
-       GtkTreeRowReference *reference;
-       GtkTreeModel *model;
-       GtkTreePath *path;
-       GtkTreeIter iter;
        GFileInfo *file_info;
        GCancellable *cancellable;
        GIcon *icon = NULL;
@@ -365,15 +341,6 @@ attachment_update_icon_column_idle_cb (gpointer weak_ref)
        attachment->priv->update_icon_column_idle_id = 0;
        g_mutex_unlock (&attachment->priv->idle_lock);
 
-       reference = e_attachment_get_reference (attachment);
-       if (!gtk_tree_row_reference_valid (reference))
-               goto exit;
-
-       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_ref_file_info (attachment);
 
@@ -475,10 +442,7 @@ attachment_update_icon_column_idle_cb (gpointer weak_ref)
                icon = emblemed_icon;
        }
 
-       gtk_list_store_set (
-               GTK_LIST_STORE (model), &iter,
-               E_ATTACHMENT_STORE_COLUMN_ICON, icon,
-               -1);
+       g_signal_emit (attachment, signals[UPDATE_ICON], 0, icon);
 
        /* Cache the icon to reuse for things like drag-n-drop. */
        if (attachment->priv->icon != NULL)
@@ -517,10 +481,6 @@ static gboolean
 attachment_update_progress_columns_idle_cb (gpointer weak_ref)
 {
        EAttachment *attachment;
-       GtkTreeRowReference *reference;
-       GtkTreeModel *model;
-       GtkTreePath *path;
-       GtkTreeIter iter;
        gboolean loading;
        gboolean saving;
        gint percent;
@@ -533,26 +493,12 @@ attachment_update_progress_columns_idle_cb (gpointer weak_ref)
        attachment->priv->update_progress_columns_idle_id = 0;
        g_mutex_unlock (&attachment->priv->idle_lock);
 
-       reference = e_attachment_get_reference (attachment);
-       if (!gtk_tree_row_reference_valid (reference))
-               goto exit;
-
-       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);
+       g_signal_emit (attachment, signals[UPDATE_PROGRESS], 0, loading, saving, percent);
 
 exit:
        g_clear_object (&attachment);
@@ -583,10 +529,6 @@ static void
 attachment_set_loading (EAttachment *attachment,
                         gboolean loading)
 {
-       GtkTreeRowReference *reference;
-
-       reference = e_attachment_get_reference (attachment);
-
        attachment->priv->percent = 0;
        attachment->priv->loading = loading;
        attachment->priv->last_percent_notify = 0;
@@ -595,12 +537,6 @@ attachment_set_loading (EAttachment *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
@@ -696,8 +632,8 @@ attachment_set_property (GObject *object,
                                g_value_get_object (value));
                        return;
 
-               case PROP_SHOWN:
-                       e_attachment_set_shown (
+               case PROP_INITIALLY_SHOWN:
+                       e_attachment_set_initially_shown (
                                E_ATTACHMENT (object),
                                g_value_get_boolean (value));
                        return;
@@ -708,12 +644,6 @@ attachment_set_property (GObject *object,
                                g_value_get_object (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),
@@ -731,12 +661,6 @@ attachment_set_property (GObject *object,
                                E_ATTACHMENT (object),
                                g_value_get_boolean (value));
                        return;
-
-               case PROP_ZOOM_TO_WINDOW:
-                       e_attachment_set_zoom_to_window (
-                               E_ATTACHMENT (object),
-                               g_value_get_boolean (value));
-                       return;
        }
 
        G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
@@ -791,10 +715,10 @@ attachment_get_property (GObject *object,
                                E_ATTACHMENT (object)));
                        return;
 
-               case PROP_SHOWN:
+               case PROP_INITIALLY_SHOWN:
                        g_value_set_boolean (
                                value,
-                               e_attachment_get_shown (
+                               e_attachment_get_initially_shown (
                                E_ATTACHMENT (object)));
                        return;
 
@@ -819,13 +743,6 @@ attachment_get_property (GObject *object,
                                E_ATTACHMENT (object)));
                        return;
 
-               case PROP_REFERENCE:
-                       g_value_set_boxed (
-                               value,
-                               e_attachment_get_reference (
-                               E_ATTACHMENT (object)));
-                       return;
-
                case PROP_SAVE_SELF:
                        g_value_set_boolean (
                                value,
@@ -853,13 +770,6 @@ attachment_get_property (GObject *object,
                                e_attachment_get_signed (
                                E_ATTACHMENT (object)));
                        return;
-
-               case PROP_ZOOM_TO_WINDOW:
-                       g_value_set_boolean (
-                               value,
-                               e_attachment_get_zoom_to_window (
-                               E_ATTACHMENT (object)));
-                       return;
        }
 
        G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
@@ -883,10 +793,6 @@ attachment_dispose (GObject *object)
                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 (e_attachment_parent_class)->dispose (object);
 }
@@ -1030,16 +936,6 @@ e_attachment_class_init (EAttachmentClass *class)
 
        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_SAVE_SELF,
                g_param_spec_boolean (
                        "save-self",
@@ -1070,10 +966,10 @@ e_attachment_class_init (EAttachmentClass *class)
 
        g_object_class_install_property (
                object_class,
-               PROP_SHOWN,
+               PROP_INITIALLY_SHOWN,
                g_param_spec_boolean (
-                       "shown",
-                       "Shown",
+                       "initially-shown",
+                       "Initially Shown",
                        NULL,
                        FALSE,
                        G_PARAM_READWRITE |
@@ -1093,16 +989,46 @@ e_attachment_class_init (EAttachmentClass *class)
                        G_PARAM_READWRITE |
                        G_PARAM_CONSTRUCT));
 
-       g_object_class_install_property (
-               object_class,
-               PROP_ZOOM_TO_WINDOW,
-               g_param_spec_boolean (
-                       "zoom-to-window",
-                       "Zoom to window",
-                       NULL,
-                       TRUE,
-                       G_PARAM_READWRITE |
-                       G_PARAM_CONSTRUCT));
+       signals[UPDATE_FILE_INFO] = g_signal_new (
+               "update-file-info",
+               G_TYPE_FROM_CLASS (class),
+               G_SIGNAL_RUN_LAST,
+               G_STRUCT_OFFSET (EAttachmentClass, update_file_info),
+               NULL, NULL, NULL,
+               G_TYPE_NONE, 4,
+               G_TYPE_STRING,
+               G_TYPE_STRING,
+               G_TYPE_STRING,
+               G_TYPE_INT64);
+
+       signals[UPDATE_ICON] = g_signal_new (
+               "update-icon",
+               G_TYPE_FROM_CLASS (class),
+               G_SIGNAL_RUN_LAST,
+               G_STRUCT_OFFSET (EAttachmentClass, update_icon),
+               NULL, NULL, NULL,
+               G_TYPE_NONE, 1,
+               G_TYPE_ICON);
+
+       signals[UPDATE_PROGRESS] = g_signal_new (
+               "update-progress",
+               G_TYPE_FROM_CLASS (class),
+               G_SIGNAL_RUN_LAST,
+               G_STRUCT_OFFSET (EAttachmentClass, update_progress),
+               NULL, NULL, NULL,
+               G_TYPE_NONE, 3,
+               G_TYPE_BOOLEAN,
+               G_TYPE_BOOLEAN,
+               G_TYPE_INT);
+
+       signals[LOAD_FAILED] = g_signal_new (
+               "load-failed",
+               G_TYPE_FROM_CLASS (class),
+               G_SIGNAL_RUN_LAST,
+               G_STRUCT_OFFSET (EAttachmentClass, load_failed),
+               NULL, NULL, NULL,
+               G_TYPE_NONE, 0,
+               G_TYPE_NONE);
 }
 
 static void
@@ -1140,18 +1066,6 @@ e_attachment_init (EAttachment *attachment)
                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);
-
        e_signal_connect_notify (
                attachment, "notify::saving",
                G_CALLBACK (attachment_update_icon_column), NULL);
@@ -1476,7 +1390,6 @@ void
 e_attachment_set_file_info (EAttachment *attachment,
                             GFileInfo *file_info)
 {
-       GtkTreeRowReference *reference;
        GIcon *icon;
 
        g_return_if_fail (E_IS_ATTACHMENT (attachment));
@@ -1501,14 +1414,6 @@ e_attachment_set_file_info (EAttachment *attachment,
        g_mutex_unlock (&attachment->priv->property_lock);
 
        g_object_notify (G_OBJECT (attachment), "file-info");
-
-       /* Tell the EAttachmentStore its total size changed. */
-       reference = e_attachment_get_reference (attachment);
-       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");
-       }
 }
 
 /**
@@ -1616,29 +1521,6 @@ e_attachment_get_percent (EAttachment *attachment)
        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)
 {
@@ -1648,44 +1530,22 @@ e_attachment_get_saving (EAttachment *attachment)
 }
 
 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");
-}
-
-gboolean
-e_attachment_get_zoom_to_window (EAttachment *attachment)
+e_attachment_get_initially_shown (EAttachment *attachment)
 {
        g_return_val_if_fail (E_IS_ATTACHMENT (attachment), FALSE);
 
-       return attachment->priv->zoom_to_window;
+       return attachment->priv->initially_shown;
 }
 
 void
-e_attachment_set_zoom_to_window (EAttachment *attachment,
-                                gboolean zoom_to_window)
+e_attachment_set_initially_shown (EAttachment *attachment,
+                                 gboolean initially_shown)
 {
        g_return_if_fail (E_IS_ATTACHMENT (attachment));
 
-       if ((attachment->priv->zoom_to_window ? 1 : 0) == (zoom_to_window ? 1 : 0))
-               return;
-
-       attachment->priv->zoom_to_window = zoom_to_window;
+       attachment->priv->initially_shown = initially_shown;
 
-       g_object_notify (G_OBJECT (attachment), "zoom-to-window");
+       g_object_notify (G_OBJECT (attachment), "initially-shown");
 }
 
 gboolean
@@ -1868,6 +1728,16 @@ exit:
        return app_info_list;
 }
 
+void
+e_attachment_update_store_columns (EAttachment *attachment)
+{
+       g_return_if_fail (E_IS_ATTACHMENT (attachment));
+
+       attachment_update_file_info_columns (attachment);
+       attachment_update_icon_column (attachment);
+       attachment_update_progress_columns (attachment);
+}
+
 /************************* e_attachment_load_async() *************************/
 
 typedef struct _LoadContext LoadContext;
@@ -2500,7 +2370,6 @@ e_attachment_load_handle_error (EAttachment *attachment,
 {
        GtkWidget *dialog;
        GFileInfo *file_info;
-       GtkTreeRowReference *reference;
        const gchar *display_name;
        const gchar *primary_text;
        GError *error = NULL;
@@ -2512,17 +2381,7 @@ e_attachment_load_handle_error (EAttachment *attachment,
        if (e_attachment_load_finish (attachment, result, &error))
                return;
 
-       /* 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);
-       }
+       g_signal_emit (attachment, signals[LOAD_FAILED], 0, NULL);
 
        /* Ignore cancellations. */
        if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) {
diff --git a/e-util/e-attachment.h b/e-util/e-attachment.h
index b7505c9..fa2ce98 100644
--- a/e-util/e-attachment.h
+++ b/e-util/e-attachment.h
@@ -60,6 +60,20 @@ struct _EAttachment {
 
 struct _EAttachmentClass {
        GObjectClass parent_class;
+
+       /* Signals */
+       void    (*update_file_info)             (EAttachment *attachment,
+                                                const gchar *caption,
+                                                const gchar *content_type,
+                                                const gchar *description,
+                                                gint64 size);
+       void    (*update_icon)                  (EAttachment *attachment,
+                                                GIcon *icon);
+       void    (*update_progress)              (EAttachment *attachment,
+                                                gboolean loading,
+                                                gboolean saving,
+                                                gint percent);
+       void    (*load_failed)                  (EAttachment *attachment);
 };
 
 GType          e_attachment_get_type           (void) G_GNUC_CONST;
@@ -92,17 +106,10 @@ CamelMimePart *    e_attachment_ref_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);
-gboolean       e_attachment_get_zoom_to_window (EAttachment *attachment);
-void           e_attachment_set_zoom_to_window (EAttachment *attachment,
-                                                gboolean zoom_to_window);
+gboolean       e_attachment_get_initially_shown(EAttachment *attachment);
+void           e_attachment_set_initially_shown(EAttachment *attachment,
+                                                gboolean initially_shown);
 gboolean       e_attachment_get_save_self      (EAttachment *attachment);
 void           e_attachment_set_save_self      (EAttachment *attachment,
                                                 gboolean save_self);
@@ -121,6 +128,8 @@ gchar *             e_attachment_dup_description    (EAttachment *attachment);
 gchar *                e_attachment_dup_thumbnail_path (EAttachment *attachment);
 gboolean       e_attachment_is_rfc822          (EAttachment *attachment);
 GList *                e_attachment_list_apps          (EAttachment *attachment);
+void           e_attachment_update_store_columns
+                                               (EAttachment *attachment);
 
 /* Asynchronous Operations */
 void           e_attachment_load_async         (EAttachment *attachment,
diff --git a/em-format/e-mail-formatter-attachment.c b/em-format/e-mail-formatter-attachment.c
index 6064b58..86a39ef 100644
--- a/em-format/e-mail-formatter-attachment.c
+++ b/em-format/e-mail-formatter-attachment.c
@@ -103,7 +103,7 @@ emfe_attachment_format (EMailFormatterExtension *extension,
                                        pair->validity->encrypt.status);
                }
 
-               e_attachment_set_shown (attachment, e_mail_part_should_show_inline (part));
+               e_attachment_set_initially_shown (attachment, e_mail_part_should_show_inline (part));
 
                e_mail_formatter_claim_attachment (formatter, attachment);
 
diff --git a/em-format/e-mail-parser-text-plain.c b/em-format/e-mail-parser-text-plain.c
index ccb371d..aa5c55a 100644
--- a/em-format/e-mail-parser-text-plain.c
+++ b/em-format/e-mail-parser-text-plain.c
@@ -185,7 +185,7 @@ empe_text_plain_parse (EMailParserExtension *extension,
 
                                empa->shown = FALSE;
                                attachment = e_mail_part_attachment_ref_attachment (empa);
-                               e_attachment_set_shown (attachment, FALSE);
+                               e_attachment_set_initially_shown (attachment, FALSE);
                                e_attachment_set_can_show (attachment, FALSE);
 
                                att_part = e_attachment_ref_mime_part (attachment);
diff --git a/em-format/e-mail-parser.c b/em-format/e-mail-parser.c
index 02d303e..b5fe91e 100644
--- a/em-format/e-mail-parser.c
+++ b/em-format/e-mail-parser.c
@@ -718,7 +718,7 @@ e_mail_parser_wrap_as_attachment (EMailParser *parser,
 
        attachment = e_mail_part_attachment_ref_attachment (empa);
 
-       e_attachment_set_shown (attachment, empa->shown);
+       e_attachment_set_initially_shown (attachment, empa->shown);
        e_attachment_set_can_show (
                attachment,
                extensions && !g_queue_is_empty (extensions));
diff --git a/mail/e-mail-display.c b/mail/e-mail-display.c
index 5bea493..c97b596 100644
--- a/mail/e-mail-display.c
+++ b/mail/e-mail-display.c
@@ -51,9 +51,19 @@
        (G_TYPE_INSTANCE_GET_PRIVATE \
        ((obj), E_TYPE_MAIL_DISPLAY, EMailDisplayPrivate))
 
+typedef enum {
+       E_ATTACHMENT_FLAG_VISIBLE       = (1 << 0),
+       E_ATTACHMENT_FLAG_ZOOMED_TO_100 = (1 << 1)
+} EAttachmentFlags;
+
 struct _EMailDisplayPrivate {
        EAttachmentStore *attachment_store;
        GWeakRef *attachment_view; /* EAttachmentView * */
+       GHashTable *attachment_flags; /* EAttachment * ~> guint bit-or of EAttachmentFlags */
+       guint attachment_inline_ui_id;
+
+       GtkActionGroup *attachment_inline_group;
+
        EMailPartList *part_list;
        EMailFormatterMode mode;
        EMailFormatter *formatter;
@@ -152,6 +162,21 @@ G_DEFINE_TYPE (
        e_mail_display,
        E_TYPE_WEB_VIEW);
 
+static const gchar *attachment_popup_ui =
+"<ui>"
+"  <popup name='context'>"
+"    <placeholder name='inline-actions'>"
+"      <menuitem action='zoom-to-100'/>"
+"      <menuitem action='zoom-to-window'/>"
+"      <menuitem action='show'/>"
+"      <menuitem action='show-all'/>"
+"      <separator/>"
+"      <menuitem action='hide'/>"
+"      <menuitem action='hide-all'/>"
+"    </placeholder>"
+"  </popup>"
+"</ui>";
+
 static void
 e_mail_display_claim_skipped_uri (EMailDisplay *mail_display,
                                  const gchar *uri)
@@ -543,6 +568,224 @@ setup_dom_bindings (EMailDisplay *display)
        }
 }
 
+static void
+mail_display_change_one_attachment_visibility (EMailDisplay *display,
+                                              EAttachment *attachment,
+                                              gboolean show,
+                                              gboolean flip)
+{
+       gchar *element_id;
+       gchar *uri;
+       guint flags;
+
+       g_return_if_fail (E_IS_MAIL_DISPLAY (display));
+       g_return_if_fail (E_IS_ATTACHMENT (attachment));
+       g_return_if_fail (g_hash_table_contains (display->priv->attachment_flags, attachment));
+
+       flags = GPOINTER_TO_UINT (g_hash_table_lookup (display->priv->attachment_flags, attachment));
+       if (flip)
+               show = !(flags & E_ATTACHMENT_FLAG_VISIBLE);
+
+       if ((((flags & E_ATTACHMENT_FLAG_VISIBLE) != 0) ? 1 : 0) == (show ? 1 : 0))
+               return;
+
+       if (show)
+               flags = flags | E_ATTACHMENT_FLAG_VISIBLE;
+       else
+               flags = flags & (~E_ATTACHMENT_FLAG_VISIBLE);
+       g_hash_table_insert (display->priv->attachment_flags, attachment, GUINT_TO_POINTER (flags));
+
+       element_id = g_strdup_printf ("attachment-wrapper-%p", attachment);
+       e_web_view_set_element_hidden (E_WEB_VIEW (display), element_id, !show);
+       g_free (element_id);
+
+       element_id = g_strdup_printf ("attachment-expander-img-%p", attachment);
+       uri = g_strdup_printf ("gtk-stock://%s?size=%d", show ? "go-down" : "go-next", GTK_ICON_SIZE_BUTTON);
+
+       e_web_view_set_element_attribute (E_WEB_VIEW (display), element_id, NULL, "src", uri);
+
+       g_free (element_id);
+       g_free (uri);
+}
+
+static void
+mail_display_change_attachment_visibility (EMailDisplay *display,
+                                          gboolean all,
+                                          gboolean show)
+{
+       EAttachmentView *view;
+       GList *attachments, *link;
+
+       g_return_if_fail (E_IS_MAIL_DISPLAY (display));
+
+       view = e_mail_display_ref_attachment_view (display);
+       g_return_if_fail (view != NULL);
+
+       if (all)
+               attachments = e_attachment_store_get_attachments (display->priv->attachment_store);
+       else
+               attachments = view ? e_attachment_view_get_selected_attachments (view) : NULL;
+
+       for (link = attachments; link; link = g_list_next (link)) {
+               EAttachment *attachment = link->data;
+
+               if (e_attachment_get_can_show (attachment))
+                       mail_display_change_one_attachment_visibility (display, attachment, show, FALSE);
+       }
+
+       g_list_free_full (attachments, g_object_unref);
+       g_clear_object (&view);
+}
+
+static void
+mail_attachment_change_zoom (EMailDisplay *display,
+                            gboolean to_100_percent)
+{
+       EAttachmentView *view;
+       GList *attachments, *link;
+
+       g_return_if_fail (E_IS_MAIL_DISPLAY (display));
+
+       view = e_mail_display_ref_attachment_view (display);
+       g_return_if_fail (view != NULL);
+
+       attachments = view ? e_attachment_view_get_selected_attachments (view) : NULL;
+
+       for (link = attachments; link; link = g_list_next (link)) {
+               EAttachment *attachment = link->data;
+               gchar *element_id;
+               const gchar *max_width;
+               guint flags;
+
+               if (!E_IS_ATTACHMENT (attachment) ||
+                   !g_hash_table_contains (display->priv->attachment_flags, attachment))
+                       continue;
+
+               flags = GPOINTER_TO_UINT (g_hash_table_lookup (display->priv->attachment_flags, attachment));
+               if ((((flags & E_ATTACHMENT_FLAG_ZOOMED_TO_100) != 0) ? 1 : 0) == (to_100_percent ? 1 : 0))
+                       continue;
+
+               if (to_100_percent)
+                       flags = flags | E_ATTACHMENT_FLAG_ZOOMED_TO_100;
+               else
+                       flags = flags & (~E_ATTACHMENT_FLAG_ZOOMED_TO_100);
+               g_hash_table_insert (display->priv->attachment_flags, attachment, GUINT_TO_POINTER (flags));
+
+               if (to_100_percent)
+                       max_width = NULL;
+               else
+                       max_width = "100%";
+
+               element_id = g_strdup_printf ("attachment-wrapper-%p::child", attachment);
+
+               e_web_view_set_element_style_property (E_WEB_VIEW (display), element_id, "max-width", 
max_width, "");
+
+               g_free (element_id);
+       }
+
+       g_list_free_full (attachments, g_object_unref);
+       g_clear_object (&view);
+}
+
+static void
+action_attachment_show_cb (GtkAction *action,
+                          EMailDisplay *display)
+{
+       g_return_if_fail (E_IS_MAIL_DISPLAY (display));
+
+       mail_display_change_attachment_visibility (display, FALSE, TRUE);
+}
+
+static void
+action_attachment_show_all_cb (GtkAction *action,
+                              EMailDisplay *display)
+{
+       g_return_if_fail (E_IS_MAIL_DISPLAY (display));
+
+       mail_display_change_attachment_visibility (display, TRUE, TRUE);
+}
+
+static void
+action_attachment_hide_cb (GtkAction *action,
+                          EMailDisplay *display)
+{
+       g_return_if_fail (E_IS_MAIL_DISPLAY (display));
+
+       mail_display_change_attachment_visibility (display, FALSE, FALSE);
+}
+
+static void
+action_attachment_hide_all_cb (GtkAction *action,
+                              EMailDisplay *display)
+{
+       g_return_if_fail (E_IS_MAIL_DISPLAY (display));
+
+       mail_display_change_attachment_visibility (display, TRUE, FALSE);
+}
+
+static void
+action_attachment_zoom_to_100_cb (GtkAction *action,
+                                 EMailDisplay *display)
+{
+       g_return_if_fail (E_IS_MAIL_DISPLAY (display));
+
+       mail_attachment_change_zoom (display, TRUE);
+}
+
+static void
+action_attachment_zoom_to_window_cb (GtkAction *action,
+                                    EMailDisplay *display)
+{
+       g_return_if_fail (E_IS_MAIL_DISPLAY (display));
+
+       mail_attachment_change_zoom (display, FALSE);
+}
+
+static GtkActionEntry attachment_inline_entries[] = {
+
+       { "hide",
+         NULL,
+         N_("_Hide"),
+         NULL,
+         NULL,  /* XXX Add a tooltip! */
+         G_CALLBACK (action_attachment_hide_cb) },
+
+       { "hide-all",
+         NULL,
+         N_("Hid_e All"),
+         NULL,
+         NULL,  /* XXX Add a tooltip! */
+         G_CALLBACK (action_attachment_hide_all_cb) },
+
+       { "show",
+         NULL,
+         N_("_View Inline"),
+         NULL,
+         NULL,  /* XXX Add a tooltip! */
+         G_CALLBACK (action_attachment_show_cb) },
+
+       { "show-all",
+         NULL,
+         N_("Vie_w All Inline"),
+         NULL,
+         NULL,  /* XXX Add a tooltip! */
+         G_CALLBACK (action_attachment_show_all_cb) },
+
+       { "zoom-to-100",
+         NULL,
+         N_("_Zoom to 100%"),
+         NULL,
+         N_("Zoom the image to its natural size"),
+         G_CALLBACK (action_attachment_zoom_to_100_cb) },
+
+       { "zoom-to-window",
+         NULL,
+         N_("_Zoom to window"),
+         NULL,
+         N_("Zoom large images to not be wider than the window width"),
+         G_CALLBACK (action_attachment_zoom_to_window_cb) }
+};
+
 static EAttachment *
 mail_display_ref_attachment_from_element (EMailDisplay *display,
                                          const gchar *element_value)
@@ -594,7 +837,6 @@ mail_display_attachment_expander_clicked_cb (EWebView *web_view,
                                             gpointer user_data)
 {
        EMailDisplay *display;
-       EAttachmentView *view;
        EAttachment *attachment;
 
        g_return_if_fail (E_IS_MAIL_DISPLAY (web_view));
@@ -603,16 +845,102 @@ mail_display_attachment_expander_clicked_cb (EWebView *web_view,
        g_return_if_fail (element_position != NULL);
 
        display = E_MAIL_DISPLAY (web_view);
-       view = e_mail_display_ref_attachment_view (display);
        attachment = mail_display_ref_attachment_from_element (display, element_value);
 
-       if (view && attachment) {
-               /* mail_display_attachment_notify_cb() takes care of the HTML part */
-               e_attachment_set_shown (attachment, !e_attachment_get_shown (attachment));
+       if (attachment) {
+               /* Flip the current 'visible' state */
+               mail_display_change_one_attachment_visibility (display, attachment, FALSE, TRUE);
        }
 
        g_clear_object (&attachment);
+}
+
+static void
+mail_display_attachment_inline_update_actions (EMailDisplay *display)
+{
+       GtkActionGroup *action_group;
+       GtkAction *action;
+       GList *attachments, *link;
+       EAttachmentView *view;
+       guint n_shown = 0;
+       guint n_hidden = 0;
+       guint n_selected = 0;
+       gboolean can_show = FALSE;
+       gboolean shown = FALSE;
+       gboolean is_image = FALSE;
+       gboolean zoomed_to_100 = FALSE;
+       gboolean visible;
+
+       g_return_if_fail (E_IS_MAIL_DISPLAY (display));
+
+       action_group = display->priv->attachment_inline_group;
+       g_return_if_fail (action_group != NULL);
+
+       attachments = e_attachment_store_get_attachments (display->priv->attachment_store);
+
+       for (link = attachments; link; link = g_list_next (link)) {
+               EAttachment *attachment = link->data;
+               guint32 flags;
+
+               if (!e_attachment_get_can_show (attachment))
+                       continue;
+
+               flags = GPOINTER_TO_UINT (g_hash_table_lookup (display->priv->attachment_flags, attachment));
+               if ((flags & E_ATTACHMENT_FLAG_VISIBLE) != 0)
+                       n_shown++;
+               else
+                       n_hidden++;
+       }
+
+       g_list_free_full (attachments, g_object_unref);
+
+       view = e_mail_display_ref_attachment_view (display);
+       attachments = view ? e_attachment_view_get_selected_attachments (view) : NULL;
+       n_selected = g_list_length (attachments);
+
+       if (n_selected == 1) {
+               EAttachment *attachment;
+               gchar *mime_type;
+               guint32 flags;
+
+               attachment = attachments->data;
+               mime_type = e_attachment_dup_mime_type (attachment);
+               can_show = e_attachment_get_can_show (attachment);
+               is_image = can_show && mime_type && g_ascii_strncasecmp (mime_type, "image/", 6) == 0;
+
+               flags = GPOINTER_TO_UINT (g_hash_table_lookup (display->priv->attachment_flags, attachment));
+               shown = (flags & E_ATTACHMENT_FLAG_VISIBLE) != 0;
+               zoomed_to_100 = (flags & E_ATTACHMENT_FLAG_ZOOMED_TO_100) != 0;
+
+               g_free (mime_type);
+       }
+       g_list_free_full (attachments, g_object_unref);
+
        g_clear_object (&view);
+
+       action = gtk_action_group_get_action (action_group, "show");
+       gtk_action_set_visible (action, can_show && !shown);
+
+       /* Show this action if there are multiple viewable
+        * attachments, and at least one of them is hidden. */
+       visible = (n_shown + n_hidden > 1) && (n_hidden > 0);
+       action = gtk_action_group_get_action (action_group, "show-all");
+       gtk_action_set_visible (action, visible);
+
+       action = gtk_action_group_get_action (action_group, "hide");
+       gtk_action_set_visible (action, can_show && shown);
+
+       /* Show this action if there are multiple viewable
+        * attachments, and at least one of them is shown. */
+       visible = (n_shown + n_hidden > 1) && (n_shown > 0);
+       action = gtk_action_group_get_action (action_group, "hide-all");
+       gtk_action_set_visible (action, visible);
+
+       action = gtk_action_group_get_action (action_group, "zoom-to-100");
+       gtk_action_set_visible (action, can_show && shown && is_image && !zoomed_to_100);
+
+       action = gtk_action_group_get_action (action_group, "zoom-to-window");
+       gtk_action_set_visible (action, can_show && shown && is_image && zoomed_to_100);
 }
 
 static void
@@ -620,15 +948,10 @@ mail_display_attachment_menu_deactivate_cb (GtkMenuShell *menu,
                                            gpointer user_data)
 {
        EMailDisplay *display = user_data;
-       EAttachmentView *view;
-       GtkActionGroup *action_group;
 
        g_return_if_fail (E_IS_MAIL_DISPLAY (display));
 
-       view = e_mail_display_ref_attachment_view (display);
-       action_group = e_attachment_view_get_action_group (view, "inline");
-
-       gtk_action_group_set_visible (action_group, FALSE);
+       gtk_action_group_set_visible (display->priv->attachment_inline_group, FALSE);
 
        g_signal_handlers_disconnect_by_func (menu,
                G_CALLBACK (mail_display_attachment_menu_deactivate_cb), display);
@@ -682,16 +1005,17 @@ static void
 mail_display_attachment_select_path (EAttachmentView *view,
                                     EAttachment *attachment)
 {
-       GtkTreeRowReference *reference;
        GtkTreePath *path;
+       GtkTreeIter iter;
+       EAttachmentStore *store;
 
        g_return_if_fail (E_IS_ATTACHMENT_VIEW (view));
        g_return_if_fail (E_IS_ATTACHMENT (attachment));
 
-       reference = e_attachment_get_reference (attachment);
-       g_return_if_fail (gtk_tree_row_reference_valid (reference));
+       store = e_attachment_view_get_store (view);
+       g_return_if_fail (e_attachment_store_find_attachment_iter (store, attachment, &iter));
 
-       path = gtk_tree_row_reference_get_path (reference);
+       path = gtk_tree_model_get_path (GTK_TREE_MODEL (store), &iter);
 
        e_attachment_view_unselect_all (view);
        e_attachment_view_select_path (view, path);
@@ -720,7 +1044,6 @@ mail_display_attachment_menu_clicked_cb (EWebView *web_view,
        attachment = mail_display_ref_attachment_from_element (display, element_value);
 
        if (view && attachment) {
-               GtkActionGroup *action_group;
                GtkWidget *popup_menu;
 
                popup_menu = e_attachment_view_get_popup_menu (view);
@@ -729,15 +1052,14 @@ mail_display_attachment_menu_clicked_cb (EWebView *web_view,
                        popup_menu, "deactivate",
                        G_CALLBACK (mail_display_attachment_menu_deactivate_cb), display);
 
-               action_group = e_attachment_view_get_action_group (view, "inline");
-
                mail_display_attachment_select_path (view, attachment);
                display->priv->attachment_popup_position = *element_position;
 
+               mail_display_attachment_inline_update_actions (display);
+               gtk_action_group_set_visible (display->priv->attachment_inline_group, TRUE);
+
                e_attachment_view_show_popup_menu (view, NULL,
                        mail_display_attachment_menu_position_cb, display);
-
-               gtk_action_group_set_visible (action_group, TRUE);
        }
 
        g_clear_object (&attachment);
@@ -745,62 +1067,20 @@ mail_display_attachment_menu_clicked_cb (EWebView *web_view,
 }
 
 static void
-mail_display_attachment_notify_cb (GObject *attachment,
-                                  GParamSpec *param,
-                                  gpointer user_data)
-{
-       EMailDisplay *display = user_data;
-       gchar *element_id = NULL;
-
-       g_return_if_fail (E_IS_ATTACHMENT (attachment));
-       g_return_if_fail (param != NULL);
-       g_return_if_fail (E_IS_MAIL_DISPLAY (display));
-
-       if (g_str_equal (param->name, "shown")) {
-               gboolean shown;
-               gchar *uri;
-
-               shown = e_attachment_get_shown (E_ATTACHMENT (attachment));
-
-               element_id = g_strdup_printf ("attachment-wrapper-%p", attachment);
-               e_web_view_set_element_hidden (E_WEB_VIEW (display), element_id, !shown);
-
-               g_free (element_id);
-               element_id = g_strdup_printf ("attachment-expander-img-%p", attachment);
-               uri = g_strdup_printf ("gtk-stock://%s?size=%d", shown ? "go-down" : "go-next", 
GTK_ICON_SIZE_BUTTON);
-
-               e_web_view_set_element_attribute (E_WEB_VIEW (display), element_id, NULL, "src", uri);
-
-               g_free (uri);
-       } else if (g_str_equal (param->name, "zoom-to-window")) {
-               const gchar *value;
-
-               if (e_attachment_get_zoom_to_window (E_ATTACHMENT (attachment)))
-                       value = "100%";
-               else
-                       value = NULL;
-
-               element_id = g_strdup_printf ("attachment-wrapper-%p::child", attachment);
-
-               e_web_view_set_element_style_property (E_WEB_VIEW (display), element_id, "max-width", value, 
"");
-       }
-
-       g_free (element_id);
-}
-
-static void
 mail_display_attachment_added_cb (EAttachmentStore *store,
                                  EAttachment *attachment,
                                  gpointer user_data)
 {
        EMailDisplay *display = user_data;
+       guint flags;
 
        g_return_if_fail (E_IS_ATTACHMENT_STORE (store));
        g_return_if_fail (E_IS_ATTACHMENT (attachment));
        g_return_if_fail (E_IS_MAIL_DISPLAY (display));
 
-       g_signal_connect (attachment, "notify",
-               G_CALLBACK (mail_display_attachment_notify_cb), display);
+       flags = e_attachment_get_initially_shown (attachment) ? E_ATTACHMENT_FLAG_VISIBLE : 0;
+
+       g_hash_table_insert (display->priv->attachment_flags, attachment, GUINT_TO_POINTER (flags));
 }
 
 static void
@@ -814,8 +1094,7 @@ mail_display_attachment_removed_cb (EAttachmentStore *store,
        g_return_if_fail (E_IS_ATTACHMENT (attachment));
        g_return_if_fail (E_IS_MAIL_DISPLAY (display));
 
-       g_signal_handlers_disconnect_by_func (attachment,
-               G_CALLBACK (mail_display_attachment_notify_cb), display);
+       g_hash_table_remove (display->priv->attachment_flags, attachment);
 }
 
 static void
@@ -1077,10 +1356,13 @@ mail_display_dispose (GObject *object)
                        G_CALLBACK (mail_display_attachment_removed_cb), object);
        }
 
+       e_mail_display_set_attachment_view (E_MAIL_DISPLAY (object), NULL);
+
        g_clear_object (&priv->part_list);
        g_clear_object (&priv->formatter);
        g_clear_object (&priv->settings);
        g_clear_object (&priv->attachment_store);
+       g_clear_object (&priv->attachment_inline_group);
 
        /* Chain up to parent's dispose() method. */
        G_OBJECT_CLASS (e_mail_display_parent_class)->dispose (object);
@@ -1104,6 +1386,7 @@ mail_display_finalize (GObject *object)
                priv->skipped_remote_content_sites = NULL;
        }
 
+       g_hash_table_destroy (priv->attachment_flags);
        g_clear_object (&priv->remote_content);
        g_mutex_unlock (&priv->remote_content_lock);
        g_mutex_clear (&priv->remote_content_lock);
@@ -1636,25 +1919,23 @@ e_mail_display_init (EMailDisplay *display)
 
        display->priv = E_MAIL_DISPLAY_GET_PRIVATE (display);
 
-       /* FIXME WK2: EAttachment::row-reference cannot be used. Steps:
-          a) open one message with attachments in the Mail window with the preview panel on
-          b) open the same message in a separate window
-             * observation - changing properties on the attachment are shown in both windows 
(expand/collapse/zoom)
-          c) close the separate window
-          d) click the arrow-down on the attachment to get its popup menu
-          A runtime warning:
-            evolution-mail-CRITICAL **: mail_display_attachment_select_path: assertion 
'gtk_tree_row_reference_valid (reference)' failed
-          is shown on the console and the popup menu is empty. Expand/collapse using the left part of the 
attachment button still works.
-       */
        display->priv->attachment_store = E_ATTACHMENT_STORE (e_attachment_store_new ());
        display->priv->attachment_view = e_weak_ref_new (NULL);
-       display->priv->old_settings = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, 
(GDestroyNotify) g_variant_unref);
+       display->priv->attachment_flags = g_hash_table_new (g_direct_hash, g_direct_equal);
+       display->priv->attachment_inline_group = gtk_action_group_new ("e-mail-display-attachment-inline");
+
+       gtk_action_group_add_actions (
+               display->priv->attachment_inline_group, attachment_inline_entries,
+               G_N_ELEMENTS (attachment_inline_entries), display);
+       gtk_action_group_set_visible (display->priv->attachment_inline_group, FALSE);
 
        g_signal_connect (display->priv->attachment_store, "attachment-added",
                G_CALLBACK (mail_display_attachment_added_cb), display);
        g_signal_connect (display->priv->attachment_store, "attachment-removed",
                G_CALLBACK (mail_display_attachment_removed_cb), display);
 
+       display->priv->old_settings = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, 
(GDestroyNotify) g_variant_unref);
+
        /* Set invalid mode so that MODE property initialization is run
         * completely (see e_mail_display_set_mode) */
        display->priv->mode = E_MAIL_FORMATTER_MODE_INVALID;
@@ -1808,11 +2089,48 @@ void
 e_mail_display_set_attachment_view (EMailDisplay *display,
                                    EAttachmentView *view)
 {
+       EAttachmentView *previous_view;
+
        g_return_if_fail (E_IS_MAIL_DISPLAY (display));
-       g_return_if_fail (E_IS_ATTACHMENT_VIEW (view));
+       if (view)
+               g_return_if_fail (E_IS_ATTACHMENT_VIEW (view));
+
+       previous_view = g_weak_ref_get (display->priv->attachment_view);
+       if (previous_view) {
+               GtkUIManager *ui_manager;
+
+               ui_manager = e_attachment_view_get_ui_manager (previous_view);
+               if (ui_manager) {
+                       gtk_ui_manager_remove_ui (ui_manager, display->priv->attachment_inline_ui_id);
+                       display->priv->attachment_inline_ui_id = 0;
+
+                       gtk_ui_manager_remove_action_group (ui_manager, 
display->priv->attachment_inline_group);
+               }
+
+               g_clear_object (&previous_view);
+       }
 
        g_weak_ref_set (display->priv->attachment_view, view);
 
+       if (view) {
+               GtkUIManager *ui_manager;
+
+               ui_manager = e_attachment_view_get_ui_manager (view);
+               if (ui_manager) {
+                       GError *error = NULL;
+
+                       gtk_ui_manager_insert_action_group (ui_manager, 
display->priv->attachment_inline_group, -1);
+
+                       display->priv->attachment_inline_ui_id = gtk_ui_manager_add_ui_from_string 
(ui_manager,
+                               attachment_popup_ui, -1, &error);
+
+                       if (error) {
+                               g_warning ("%s: Failed to read attachment_popup_ui: %s", G_STRFUNC, 
error->message);
+                               g_clear_error (&error);
+                       }
+               }
+       }
+
        g_object_notify (G_OBJECT (display), "attachment-view");
 }
 
diff --git a/mail/e-mail-request.c b/mail/e-mail-request.c
index 816227f..649269f 100644
--- a/mail/e-mail-request.c
+++ b/mail/e-mail-request.c
@@ -183,30 +183,22 @@ mail_request_process_mail_sync (EContentRequest *request,
                                g_free (tmp);
 
                                if (can_use) {
-                                       GtkTreeRowReference *reference;
+                                       GtkTreeIter iter;
 
-                                       reference = e_attachment_get_reference (attachment);
-                                       if (gtk_tree_row_reference_valid (reference)) {
-                                               GtkTreePath *path;
-                                               GtkTreeIter iter;
+                                       if (e_attachment_store_find_attachment_iter (attachment_store, 
attachment, &iter)) {
+                                               GIcon *icon = NULL;
 
-                                               path = gtk_tree_row_reference_get_path (reference);
-                                               if (gtk_tree_model_get_iter (GTK_TREE_MODEL 
(attachment_store), &iter, path)) {
-                                                       GIcon *icon = NULL;
+                                               gtk_tree_model_get (GTK_TREE_MODEL (attachment_store), &iter,
+                                                       E_ATTACHMENT_STORE_COLUMN_ICON, &icon,
+                                                       -1);
 
-                                                       gtk_tree_model_get (GTK_TREE_MODEL 
(attachment_store), &iter,
-                                                               E_ATTACHMENT_STORE_COLUMN_ICON, &icon,
-                                                               -1);
+                                               if (icon) {
+                                                       const gchar *size = g_hash_table_lookup (uri_query, 
"size");
+                                                       if (!size)
+                                                               size = "16";
 
-                                                       if (icon) {
-                                                               const gchar *size = g_hash_table_lookup 
(uri_query, "size");
-                                                               if (!size)
-                                                                       size = "16";
-
-                                                               save_gicon_to_stream (icon, atoi (size), 
output_stream, &use_mime_type);
-                                                       }
+                                                       save_gicon_to_stream (icon, atoi (size), 
output_stream, &use_mime_type);
                                                }
-                                               gtk_tree_path_free (path);
                                        }
 
                                        break;


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