[evolution/wip/webkit2] Finish the second leftover (of 2) from the EAttachmentBar changes (Do not access EAttachmentStore fr
- From: Milan Crha <mcrha src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [evolution/wip/webkit2] Finish the second leftover (of 2) from the EAttachmentBar changes (Do not access EAttachmentStore fr
- Date: Thu, 2 Jun 2016 18:26:37 +0000 (UTC)
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]