[evolution] Add EMailPrintConfigHeaders.



commit 27c92e7f3d166e0ab38ad8d652b3c5079a86cddb
Author: Matthew Barnes <mbarnes redhat com>
Date:   Sat May 11 16:05:22 2013 -0400

    Add EMailPrintConfigHeaders.
    
    This splits the print dialog's "Headers" tab into a separate widget.
    
    EMailPrintConfigHeaders takes an EMailPartHeaders and displays its print
    model, which is a representation of all message headers (except subject)
    with an on/off flag for each.  The headers can be toggled and reordered,
    and the changes are written back to the print model.
    
    During printing, EMailFormatterPrintHeaders uses the same print model
    to determine which headers to show and in what order (except subject).
    
    This approach is much saner than the old method, which was trying to
    manipulate WebKitWebView DOM directly to toggle and reorder headers.
    This approach also happens to work, whereas the old method did not.

 em-format/e-mail-formatter-print-headers.c |   67 ++--
 mail/Makefile.am                           |    2 +
 mail/e-mail-print-config-headers.c         |  659 ++++++++++++++++++++++++++++
 mail/e-mail-print-config-headers.h         |   69 +++
 mail/e-mail-printer.c                      |  542 ++---------------------
 po/POTFILES.in                             |    1 +
 6 files changed, 810 insertions(+), 530 deletions(-)
---
diff --git a/em-format/e-mail-formatter-print-headers.c b/em-format/e-mail-formatter-print-headers.c
index 3eb1885..29aa93a 100644
--- a/em-format/e-mail-formatter-print-headers.c
+++ b/em-format/e-mail-formatter-print-headers.c
@@ -31,6 +31,7 @@
 #include "e-mail-formatter-print.h"
 #include "e-mail-formatter-utils.h"
 #include "e-mail-inline-filter.h"
+#include "e-mail-part-headers.h"
 
 typedef EMailFormatterExtension EMailFormatterPrintHeaders;
 typedef EMailFormatterExtensionClass EMailFormatterPrintHeadersClass;
@@ -55,17 +56,22 @@ emfpe_headers_format (EMailFormatterExtension *extension,
                       CamelStream *stream,
                       GCancellable *cancellable)
 {
+       EMailPartHeaders *headers_part;
+       GtkTreeModel *tree_model;
+       GtkTreeIter iter;
+       gboolean iter_valid;
        GString *str, *tmp;
        gchar *subject;
        const gchar *buf;
        gint attachments_count;
        gchar *part_id_prefix;
        CamelMimePart *mime_part;
-       GQueue *headers_queue;
        GQueue queue = G_QUEUE_INIT;
        GList *head, *link;
        const gchar *part_id;
 
+       g_return_val_if_fail (E_IS_MAIL_PART_HEADERS (part), FALSE);
+
        mime_part = e_mail_part_ref_mime_part (part);
 
        buf = camel_medium_get_header (CAMEL_MEDIUM (mime_part), "subject");
@@ -79,42 +85,39 @@ emfpe_headers_format (EMailFormatterExtension *extension,
                "<table border=\"0\" cellspacing=\"5\" "
                "cellpadding=\"0\" class=\"printing-header\">\n");
 
-       headers_queue = e_mail_formatter_dup_headers (formatter);
-       for (link = headers_queue->head; link != NULL; link = g_list_next (link)) {
-               EMailFormatterHeader *header = link->data;
-
-               /* Skip 'Subject' header, it's already displayed. */
-               if (g_ascii_strncasecmp (header->name, "Subject", 7) == 0)
-                       continue;
-
-               if (header->value && *header->value) {
+       headers_part = E_MAIL_PART_HEADERS (part);
+       tree_model = e_mail_part_headers_ref_print_model (headers_part);
+       iter_valid = gtk_tree_model_get_iter_first (tree_model, &iter);
+
+       while (iter_valid) {
+               gchar *header_name = NULL;
+               gchar *header_value = NULL;
+               gboolean include = FALSE;
+
+               gtk_tree_model_get (
+                       tree_model, &iter,
+                       E_MAIL_PART_HEADERS_PRINT_MODEL_COLUMN_INCLUDE,
+                       &include,
+                       E_MAIL_PART_HEADERS_PRINT_MODEL_COLUMN_HEADER_NAME,
+                       &header_name,
+                       E_MAIL_PART_HEADERS_PRINT_MODEL_COLUMN_HEADER_VALUE,
+                       &header_value,
+                       -1);
+
+               if (include)
                        e_mail_formatter_format_header (
                                formatter, str,
-                               header->name,
-                               header->value,
-                               header->flags | E_MAIL_FORMATTER_HEADER_FLAG_NOLINKS,
+                               header_name, header_value,
+                               E_MAIL_FORMATTER_HEADER_FLAG_NOLINKS,
                                "UTF-8");
-               } else {
-                       CamelMimeMessage *message;
-                       const gchar *header_value;
-
-                       message = e_mail_part_list_get_message (context->part_list);
-
-                       header_value = camel_medium_get_header (
-                               CAMEL_MEDIUM (message), header->name);
-
-                       if (header_value != NULL && *header_value != '\0') {
-                               e_mail_formatter_format_header (
-                                       formatter, str,
-                                       header->name,
-                                       header_value,
-                                       header->flags | E_MAIL_FORMATTER_HEADER_FLAG_NOLINKS,
-                                       "UTF-8");
-                       }
-               }
+
+               g_free (header_name);
+               g_free (header_value);
+
+               iter_valid = gtk_tree_model_iter_next (tree_model, &iter);
        }
 
-       g_queue_free_full (headers_queue, (GDestroyNotify) e_mail_formatter_header_free);
+       g_object_unref (tree_model);
 
        /* Get prefix of this PURI */
        part_id = e_mail_part_get_id (part);
diff --git a/mail/Makefile.am b/mail/Makefile.am
index 8ce0a08..61dc4c3 100644
--- a/mail/Makefile.am
+++ b/mail/Makefile.am
@@ -75,6 +75,7 @@ mailinclude_HEADERS =                                 \
        e-mail-message-pane.h                           \
        e-mail-migrate.h                                \
        e-mail-paned-view.h                             \
+       e-mail-print-config-headers.h                   \
        e-mail-printer.h                                \
        e-mail-reader-utils.h                           \
        e-mail-reader.h                                 \
@@ -148,6 +149,7 @@ libevolution_mail_la_SOURCES =                              \
        e-mail-message-pane.c                           \
        e-mail-migrate.c                                \
        e-mail-paned-view.c                             \
+       e-mail-print-config-headers.c                   \
        e-mail-printer.c                                \
        e-mail-reader-utils.c                           \
        e-mail-reader.c                                 \
diff --git a/mail/e-mail-print-config-headers.c b/mail/e-mail-print-config-headers.c
new file mode 100644
index 0000000..2070500
--- /dev/null
+++ b/mail/e-mail-print-config-headers.c
@@ -0,0 +1,659 @@
+/*
+ * e-mail-print-config-headers.c
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) version 3.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with the program; if not, see <http://www.gnu.org/licenses/>
+ *
+ */
+
+#include "e-mail-print-config-headers.h"
+
+#include <config.h>
+#include <glib/gi18n-lib.h>
+
+#include <em-format/e-mail-formatter-print.h>
+
+#define E_MAIL_PRINT_CONFIG_HEADERS_GET_PRIVATE(obj) \
+       (G_TYPE_INSTANCE_GET_PRIVATE \
+       ((obj), E_TYPE_MAIL_PRINT_CONFIG_HEADERS, EMailPrintConfigHeadersPrivate))
+
+struct _EMailPrintConfigHeadersPrivate {
+       GtkTreeView *tree_view;       /* not referenced */
+       GtkWidget *go_top_button;     /* not referenced */
+       GtkWidget *go_up_button;      /* not referenced */
+       GtkWidget *go_down_button;    /* not referenced */
+       GtkWidget *go_bottom_button;  /* not referenced */
+       GtkWidget *select_all_button; /* not referenced */
+       GtkWidget *clear_button;      /* not referenced */
+
+       EMailPartHeaders *part;
+};
+
+enum {
+       PROP_0,
+       PROP_PART
+};
+
+G_DEFINE_TYPE (
+       EMailPrintConfigHeaders,
+       e_mail_print_config_headers,
+       GTK_TYPE_BOX)
+
+static GtkToolItem *
+mail_print_config_headers_new_tool_button (const gchar *icon_name)
+{
+       GIcon *icon;
+       GtkWidget *image;
+
+       icon = g_themed_icon_new_with_default_fallbacks (icon_name);
+       image = gtk_image_new_from_gicon (icon, GTK_ICON_SIZE_SMALL_TOOLBAR);
+       gtk_widget_show (image);
+       g_object_unref (icon);
+
+       return gtk_tool_button_new (image, NULL);
+}
+
+static gboolean
+mail_print_config_headers_first_row_selected (EMailPrintConfigHeaders *config)
+{
+       GtkTreeModel *tree_model;
+       GtkTreeSelection *selection;
+       GtkTreeIter iter;
+
+       tree_model = gtk_tree_view_get_model (config->priv->tree_view);
+       selection = gtk_tree_view_get_selection (config->priv->tree_view);
+
+       if (!gtk_tree_model_iter_nth_child (tree_model, &iter, NULL, 0))
+               return FALSE;
+
+       return gtk_tree_selection_iter_is_selected (selection, &iter);
+}
+
+static gboolean
+mail_print_config_headers_last_row_selected (EMailPrintConfigHeaders *config)
+{
+       GtkTreeModel *tree_model;
+       GtkTreeSelection *selection;
+       GtkTreeIter iter;
+       gint last;
+
+       tree_model = gtk_tree_view_get_model (config->priv->tree_view);
+       selection = gtk_tree_view_get_selection (config->priv->tree_view);
+
+       last = gtk_tree_model_iter_n_children (tree_model, NULL) - 1;
+       if (last < 0)
+               return FALSE;
+
+       if (!gtk_tree_model_iter_nth_child (tree_model, &iter, NULL, last))
+               return FALSE;
+
+       return gtk_tree_selection_iter_is_selected (selection, &iter);
+}
+
+static gboolean
+mail_print_config_headers_move_selection_up (EMailPrintConfigHeaders *config)
+{
+       GtkListStore *list_store;
+       GtkTreeModel *tree_model;
+       GtkTreeSelection *selection;
+       GList *list, *link;
+
+       /* Move all selected rows up one, even
+        * if the selection is not contiguous. */
+
+       if (mail_print_config_headers_first_row_selected (config))
+               return FALSE;
+
+       selection = gtk_tree_view_get_selection (config->priv->tree_view);
+       list = gtk_tree_selection_get_selected_rows (selection, &tree_model);
+
+       list_store = GTK_LIST_STORE (tree_model);
+
+       for (link = list; link != NULL; link = g_list_next (link)) {
+               GtkTreePath *path = link->data;
+               GtkTreeIter iter;
+               GtkTreeIter prev;
+
+               if (!gtk_tree_model_get_iter (tree_model, &iter, path)) {
+                       g_warn_if_reached ();
+                       continue;
+               }
+
+               prev = iter;
+               if (!gtk_tree_model_iter_previous (tree_model, &prev)) {
+                       g_warn_if_reached ();
+                       continue;
+               }
+
+               gtk_list_store_swap (list_store, &iter, &prev);
+       }
+
+       g_list_free_full (list, (GDestroyNotify) gtk_tree_path_free);
+
+       return TRUE;
+}
+
+static gboolean
+mail_print_config_headers_move_selection_down (EMailPrintConfigHeaders *config)
+{
+       GtkListStore *list_store;
+       GtkTreeModel *tree_model;
+       GtkTreeSelection *selection;
+       GList *list, *link;
+
+       /* Move all selected rows down one, even
+        * if the selection is not contiguous. */
+
+       if (mail_print_config_headers_last_row_selected (config))
+               return FALSE;
+
+       selection = gtk_tree_view_get_selection (config->priv->tree_view);
+       list = gtk_tree_selection_get_selected_rows (selection, &tree_model);
+
+       /* Reverse the list so we don't disturb rows we've already moved. */
+       list = g_list_reverse (list);
+
+       list_store = GTK_LIST_STORE (tree_model);
+
+       for (link = list; link != NULL; link = g_list_next (link)) {
+               GtkTreePath *path = link->data;
+               GtkTreeIter iter;
+               GtkTreeIter next;
+
+               if (!gtk_tree_model_get_iter (tree_model, &iter, path)) {
+                       g_warn_if_reached ();
+                       continue;
+               }
+
+               next = iter;
+               if (!gtk_tree_model_iter_next (tree_model, &next)) {
+                       g_warn_if_reached ();
+                       continue;
+               }
+
+               gtk_list_store_swap (list_store, &iter, &next);
+       }
+
+       g_list_free_full (list, (GDestroyNotify) gtk_tree_path_free);
+
+       return TRUE;
+}
+
+static void
+mail_print_config_headers_scroll_to_cursor (EMailPrintConfigHeaders *config)
+{
+       GtkTreePath *path = NULL;
+
+       gtk_tree_view_get_cursor (config->priv->tree_view, &path, NULL);
+
+       if (path != NULL) {
+               gtk_tree_view_scroll_to_cell (
+                       config->priv->tree_view,
+                       path, NULL, FALSE, 0.0, 0.0);
+               gtk_tree_path_free (path);
+       }
+}
+
+static void
+mail_print_config_headers_update_buttons (EMailPrintConfigHeaders *config)
+{
+       GtkWidget *widget;
+       GtkTreeModel *tree_model;
+       GtkTreeSelection *selection;
+       gboolean first_row_selected;
+       gboolean last_row_selected;
+       gboolean sensitive;
+       gint n_selected_rows;
+       gint n_rows;
+
+       tree_model = gtk_tree_view_get_model (config->priv->tree_view);
+       selection = gtk_tree_view_get_selection (config->priv->tree_view);
+
+       n_rows = gtk_tree_model_iter_n_children (tree_model, NULL);
+       n_selected_rows = gtk_tree_selection_count_selected_rows (selection);
+
+       first_row_selected =
+               mail_print_config_headers_first_row_selected (config);
+       last_row_selected =
+               mail_print_config_headers_last_row_selected (config);
+
+       widget = config->priv->go_top_button;
+       sensitive = (n_selected_rows > 0 && !first_row_selected);
+       gtk_widget_set_sensitive (widget, sensitive);
+
+       widget = config->priv->go_up_button;
+       sensitive = (n_selected_rows > 0 && !first_row_selected);
+       gtk_widget_set_sensitive (widget, sensitive);
+
+       widget = config->priv->go_down_button;
+       sensitive = (n_selected_rows > 0 && !last_row_selected);
+       gtk_widget_set_sensitive (widget, sensitive);
+
+       widget = config->priv->go_bottom_button;
+       sensitive = (n_selected_rows > 0 && !last_row_selected);
+       gtk_widget_set_sensitive (widget, sensitive);
+
+       widget = config->priv->select_all_button;
+       sensitive = (n_selected_rows < n_rows);
+       gtk_widget_set_sensitive (widget, sensitive);
+
+       widget = config->priv->clear_button;
+       sensitive = (n_selected_rows > 0);
+       gtk_widget_set_sensitive (widget, sensitive);
+}
+
+static void
+mail_print_config_headers_go_top_cb (GtkToolButton *tool_button,
+                                     EMailPrintConfigHeaders *config)
+{
+       /* Not the most efficient method, but it's simple and works.
+        * There should not be so many headers that this is a major
+        * performance hit anyway. */
+       while (mail_print_config_headers_move_selection_up (config))
+               ;
+
+       mail_print_config_headers_scroll_to_cursor (config);
+       mail_print_config_headers_update_buttons (config);
+}
+
+static void
+mail_print_config_headers_go_up_cb (GtkToolButton *tool_button,
+                                    EMailPrintConfigHeaders *config)
+{
+       mail_print_config_headers_move_selection_up (config);
+
+       mail_print_config_headers_scroll_to_cursor (config);
+       mail_print_config_headers_update_buttons (config);
+}
+
+static void
+mail_print_config_headers_go_down_cb (GtkToolButton *tool_button,
+                                      EMailPrintConfigHeaders *config)
+{
+       mail_print_config_headers_move_selection_down (config);
+
+       mail_print_config_headers_scroll_to_cursor (config);
+       mail_print_config_headers_update_buttons (config);
+}
+
+static void
+mail_print_config_headers_go_bottom_cb (GtkToolButton *tool_button,
+                                        EMailPrintConfigHeaders *config)
+{
+       /* Not the most efficient method, but it's simple and works.
+        * There should not be so many headers that this is a major
+        * performance hit anyway. */
+       while (mail_print_config_headers_move_selection_down (config))
+               ;
+
+       mail_print_config_headers_scroll_to_cursor (config);
+       mail_print_config_headers_update_buttons (config);
+}
+
+static void
+mail_print_config_headers_select_all_cb (GtkToolButton *tool_button,
+                                         EMailPrintConfigHeaders *config)
+{
+       GtkTreeSelection *selection;
+
+       selection = gtk_tree_view_get_selection (config->priv->tree_view);
+       gtk_tree_selection_select_all (selection);
+
+       mail_print_config_headers_update_buttons (config);
+}
+
+static void
+mail_print_config_headers_unselect_all_cb (GtkToolButton *tool_button,
+                                           EMailPrintConfigHeaders *config)
+{
+       GtkTreeSelection *selection;
+
+       selection = gtk_tree_view_get_selection (config->priv->tree_view);
+       gtk_tree_selection_unselect_all (selection);
+
+       mail_print_config_headers_update_buttons (config);
+}
+
+static void
+mail_print_config_headers_toggled_cb (GtkCellRendererToggle *renderer,
+                                      const gchar *path_string,
+                                      EMailPrintConfigHeaders *config)
+{
+       GtkTreeModel *tree_model;
+       GtkTreeIter iter;
+       gboolean include;
+
+       tree_model = gtk_tree_view_get_model (config->priv->tree_view);
+       gtk_tree_model_get_iter_from_string (tree_model, &iter, path_string);
+
+       gtk_tree_model_get (
+               tree_model, &iter,
+               E_MAIL_PART_HEADERS_PRINT_MODEL_COLUMN_INCLUDE, &include, -1);
+
+       gtk_list_store_set (
+               GTK_LIST_STORE (tree_model), &iter,
+               E_MAIL_PART_HEADERS_PRINT_MODEL_COLUMN_INCLUDE, !include, -1);
+
+       mail_print_config_headers_update_buttons (config);
+}
+
+static void
+mail_print_config_headers_selection_changed_cb (GtkTreeSelection *selection,
+                                                EMailPrintConfigHeaders *config)
+{
+       mail_print_config_headers_update_buttons (config);
+}
+
+static void
+mail_print_config_headers_set_part (EMailPrintConfigHeaders *config,
+                                    EMailPartHeaders *part)
+{
+       g_return_if_fail (E_IS_MAIL_PART_HEADERS (part));
+       g_return_if_fail (config->priv->part == NULL);
+
+       config->priv->part = g_object_ref (part);
+}
+
+static void
+mail_print_config_headers_set_property (GObject *object,
+                                        guint property_id,
+                                        const GValue *value,
+                                        GParamSpec *pspec)
+{
+       switch (property_id) {
+               case PROP_PART:
+                       mail_print_config_headers_set_part (
+                               E_MAIL_PRINT_CONFIG_HEADERS (object),
+                               g_value_get_object (value));
+                       return;
+       }
+
+       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+}
+
+static void
+mail_print_config_headers_get_property (GObject *object,
+                                        guint property_id,
+                                        GValue *value,
+                                        GParamSpec *pspec)
+{
+       switch (property_id) {
+               case PROP_PART:
+                       g_value_take_object (
+                               value,
+                               e_mail_print_config_headers_ref_part (
+                               E_MAIL_PRINT_CONFIG_HEADERS (object)));
+                       return;
+       }
+
+       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+}
+
+static void
+mail_print_config_headers_dispose (GObject *object)
+{
+       EMailPrintConfigHeadersPrivate *priv;
+
+       priv = E_MAIL_PRINT_CONFIG_HEADERS_GET_PRIVATE (object);
+
+       g_clear_object (&priv->part);
+
+       /* Chain up to parent's dispose() method. */
+       G_OBJECT_CLASS (e_mail_print_config_headers_parent_class)->
+               dispose (object);
+}
+
+static void
+mail_print_config_headers_constructed (GObject *object)
+{
+       EMailPrintConfigHeaders *config;
+       GtkStyleContext *style_context;
+       GtkWidget *widget;
+       GtkWidget *container;
+       GtkToolItem *tool_item;
+       GtkTreeSelection *selection;
+       GtkTreeViewColumn *column;
+       GtkCellRenderer *renderer;
+       EMailPartHeaders *part;
+       GtkTreeModel *print_model;
+       const gchar *icon_name;
+       const gchar *text;
+
+       config = E_MAIL_PRINT_CONFIG_HEADERS (object);
+
+       /* Chain up to parent's constructed() method. */
+       G_OBJECT_CLASS (e_mail_print_config_headers_parent_class)->
+               constructed (object);
+
+       gtk_container_set_border_width (GTK_CONTAINER (object), 12);
+
+       gtk_orientable_set_orientation (
+               GTK_ORIENTABLE (object), GTK_ORIENTATION_VERTICAL);
+
+       container = GTK_WIDGET (object);
+
+       widget = gtk_scrolled_window_new (NULL, NULL);
+       gtk_scrolled_window_set_shadow_type (
+               GTK_SCROLLED_WINDOW (widget), GTK_SHADOW_IN);
+       gtk_box_pack_start (GTK_BOX (container), widget, TRUE, TRUE, 0);
+       gtk_widget_show (widget);
+
+       container = widget;
+
+       widget = gtk_tree_view_new ();
+       gtk_tree_view_set_reorderable (GTK_TREE_VIEW (widget), TRUE);
+       gtk_container_add (GTK_CONTAINER (container), widget);
+       config->priv->tree_view = GTK_TREE_VIEW (widget);
+       gtk_widget_show (widget);
+
+       container = GTK_WIDGET (object);
+
+       widget = gtk_toolbar_new ();
+       gtk_toolbar_set_icon_size (GTK_TOOLBAR (widget), GTK_ICON_SIZE_MENU);
+       style_context = gtk_widget_get_style_context (widget);
+       gtk_style_context_set_junction_sides (
+               style_context, GTK_JUNCTION_TOP);
+       gtk_style_context_add_class (
+               style_context, GTK_STYLE_CLASS_INLINE_TOOLBAR);
+       gtk_box_pack_start (GTK_BOX (container), widget, FALSE, FALSE, 0);
+       gtk_widget_show (widget);
+
+       container = widget;
+
+       icon_name = "go-top-symbolic";
+       tool_item = mail_print_config_headers_new_tool_button (icon_name);
+       gtk_toolbar_insert (GTK_TOOLBAR (container), tool_item, -1);
+       config->priv->go_top_button = GTK_WIDGET (tool_item);
+       gtk_widget_show (GTK_WIDGET (tool_item));
+
+       text = _("Move selection to top");
+       gtk_widget_set_tooltip_text (GTK_WIDGET (tool_item), text);
+
+       g_signal_connect (
+               tool_item, "clicked",
+               G_CALLBACK (mail_print_config_headers_go_top_cb),
+               config);
+
+       icon_name = "go-up-symbolic";
+       tool_item = mail_print_config_headers_new_tool_button (icon_name);
+       gtk_toolbar_insert (GTK_TOOLBAR (container), tool_item, -1);
+       config->priv->go_up_button = GTK_WIDGET (tool_item);
+       gtk_widget_show (GTK_WIDGET (tool_item));
+
+       text = _("Move selection up one row");
+       gtk_widget_set_tooltip_text (GTK_WIDGET (tool_item), text);
+
+       g_signal_connect (
+               tool_item, "clicked",
+               G_CALLBACK (mail_print_config_headers_go_up_cb),
+               config);
+
+       icon_name = "go-down-symbolic";
+       tool_item = mail_print_config_headers_new_tool_button (icon_name);
+       gtk_toolbar_insert (GTK_TOOLBAR (container), tool_item, -1);
+       config->priv->go_down_button = GTK_WIDGET (tool_item);
+       gtk_widget_show (GTK_WIDGET (tool_item));
+
+       text = _("Move selection down one row");
+       gtk_widget_set_tooltip_text (GTK_WIDGET (tool_item), text);
+
+       g_signal_connect (
+               tool_item, "clicked",
+               G_CALLBACK (mail_print_config_headers_go_down_cb),
+               config);
+
+       icon_name = "go-bottom-symbolic";
+       tool_item = mail_print_config_headers_new_tool_button (icon_name);
+       gtk_toolbar_insert (GTK_TOOLBAR (container), tool_item, -1);
+       config->priv->go_bottom_button = GTK_WIDGET (tool_item);
+       gtk_widget_show (GTK_WIDGET (tool_item));
+
+       text = _("Move selection to bottom");
+       gtk_widget_set_tooltip_text (GTK_WIDGET (tool_item), text);
+
+       g_signal_connect (
+               tool_item, "clicked",
+               G_CALLBACK (mail_print_config_headers_go_bottom_cb),
+               config);
+
+       icon_name = "edit-select-all-symbolic";
+       tool_item = mail_print_config_headers_new_tool_button (icon_name);
+       gtk_toolbar_insert (GTK_TOOLBAR (container), tool_item, -1);
+       config->priv->select_all_button = GTK_WIDGET (tool_item);
+       gtk_widget_show (GTK_WIDGET (tool_item));
+
+       text = _("Select all headers");
+       gtk_widget_set_tooltip_text (GTK_WIDGET (tool_item), text);
+
+       g_signal_connect (
+               tool_item, "clicked",
+               G_CALLBACK (mail_print_config_headers_select_all_cb),
+               config);
+
+       icon_name = "edit-clear-symbolic";
+       tool_item = mail_print_config_headers_new_tool_button (icon_name);
+       gtk_toolbar_insert (GTK_TOOLBAR (container), tool_item, -1);
+       config->priv->clear_button = GTK_WIDGET (tool_item);
+       gtk_widget_show (GTK_WIDGET (tool_item));
+
+       text = _("Unselect all headers");
+       gtk_widget_set_tooltip_text (GTK_WIDGET (tool_item), text);
+
+       g_signal_connect (
+               tool_item, "clicked",
+               G_CALLBACK (mail_print_config_headers_unselect_all_cb),
+               config);
+
+       column = gtk_tree_view_column_new ();
+       renderer = gtk_cell_renderer_toggle_new ();
+       gtk_tree_view_column_pack_start (column, renderer, FALSE);
+       gtk_tree_view_column_add_attribute (
+               column, renderer, "active",
+               E_MAIL_PART_HEADERS_PRINT_MODEL_COLUMN_INCLUDE);
+       gtk_tree_view_append_column (config->priv->tree_view, column);
+
+       g_signal_connect (
+               renderer, "toggled",
+               G_CALLBACK (mail_print_config_headers_toggled_cb), config);
+
+       column = gtk_tree_view_column_new ();
+       gtk_tree_view_column_set_title (column, _("Header Name"));
+       renderer = gtk_cell_renderer_text_new ();
+       gtk_tree_view_column_pack_start (column, renderer, FALSE);
+       gtk_tree_view_column_add_attribute (
+               column, renderer, "text",
+               E_MAIL_PART_HEADERS_PRINT_MODEL_COLUMN_HEADER_NAME);
+       gtk_tree_view_append_column (config->priv->tree_view, column);
+
+       column = gtk_tree_view_column_new ();
+       gtk_tree_view_column_set_title (column, _("Header Value"));
+       renderer = gtk_cell_renderer_text_new ();
+       gtk_tree_view_column_pack_start (column, renderer, FALSE);
+       gtk_tree_view_column_add_attribute (
+               column, renderer, "text",
+               E_MAIL_PART_HEADERS_PRINT_MODEL_COLUMN_HEADER_VALUE);
+       gtk_tree_view_append_column (config->priv->tree_view, column);
+
+       part = e_mail_print_config_headers_ref_part (config);
+       print_model = e_mail_part_headers_ref_print_model (part);
+       gtk_tree_view_set_model (config->priv->tree_view, print_model);
+       g_object_unref (print_model);
+       g_object_unref (part);
+
+       selection = gtk_tree_view_get_selection (config->priv->tree_view);
+       gtk_tree_selection_set_mode (selection, GTK_SELECTION_MULTIPLE);
+
+       g_signal_connect (
+               selection, "changed",
+               G_CALLBACK (mail_print_config_headers_selection_changed_cb),
+               config);
+
+       mail_print_config_headers_update_buttons (config);
+}
+
+static void
+e_mail_print_config_headers_class_init (EMailPrintConfigHeadersClass *class)
+{
+       GObjectClass *object_class;
+
+       g_type_class_add_private (
+               class, sizeof (EMailPrintConfigHeadersPrivate));
+
+       object_class = G_OBJECT_CLASS (class);
+       object_class->set_property = mail_print_config_headers_set_property;
+       object_class->get_property = mail_print_config_headers_get_property;
+       object_class->dispose = mail_print_config_headers_dispose;
+       object_class->constructed = mail_print_config_headers_constructed;
+
+       /**
+        * EMailPartConfigHeaders:part:
+        *
+        * The #EMailPartHeaders to configure.
+        **/
+       g_object_class_install_property (
+               object_class,
+               PROP_PART,
+               g_param_spec_object (
+                       "part",
+                       "Part",
+                       "The EMailPartHeaders to configure",
+                       E_TYPE_MAIL_PART_HEADERS,
+                       G_PARAM_READWRITE |
+                       G_PARAM_CONSTRUCT_ONLY |
+                       G_PARAM_STATIC_STRINGS));
+}
+
+static void
+e_mail_print_config_headers_init (EMailPrintConfigHeaders *config)
+{
+       config->priv = E_MAIL_PRINT_CONFIG_HEADERS_GET_PRIVATE (config);
+}
+
+GtkWidget *
+e_mail_print_config_headers_new (EMailPartHeaders *part)
+{
+       g_return_val_if_fail (E_IS_MAIL_PART_HEADERS (part), NULL);
+
+       return g_object_new (
+               E_TYPE_MAIL_PRINT_CONFIG_HEADERS,
+               "part", part, NULL);
+}
+
+EMailPartHeaders *
+e_mail_print_config_headers_ref_part (EMailPrintConfigHeaders *config)
+{
+       g_return_val_if_fail (E_IS_MAIL_PRINT_CONFIG_HEADERS (config), NULL);
+
+       return g_object_ref (config->priv->part);
+}
+
diff --git a/mail/e-mail-print-config-headers.h b/mail/e-mail-print-config-headers.h
new file mode 100644
index 0000000..5b7d923
--- /dev/null
+++ b/mail/e-mail-print-config-headers.h
@@ -0,0 +1,69 @@
+/*
+ * e-mail-print-config-headers.h
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) version 3.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with the program; if not, see <http://www.gnu.org/licenses/>
+ *
+ */
+
+#ifndef E_MAIL_PRINT_CONFIG_HEADERS_H
+#define E_MAIL_PRINT_CONFIG_HEADERS_H
+
+#include <em-format/e-mail-part-headers.h>
+
+/* Standard GObject macros */
+#define E_TYPE_MAIL_PRINT_CONFIG_HEADERS \
+       (e_mail_print_config_headers_get_type ())
+#define E_MAIL_PRINT_CONFIG_HEADERS(obj) \
+       (G_TYPE_CHECK_INSTANCE_CAST \
+       ((obj), E_TYPE_MAIL_PRINT_CONFIG_HEADERS, EMailPrintConfigHeaders))
+#define E_MAIL_PRINT_CONFIG_HEADERS_CLASS(cls) \
+       (G_TYPE_CHECK_CLASS_CAST \
+       ((cls), E_TYPE_MAIL_PRINT_CONFIG_HEADERS, EMailPrintConfigHeadersClass))
+#define E_IS_MAIL_PRINT_CONFIG_HEADERS(obj) \
+       (G_TYPE_CHECK_INSTANCE_TYPE \
+       ((obj), E_TYPE_MAIL_PRINT_CONFIG_HEADERS))
+#define E_IS_MAIL_PRINT_CONFIG_HEADERS_CLASS(cls) \
+       (G_TYPE_CHECK_CLASS_TYPE \
+       ((cls), E_TYPE_MAIL_PRINT_CONFIG_HEADERS))
+#define E_MAIL_PRINT_CONFIG_HEADERS_GET_CLASS(obj) \
+       (G_TYPE_INSTANCE_GET_CLASS \
+       ((obj), E_TYPE_MAIL_PRINT_CONFIG_HEADERS, EMailPrintConfigHeadersClass))
+
+G_BEGIN_DECLS
+
+typedef struct _EMailPrintConfigHeaders EMailPrintConfigHeaders;
+typedef struct _EMailPrintConfigHeadersClass EMailPrintConfigHeadersClass;
+typedef struct _EMailPrintConfigHeadersPrivate EMailPrintConfigHeadersPrivate;
+
+struct _EMailPrintConfigHeaders {
+       GtkBox parent;
+       EMailPrintConfigHeadersPrivate *priv;
+};
+
+struct _EMailPrintConfigHeadersClass {
+       GtkBoxClass parent_class;
+};
+
+GType          e_mail_print_config_headers_get_type
+                                       (void) G_GNUC_CONST;
+GtkWidget *    e_mail_print_config_headers_new
+                                       (EMailPartHeaders *part);
+EMailPartHeaders *
+               e_mail_print_config_headers_ref_part
+                                       (EMailPrintConfigHeaders *config);
+
+G_END_DECLS
+
+#endif /* E_MAIL_PRINT_CONFIG_HEADERS_H */
+
diff --git a/mail/e-mail-printer.c b/mail/e-mail-printer.c
index 2d5af91..68ee6ba 100644
--- a/mail/e-mail-printer.c
+++ b/mail/e-mail-printer.c
@@ -33,6 +33,7 @@
 
 #include "e-mail-printer.h"
 #include "e-mail-display.h"
+#include "e-mail-print-config-headers.h"
 
 #define w(x)
 
@@ -58,8 +59,6 @@ struct _EMailPrinterPrivate {
 
        gchar *export_filename;
 
-       GtkListStore *headers;
-
        WebKitWebView *webview; /* WebView to print from */
        gchar *uri;
        GtkWidget *buttons[BUTTONS_COUNT];
@@ -114,19 +113,38 @@ async_context_free (AsyncContext *async_context)
        g_slice_free (AsyncContext, async_context);
 }
 
-static gint
-mail_printer_header_name_equal (const EMailFormatterHeader *h1,
-                                const EMailFormatterHeader *h2)
+static GtkWidget *
+mail_printer_create_custom_widget_cb (GtkPrintOperation *operation,
+                                      AsyncContext *async_context)
 {
-       if ((h2->value == NULL) || (h1->value == NULL)) {
-               return g_strcmp0 (h1->name, h2->name);
-       } else {
-               if ((g_strcmp0 (h1->name, h2->name) == 0) &&
-                   (g_strcmp0 (h1->value, h2->value) == 0))
-                       return 0;
-               else
-                       return 1;
-       }
+       EMailDisplay *display;
+       EMailPartList *part_list;
+       EMailPart *part;
+       GtkWidget *widget;
+
+       gtk_print_operation_set_custom_tab_label (operation, _("Headers"));
+
+       display = E_MAIL_DISPLAY (async_context->web_view);
+       part_list = e_mail_display_get_parts_list (display);
+
+       /* FIXME Hard-coding the part ID works for now but could easily
+        *       break silently.  Need a less brittle way of extracting
+        *       specific parts by either MIME type or GType. */
+       part = e_mail_part_list_ref_part (part_list, ".message.headers");
+
+       widget = e_mail_print_config_headers_new (E_MAIL_PART_HEADERS (part));
+
+       g_object_unref (part);
+
+       return widget;
+}
+
+static void
+mail_printer_custom_widget_apply_cb (GtkPrintOperation *operation,
+                                     GtkWidget *widget,
+                                     AsyncContext *async_context)
+{
+       webkit_web_view_reload (async_context->web_view);
 }
 
 static void
@@ -166,383 +184,6 @@ mail_printer_draw_footer_cb (GtkPrintOperation *operation,
        g_free (text);
 }
 
-static void
-set_header_visible (EMailPrinter *emp,
-                    EMailFormatterHeader *header,
-                    gint index,
-                    gboolean visible)
-{
-       WebKitDOMDocument *document;
-       WebKitDOMNodeList *headers;
-       WebKitDOMElement *element;
-       WebKitDOMCSSStyleDeclaration *style;
-
-       document = webkit_web_view_get_dom_document (emp->priv->webview);
-       headers = webkit_dom_document_get_elements_by_class_name (document, "header-item");
-
-       g_return_if_fail (index < webkit_dom_node_list_get_length (headers));
-
-       element = WEBKIT_DOM_ELEMENT (webkit_dom_node_list_item (headers, index));
-       style = webkit_dom_element_get_style (element);
-       webkit_dom_css_style_declaration_set_property (
-               style,
-               "display", (visible ? "table-row" : "none"), "", NULL);
-}
-
-static void
-header_active_renderer_toggled_cb (GtkCellRendererToggle *renderer,
-                                   gchar *path,
-                                   EMailPrinter *emp)
-{
-       GtkTreeIter iter;
-       GtkTreePath *p;
-       gboolean active;
-       EMailFormatterHeader *header;
-       gint *indices;
-
-       gtk_tree_model_get_iter_from_string (
-               GTK_TREE_MODEL (emp->priv->headers),
-               &iter, path);
-
-       gtk_tree_model_get (
-               GTK_TREE_MODEL (emp->priv->headers), &iter,
-               COLUMN_ACTIVE, &active, -1);
-       gtk_tree_model_get (
-               GTK_TREE_MODEL (emp->priv->headers), &iter,
-               COLUMN_HEADER_STRUCT, &header, -1);
-       gtk_list_store_set (
-               GTK_LIST_STORE (emp->priv->headers), &iter,
-               COLUMN_ACTIVE, !active, -1);
-
-       p = gtk_tree_path_new_from_string (path);
-       indices = gtk_tree_path_get_indices (p);
-       set_header_visible (emp, header, indices[0], !active);
-       gtk_tree_path_free (p);
-}
-
-static void
-emp_headers_tab_toggle_selection (GtkWidget *button,
-                                  gpointer user_data)
-{
-       EMailPrinter *emp = user_data;
-       GtkTreeIter iter;
-       gboolean select;
-
-       if (button == emp->priv->buttons[BUTTON_SELECT_ALL])
-               select = TRUE;
-       else if (button == emp->priv->buttons[BUTTON_SELECT_NONE])
-               select = FALSE;
-       else
-               return;
-
-       if (!gtk_tree_model_get_iter_first (GTK_TREE_MODEL (emp->priv->headers), &iter))
-               return;
-
-       do {
-               EMailFormatterHeader *header;
-               GtkTreePath *path;
-               gint *indices;
-
-               gtk_tree_model_get (
-                       GTK_TREE_MODEL (emp->priv->headers), &iter,
-                       COLUMN_HEADER_STRUCT, &header, -1);
-               gtk_list_store_set (
-                       GTK_LIST_STORE (emp->priv->headers), &iter,
-                       COLUMN_ACTIVE, select, -1);
-
-               path = gtk_tree_model_get_path (GTK_TREE_MODEL (emp->priv->headers), &iter);
-               indices = gtk_tree_path_get_indices (path);
-               set_header_visible (emp, header, indices[0], select);
-               gtk_tree_path_free (path);
-
-       } while (gtk_tree_model_iter_next (GTK_TREE_MODEL (emp->priv->headers), &iter));
-}
-
-static void
-emp_headers_tab_selection_changed (GtkTreeSelection *selection,
-                                   gpointer user_data)
-{
-       EMailPrinter *emp = user_data;
-       gboolean enabled;
-       GList *selected_rows;
-       GtkTreeIter iter;
-       GtkTreeModel *model;
-       GtkTreePath *path;
-
-       if (gtk_tree_selection_count_selected_rows (selection) == 0) {
-               gtk_widget_set_sensitive (emp->priv->buttons[BUTTON_TOP], FALSE);
-               gtk_widget_set_sensitive (emp->priv->buttons[BUTTON_UP], FALSE);
-               gtk_widget_set_sensitive (emp->priv->buttons[BUTTON_DOWN], FALSE);
-               gtk_widget_set_sensitive (emp->priv->buttons[BUTTON_BOTTOM], FALSE);
-
-               return;
-       }
-
-       model = GTK_TREE_MODEL (emp->priv->headers);
-       selected_rows = gtk_tree_selection_get_selected_rows (selection, &model);
-
-       path = gtk_tree_path_copy (selected_rows->data);
-       enabled = gtk_tree_path_prev (path);
-       gtk_widget_set_sensitive (emp->priv->buttons[BUTTON_TOP], enabled);
-       gtk_widget_set_sensitive (emp->priv->buttons[BUTTON_UP], enabled);
-
-       gtk_tree_model_get_iter (model, &iter, g_list_last (selected_rows)->data);
-       enabled = gtk_tree_model_iter_next (model, &iter);
-       gtk_widget_set_sensitive (emp->priv->buttons[BUTTON_DOWN], enabled);
-       gtk_widget_set_sensitive (emp->priv->buttons[BUTTON_BOTTOM], enabled);
-
-       g_list_foreach (selected_rows, (GFunc) gtk_tree_path_free, NULL);
-       g_list_free (selected_rows);
-       gtk_tree_path_free (path);
-}
-
-static void
-emp_headers_tab_move (GtkWidget *button,
-                      gpointer user_data)
-{
-       EMailPrinter *emp = user_data;
-       GtkTreeSelection *selection;
-       GList *selected_rows, *references, *l;
-       GtkTreePath *path;
-       GtkTreeModel *model;
-       GtkTreeIter iter;
-       GtkTreeRowReference *selection_middle;
-       gint *indices;
-
-       WebKitDOMDocument *document;
-       WebKitDOMNodeList *headers;
-       WebKitDOMNode *header, *parent;
-
-       model = GTK_TREE_MODEL (emp->priv->headers);
-       selection = gtk_tree_view_get_selection  (GTK_TREE_VIEW (emp->priv->treeview));
-       selected_rows = gtk_tree_selection_get_selected_rows (selection, &model);
-
-        /* The order of header rows in the HMTL document should be in sync with
-          order of headers in the listview and in efhp->headers_list */
-       document = webkit_web_view_get_dom_document (emp->priv->webview);
-       headers = webkit_dom_document_get_elements_by_class_name (document, "header-item");
-
-       l = g_list_nth (selected_rows, g_list_length (selected_rows) / 2);
-       selection_middle = gtk_tree_row_reference_new (model, l->data);
-
-       references = NULL;
-       for (l = selected_rows; l; l = l->next) {
-               references = g_list_prepend (
-                       references,
-                       gtk_tree_row_reference_new (model, l->data));
-       }
-
-       if (button == emp->priv->buttons[BUTTON_TOP]) {
-
-               for (l = references; l; l = l->next) {
-                        /* Move the rows in the view  */
-                       path = gtk_tree_row_reference_get_path (l->data);
-                       gtk_tree_model_get_iter (model, &iter, path);
-                       gtk_list_store_move_after (emp->priv->headers, &iter, NULL);
-
-                        /* Move the header row in HTML document */
-                       indices = gtk_tree_path_get_indices (path);
-                       header = webkit_dom_node_list_item (headers, indices[0]);
-                       parent = webkit_dom_node_get_parent_node (header);
-                       webkit_dom_node_remove_child (parent, header, NULL);
-                       webkit_dom_node_insert_before (parent, header,
-                               webkit_dom_node_get_first_child (parent), NULL);
-
-                       gtk_tree_path_free (path);
-               }
-
-       } else if (button == emp->priv->buttons[BUTTON_UP]) {
-
-               GtkTreeIter *iter_prev;
-               WebKitDOMNode *node2;
-
-               references = g_list_reverse (references);
-
-               for (l = references; l; l = l->next) {
-
-                       path = gtk_tree_row_reference_get_path (l->data);
-                       gtk_tree_model_get_iter (model, &iter, path);
-                       iter_prev = gtk_tree_iter_copy (&iter);
-                       gtk_tree_model_iter_previous (model, iter_prev);
-
-                       gtk_list_store_move_before (emp->priv->headers, &iter, iter_prev);
-
-                       indices = gtk_tree_path_get_indices (path);
-                       header = webkit_dom_node_list_item (headers, indices[0]);
-                       node2 = webkit_dom_node_get_previous_sibling (header);
-                       parent = webkit_dom_node_get_parent_node (header);
-
-                       webkit_dom_node_remove_child (parent, header, NULL);
-                       webkit_dom_node_insert_before (parent, header, node2, NULL);
-
-                       gtk_tree_path_free (path);
-                       gtk_tree_iter_free (iter_prev);
-               }
-
-       } else if (button == emp->priv->buttons[BUTTON_DOWN]) {
-
-               GtkTreeIter *iter_next;
-               WebKitDOMNode *node2;
-
-               for (l = references; l; l = l->next) {
-
-                       path = gtk_tree_row_reference_get_path (l->data);
-                       gtk_tree_model_get_iter (model, &iter, path);
-                       iter_next = gtk_tree_iter_copy (&iter);
-                       gtk_tree_model_iter_next (model, iter_next);
-
-                       gtk_list_store_move_after (emp->priv->headers, &iter, iter_next);
-
-                       indices = gtk_tree_path_get_indices (path);
-                       header = webkit_dom_node_list_item (headers, indices[0]);
-                       node2 = webkit_dom_node_get_next_sibling (header);
-                       parent = webkit_dom_node_get_parent_node (header);
-
-                       webkit_dom_node_remove_child (parent, header, NULL);
-                       webkit_dom_node_insert_before (parent, header,
-                               webkit_dom_node_get_next_sibling (node2), NULL);
-
-                       gtk_tree_path_free (path);
-                       gtk_tree_iter_free (iter_next);
-               }
-
-       } else if (button == emp->priv->buttons[BUTTON_BOTTOM]) {
-
-               references = g_list_reverse (references);
-
-               for (l = references; l; l = l->next) {
-                       path = gtk_tree_row_reference_get_path (l->data);
-                       gtk_tree_model_get_iter (model, &iter, path);
-                       gtk_list_store_move_before (emp->priv->headers, &iter, NULL);
-
-                        /* Move the header row in HTML document */
-                       indices = gtk_tree_path_get_indices (path);
-                       header = webkit_dom_node_list_item (headers, indices[0]);
-                       parent = webkit_dom_node_get_parent_node (header);
-                       webkit_dom_node_remove_child (parent, header, NULL);
-                       webkit_dom_node_append_child (parent, header, NULL);
-
-                       gtk_tree_path_free (path);
-               }
-       };
-
-       g_list_foreach (references, (GFunc) gtk_tree_row_reference_free, NULL);
-       g_list_free (references);
-
-        /* Keep the selection in middle of the screen */
-       path = gtk_tree_row_reference_get_path (selection_middle);
-       gtk_tree_view_scroll_to_cell (
-               GTK_TREE_VIEW (emp->priv->treeview),
-               path, COLUMN_ACTIVE, TRUE, 0.5, 0.5);
-       gtk_tree_path_free (path);
-       gtk_tree_row_reference_free (selection_middle);
-
-       g_list_foreach (selected_rows, (GFunc) gtk_tree_path_free, NULL);
-       g_list_free (selected_rows);
-
-       emp_headers_tab_selection_changed (selection, user_data);
-}
-
-static GtkWidget *
-emp_create_headers_tab (GtkPrintOperation *operation,
-                        EMailPrinter *emp)
-{
-       GtkWidget *vbox, *hbox, *scw, *button;
-       GtkTreeView *view;
-       GtkTreeSelection *selection;
-       GtkTreeViewColumn *column;
-       GtkCellRenderer *renderer;
-
-       hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 5);
-       vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 5);
-       gtk_box_pack_end (GTK_BOX (hbox), vbox, FALSE, FALSE, 5);
-
-       emp->priv->treeview = gtk_tree_view_new_with_model (
-               GTK_TREE_MODEL (emp->priv->headers));
-       view = GTK_TREE_VIEW (emp->priv->treeview);
-       selection = gtk_tree_view_get_selection (view);
-       gtk_tree_selection_set_mode (selection, GTK_SELECTION_MULTIPLE);
-       g_signal_connect (
-               selection, "changed",
-               G_CALLBACK (emp_headers_tab_selection_changed), emp);
-
-       renderer = gtk_cell_renderer_toggle_new ();
-       g_signal_connect (
-               renderer, "toggled",
-               G_CALLBACK (header_active_renderer_toggled_cb), emp);
-       column = gtk_tree_view_column_new_with_attributes (
-               _("Print"), renderer,
-               "active", COLUMN_ACTIVE, NULL);
-       gtk_tree_view_append_column (view, column);
-
-       renderer = gtk_cell_renderer_text_new ();
-       column = gtk_tree_view_column_new_with_attributes (
-               _("Header Name"), renderer,
-               "text", COLUMN_HEADER_NAME, NULL);
-       gtk_tree_view_append_column (view, column);
-
-       renderer = gtk_cell_renderer_text_new ();
-       column = gtk_tree_view_column_new_with_attributes (
-               _("Header Value"), renderer,
-               "text", COLUMN_HEADER_VALUE, NULL);
-       gtk_tree_view_append_column (view, column);
-
-       scw = gtk_scrolled_window_new (NULL, NULL);
-       gtk_container_add (GTK_CONTAINER (scw), GTK_WIDGET (view));
-       gtk_box_pack_start (GTK_BOX (hbox), scw, TRUE, TRUE, 0);
-
-       button = gtk_button_new_from_stock (GTK_STOCK_SELECT_ALL);
-       emp->priv->buttons[BUTTON_SELECT_ALL] = button;
-       g_signal_connect (
-               button, "clicked",
-               G_CALLBACK (emp_headers_tab_toggle_selection), emp);
-       gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, TRUE, 5);
-
-       button = gtk_button_new_from_stock (GTK_STOCK_CLEAR);
-       emp->priv->buttons[BUTTON_SELECT_NONE] = button;
-       g_signal_connect (
-               button, "clicked",
-               G_CALLBACK (emp_headers_tab_toggle_selection), emp);
-       gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, TRUE, 5);
-
-       button = gtk_button_new_from_stock (GTK_STOCK_GOTO_TOP);
-       emp->priv->buttons[BUTTON_TOP] = button;
-       gtk_widget_set_sensitive (button, FALSE);
-       g_signal_connect (
-               button, "clicked",
-               G_CALLBACK (emp_headers_tab_move), emp);
-       gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, TRUE, 5);
-
-       button = gtk_button_new_from_stock (GTK_STOCK_GO_UP);
-       emp->priv->buttons[BUTTON_UP] = button;
-       gtk_widget_set_sensitive (button, FALSE);
-       g_signal_connect (
-               button, "clicked",
-               G_CALLBACK (emp_headers_tab_move), emp);
-       gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, TRUE, 5);
-
-       button = gtk_button_new_from_stock (GTK_STOCK_GO_DOWN);
-       emp->priv->buttons[BUTTON_DOWN] = button;
-       gtk_widget_set_sensitive (button, FALSE);
-       g_signal_connect (
-               button, "clicked",
-               G_CALLBACK (emp_headers_tab_move), emp);
-       gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, TRUE, 5);
-
-       button = gtk_button_new_from_stock (GTK_STOCK_GOTO_BOTTOM);
-       emp->priv->buttons[BUTTON_BOTTOM] = button;
-       gtk_widget_set_sensitive (button, FALSE);
-       g_signal_connect (
-               button, "clicked",
-               G_CALLBACK (emp_headers_tab_move), emp);
-       gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, TRUE, 5);
-
-       gtk_print_operation_set_custom_tab_label (operation, _("Headers"));
-       gtk_widget_show_all (hbox);
-
-       return hbox;
-}
-
 static gboolean
 mail_printer_print_timeout_cb (gpointer user_data)
 {
@@ -554,6 +195,7 @@ mail_printer_print_timeout_cb (gpointer user_data)
        EMailPrinter *printer;
        WebKitWebFrame *web_frame;
        gulong create_custom_widget_handler_id;
+       gulong custom_widget_apply_handler_id;
        gulong draw_page_handler_id;
        GError *error = NULL;
 
@@ -572,6 +214,7 @@ mail_printer_print_timeout_cb (gpointer user_data)
                G_ASYNC_RESULT (simple));
 
        print_operation = e_print_operation_new ();
+
        gtk_print_operation_set_show_progress (print_operation, TRUE);
        gtk_print_operation_set_unit (print_operation, GTK_UNIT_PIXEL);
 
@@ -586,7 +229,13 @@ mail_printer_print_timeout_cb (gpointer user_data)
 
        create_custom_widget_handler_id = g_signal_connect (
                print_operation, "create-custom-widget",
-               G_CALLBACK (emp_create_headers_tab), printer);
+               G_CALLBACK (mail_printer_create_custom_widget_cb),
+               async_context);
+
+       custom_widget_apply_handler_id = g_signal_connect (
+               print_operation, "custom-widget-apply",
+               G_CALLBACK (mail_printer_custom_widget_apply_cb),
+               async_context);
 
        draw_page_handler_id = g_signal_connect (
                print_operation, "draw-page",
@@ -627,6 +276,9 @@ mail_printer_print_timeout_cb (gpointer user_data)
                print_operation, create_custom_widget_handler_id);
 
        g_signal_handler_disconnect (
+               print_operation, custom_widget_apply_handler_id);
+
+       g_signal_handler_disconnect (
                print_operation, draw_page_handler_id);
 
        g_object_unref (print_operation);
@@ -696,74 +348,6 @@ mail_printer_load_status_cb (WebKitWebView *web_view,
        g_object_unref (simple);
 }
 
-static void
-mail_printer_build_model (EMailPrinter *printer,
-                          EMailPartList *part_list)
-{
-       CamelMediumHeader *header;
-       CamelMimeMessage *message;
-       GArray *headers;
-       GQueue *headers_queue;
-       gint i;
-       GtkTreeIter last_known = { 0 };
-
-       if (printer->priv->headers != NULL)
-               g_object_unref (printer->priv->headers);
-       printer->priv->headers = gtk_list_store_new (
-               5,
-               G_TYPE_BOOLEAN,  /* COLUMN_ACTIVE */
-               G_TYPE_STRING,   /* COLUMN_HEADER_NAME */
-               G_TYPE_STRING,   /* COLUMN_HEADER_VALUE */
-               G_TYPE_POINTER,  /* COLUMN_HEADER_STRUCT */
-               G_TYPE_INT);     /* ??? */
-
-       message = e_mail_part_list_get_message (part_list);
-       headers = camel_medium_get_headers (CAMEL_MEDIUM (message));
-       if (!headers)
-               return;
-
-       headers_queue = e_mail_formatter_dup_headers (printer->priv->formatter);
-       for (i = 0; i < headers->len; i++) {
-               GtkTreeIter iter;
-               GList *found_header;
-               EMailFormatterHeader *emfh;
-
-               header = &g_array_index (headers, CamelMediumHeader, i);
-               emfh = e_mail_formatter_header_new (header->name, header->value);
-
-               found_header = g_queue_find_custom (
-                       headers_queue, emfh, (GCompareFunc)
-                       mail_printer_header_name_equal);
-
-               if (!found_header) {
-                       emfh->flags |= E_MAIL_FORMATTER_HEADER_FLAG_HIDDEN;
-                       e_mail_formatter_add_header_struct (
-                               printer->priv->formatter, emfh);
-                       gtk_list_store_append (printer->priv->headers, &iter);
-               } else {
-                       if (gtk_list_store_iter_is_valid (printer->priv->headers, &last_known))
-                               gtk_list_store_insert_after (printer->priv->headers, &iter, &last_known);
-                       else
-                               gtk_list_store_insert_after (printer->priv->headers, &iter, NULL);
-
-                       last_known = iter;
-               }
-
-               gtk_list_store_set (
-                       printer->priv->headers, &iter,
-                       COLUMN_ACTIVE, (found_header != NULL),
-                       COLUMN_HEADER_NAME, emfh->name,
-                       COLUMN_HEADER_VALUE, emfh->value,
-                       COLUMN_HEADER_STRUCT, emfh, -1);
-       }
-
-       g_queue_free_full (
-               headers_queue,
-               (GDestroyNotify) e_mail_formatter_header_free);
-
-       camel_medium_free_headers (CAMEL_MEDIUM (message), headers);
-}
-
 static WebKitWebView *
 mail_printer_new_web_view (const gchar *charset,
                            const gchar *default_charset)
@@ -838,29 +422,8 @@ mail_printer_dispose (GObject *object)
 
        priv = E_MAIL_PRINTER_GET_PRIVATE (object);
 
-       if (priv->headers != NULL) {
-               GtkTreeModel *model;
-               GtkTreeIter iter;
-               gboolean valid;
-
-               model = GTK_TREE_MODEL (priv->headers);
-
-               valid = gtk_tree_model_get_iter_first (model, &iter);
-               while (valid) {
-                       EMailFormatterHeader *header = NULL;
-
-                       gtk_tree_model_get (
-                               model, &iter,
-                               COLUMN_HEADER_STRUCT, &header, -1);
-                       e_mail_formatter_header_free (header);
-
-                       valid = gtk_tree_model_iter_next (model, &iter);
-               }
-       }
-
        g_clear_object (&priv->formatter);
        g_clear_object (&priv->part_list);
-       g_clear_object (&priv->headers);
        g_clear_object (&priv->webview);
        g_clear_object (&priv->operation);
 
@@ -882,22 +445,6 @@ mail_printer_finalize (GObject *object)
 }
 
 static void
-mail_printer_constructed (GObject *object)
-{
-       EMailPrinter *printer;
-       EMailPartList *part_list;
-
-       printer = E_MAIL_PRINTER (object);
-
-       /* Chain up to parent's constructed() method. */
-       G_OBJECT_CLASS (e_mail_printer_parent_class)->constructed (object);
-
-       part_list = e_mail_printer_ref_part_list (printer);
-       mail_printer_build_model (printer, part_list);
-       g_object_unref (part_list);
-}
-
-static void
 e_mail_printer_class_init (EMailPrinterClass *class)
 {
        GObjectClass *object_class;
@@ -909,7 +456,6 @@ e_mail_printer_class_init (EMailPrinterClass *class)
        object_class->get_property = mail_printer_get_property;
        object_class->dispose = mail_printer_dispose;
        object_class->finalize = mail_printer_finalize;
-       object_class->constructed = mail_printer_constructed;
 
        g_object_class_install_property (
                object_class,
diff --git a/po/POTFILES.in b/po/POTFILES.in
index cd2e191..bd23b8b 100644
--- a/po/POTFILES.in
+++ b/po/POTFILES.in
@@ -333,6 +333,7 @@ mail/e-mail-label-list-store.c
 mail/e-mail-label-manager.c
 mail/e-mail-label-tree-view.c
 mail/e-mail-migrate.c
+mail/e-mail-print-config-headers.c
 mail/e-mail-printer.c
 mail/e-mail-reader.c
 mail/e-mail-reader-utils.c


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