aboutsummaryrefslogtreecommitdiffstats
path: root/mail/e-mail-printer.c
diff options
context:
space:
mode:
Diffstat (limited to 'mail/e-mail-printer.c')
-rw-r--r--mail/e-mail-printer.c859
1 files changed, 859 insertions, 0 deletions
diff --git a/mail/e-mail-printer.c b/mail/e-mail-printer.c
new file mode 100644
index 0000000000..f0fb8412a5
--- /dev/null
+++ b/mail/e-mail-printer.c
@@ -0,0 +1,859 @@
+/*
+ * 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/>
+ *
+ * Copyright (C) 2011 Dan Vratil <dvratil@redhat.com>
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <string.h>
+#include <glib/gi18n.h>
+#include <gtk/gtk.h>
+
+#include <e-util/e-print.h>
+#include <e-util/e-marshal.h>
+
+#include <webkit/webkitdom.h>
+
+#include "e-mail-printer.h"
+#include "em-format-html-print.h"
+#include "e-mail-display.h"
+
+static gpointer parent_class = NULL;
+
+enum {
+ BUTTON_SELECT_ALL,
+ BUTTON_SELECT_NONE,
+ BUTTON_TOP,
+ BUTTON_UP,
+ BUTTON_DOWN,
+ BUTTON_BOTTOM,
+ BUTTONS_COUNT
+};
+
+#define w(x)
+
+struct _EMailPrinterPrivate {
+ EMFormatHTMLPrint *efhp;
+
+ gboolean export_mode;
+
+ GtkListStore *headers;
+
+ WebKitWebView *webview; /* WebView to print from */
+ gchar *uri;
+ GtkWidget *buttons[BUTTONS_COUNT];
+ GtkWidget *treeview;
+
+ GtkPrintOperation *operation;
+};
+
+G_DEFINE_TYPE (
+ EMailPrinter,
+ e_mail_printer,
+ G_TYPE_OBJECT);
+
+enum {
+ PROP_0,
+ PROP_PRINT_FORMATTER
+};
+
+enum {
+ SIGNAL_DONE,
+ LAST_SIGNAL
+};
+
+enum {
+ COLUMN_ACTIVE,
+ COLUMN_HEADER_NAME,
+ COLUMN_HEADER_VALUE,
+ COLUMN_HEADER_STRUCT,
+ LAST_COLUMN
+};
+
+static guint signals[LAST_SIGNAL];
+
+static gint
+emp_header_name_equal (const EMFormatHeader *h1,
+ const EMFormatHeader *h2)
+{
+ 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;
+ }
+}
+
+static void
+emp_draw_footer (GtkPrintOperation *operation,
+ GtkPrintContext *context,
+ gint page_nr)
+{
+ PangoFontDescription *desc;
+ PangoLayout *layout;
+ gint n_pages;
+ gdouble width, height;
+ gchar *text;
+ cairo_t *cr;
+
+ cr = gtk_print_context_get_cairo_context (context);
+ width = gtk_print_context_get_width (context);
+ height = gtk_print_context_get_height (context);
+
+ g_object_get (operation, "n-pages", &n_pages, NULL);
+ text = g_strdup_printf (_("Page %d of %d"), page_nr + 1, n_pages);
+
+ cairo_set_source_rgb (cr, 0.1, 0.1, 0.1);
+ cairo_fill (cr);
+
+ desc = pango_font_description_from_string ("Sans Regular 10");
+ layout = gtk_print_context_create_pango_layout (context);
+ pango_layout_set_alignment (layout, PANGO_ALIGN_CENTER);
+ pango_layout_set_font_description (layout, desc);
+ pango_layout_set_text (layout, text, -1);
+ pango_layout_set_width (layout, width * PANGO_SCALE);
+ pango_font_description_free (desc);
+
+ cairo_move_to (cr, 0, height + 5);
+ pango_cairo_show_layout (cr, layout);
+
+ g_object_unref (layout);
+ g_free (text);
+}
+
+static void
+emp_printing_done (GtkPrintOperation *operation,
+ GtkPrintOperationResult result,
+ gpointer user_data)
+{
+ EMailPrinter *emp = user_data;
+
+ g_signal_emit (emp, signals[SIGNAL_DONE], 0, operation, result);
+}
+
+static void
+emp_start_printing (GObject *object,
+ GParamSpec *pspec,
+ gpointer user_data)
+{
+ WebKitWebView *web_view;
+ WebKitWebFrame *frame;
+ WebKitLoadStatus load_status;
+ EMailPrinter *emp = user_data;
+
+ web_view = WEBKIT_WEB_VIEW (object);
+ load_status = webkit_web_view_get_load_status (web_view);
+
+ if (load_status != WEBKIT_LOAD_FINISHED)
+ return;
+
+ frame = webkit_web_view_get_main_frame (web_view);
+
+ if (emp->priv->export_mode) {
+ gtk_print_operation_set_export_filename (
+ emp->priv->operation,
+ emp->priv->efhp->export_filename);
+ webkit_web_frame_print_full (
+ frame, emp->priv->operation,
+ GTK_PRINT_OPERATION_ACTION_EXPORT, NULL);
+ } else {
+ webkit_web_frame_print_full
+ (frame, emp->priv->operation,
+ GTK_PRINT_OPERATION_ACTION_PRINT_DIALOG, NULL);
+ }
+
+}
+
+static void
+emp_run_print_operation (EMailPrinter *emp)
+{
+ EMFormat *emf;
+ SoupSession *session;
+ GHashTable *formatters;
+ gchar *mail_uri;
+
+ emf = EM_FORMAT (emp->priv->efhp);
+ mail_uri = em_format_build_mail_uri (emf->folder, emf->message_uid, NULL, NULL);
+
+ /* It's safe to assume that session exists and contains formatters table,
+ * because at least the message we are about to print now must be already
+ * there */
+ session = webkit_get_default_session ();
+ formatters = g_object_get_data (G_OBJECT (session), "formatters");
+ g_hash_table_insert (formatters, g_strdup (mail_uri), emp->priv->efhp);
+
+ /* Print_layout is a special EMPart created by EMFormatHTMLPrint */
+ if (emp->priv->uri)
+ g_free (emp->priv->uri);
+
+ emp->priv->uri = g_strconcat (mail_uri, "?part_id=print_layout&__evo-load-images=1", NULL);
+
+ if (emp->priv->webview == NULL) {
+ emp->priv->webview = g_object_new (E_TYPE_MAIL_DISPLAY, NULL);
+ e_web_view_set_enable_frame_flattening (E_WEB_VIEW (emp->priv->webview), FALSE);
+ e_mail_display_set_force_load_images (
+ E_MAIL_DISPLAY (emp->priv->webview), TRUE);
+ g_object_ref_sink (emp->priv->webview);
+ g_signal_connect (emp->priv->webview, "notify::load-status",
+ G_CALLBACK (emp_start_printing), emp);
+
+ w ({
+ GtkWidget *window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
+ GtkWidget *sw = gtk_scrolled_window_new (NULL, NULL);
+ gtk_container_add (GTK_CONTAINER (window), sw);
+ gtk_container_add (GTK_CONTAINER (sw),
+ GTK_WIDGET (emp->priv->webview));
+ gtk_widget_show_all (window);
+ });
+ }
+
+ e_mail_display_set_formatter (E_MAIL_DISPLAY (emp->priv->webview),
+ (EMFormatHTML *) emp->priv->efhp);
+
+ webkit_web_view_load_uri (emp->priv->webview, emp->priv->uri);
+
+ g_free (mail_uri);
+}
+
+static void
+set_header_visible (EMailPrinter *emp,
+ EMFormatHeader *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;
+ EMFormatHeader *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 {
+ EMFormatHeader *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 void
+emp_set_formatter (EMailPrinter *emp,
+ EMFormatHTMLPrint *formatter)
+{
+ EMFormat *emf = (EMFormat *) formatter;
+ CamelMediumHeader *header;
+ GArray *headers;
+ gint i;
+ GtkTreeIter last_known;
+
+ g_return_if_fail (EM_IS_FORMAT_HTML_PRINT (formatter));
+
+ g_object_ref (formatter);
+
+ if (emp->priv->efhp)
+ g_object_unref (emp->priv->efhp);
+
+ emp->priv->efhp = formatter;
+
+ if (emp->priv->headers)
+ g_object_unref (emp->priv->headers);
+ emp->priv->headers = gtk_list_store_new (5,
+ G_TYPE_BOOLEAN, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_POINTER, G_TYPE_INT);
+
+ headers = camel_medium_get_headers (CAMEL_MEDIUM (emf->message));
+ if (!headers)
+ return;
+
+ for (i = 0; i < headers->len; i++) {
+ GtkTreeIter iter;
+ GList *found_header;
+ EMFormatHeader *emfh;
+
+ header = &g_array_index (headers, CamelMediumHeader, i);
+ emfh = em_format_header_new (header->name, header->value);
+
+ found_header = g_queue_find_custom (&EM_FORMAT (formatter)->header_list,
+ emfh, (GCompareFunc) emp_header_name_equal);
+
+ if (!found_header) {
+ emfh->flags |= EM_FORMAT_HTML_HEADER_HIDDEN;
+ em_format_add_header_struct (EM_FORMAT (formatter), emfh);
+ gtk_list_store_append (emp->priv->headers, &iter);
+ } else {
+ if (gtk_list_store_iter_is_valid (emp->priv->headers, &last_known))
+ gtk_list_store_insert_after (emp->priv->headers, &iter, &last_known);
+ else
+ gtk_list_store_insert_after (emp->priv->headers, &iter, NULL);
+
+ last_known = iter;
+ }
+
+ gtk_list_store_set (emp->priv->headers, &iter,
+ COLUMN_ACTIVE, (found_header != NULL),
+ COLUMN_HEADER_NAME, emfh->name,
+ COLUMN_HEADER_VALUE, emfh->value,
+ COLUMN_HEADER_STRUCT, emfh, -1);
+ }
+
+ camel_medium_free_headers (CAMEL_MEDIUM (emf->message), headers);
+}
+
+static void
+emp_set_property (GObject *object,
+ guint property_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ EMailPrinter *emp = E_MAIL_PRINTER (object);
+
+ switch (property_id) {
+
+ case PROP_PRINT_FORMATTER:
+ emp_set_formatter (emp, g_value_get_object (value));
+ return;
+ }
+
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+}
+
+static void
+emp_get_property (GObject *object,
+ guint property_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ EMailPrinter *emp = E_MAIL_PRINTER (object);
+
+ switch (property_id) {
+
+ case PROP_PRINT_FORMATTER:
+ g_value_set_object (value,
+ e_mail_printer_get_print_formatter (emp));
+ return;
+ }
+
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+}
+
+static void
+emp_finalize (GObject *object)
+{
+ EMailPrinterPrivate *priv = E_MAIL_PRINTER (object)->priv;
+
+ if (priv->efhp) {
+ g_object_unref (priv->efhp);
+ priv->efhp = NULL;
+ }
+
+ if (priv->headers) {
+ GtkTreeIter iter;
+
+ if (gtk_tree_model_get_iter_first (GTK_TREE_MODEL (priv->headers), &iter)) {
+ do {
+ EMFormatHeader *header = NULL;
+ gtk_tree_model_get (GTK_TREE_MODEL (priv->headers), &iter,
+ COLUMN_HEADER_STRUCT, &header, -1);
+ em_format_header_free (header);
+ } while (gtk_tree_model_iter_next (GTK_TREE_MODEL (priv->headers), &iter));
+ }
+ g_object_unref (priv->headers);
+ priv->headers = NULL;
+ }
+
+ if (priv->webview) {
+ g_object_unref (priv->webview);
+ priv->webview = NULL;
+ }
+
+ if (priv->uri) {
+ g_free (priv->uri);
+ priv->uri = NULL;
+ }
+
+ if (priv->operation) {
+ g_object_unref (priv->operation);
+ priv->operation = NULL;
+ }
+
+ /* Chain up to parent's finalize() method. */
+ G_OBJECT_CLASS (parent_class)->finalize (object);
+}
+
+static void
+e_mail_printer_class_init (EMailPrinterClass *klass)
+{
+ GObjectClass *object_class;
+
+ parent_class = g_type_class_peek_parent (klass);
+ g_type_class_add_private (klass, sizeof (EMailPrinterPrivate));
+
+ object_class = G_OBJECT_CLASS (klass);
+ object_class->set_property = emp_set_property;
+ object_class->get_property = emp_get_property;
+ object_class->finalize = emp_finalize;
+
+ g_object_class_install_property (
+ object_class,
+ PROP_PRINT_FORMATTER,
+ g_param_spec_object (
+ "print-formatter",
+ NULL,
+ NULL,
+ EM_TYPE_FORMAT_HTML_PRINT,
+ G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
+
+ signals[SIGNAL_DONE] = g_signal_new ("done",
+ G_TYPE_FROM_CLASS (klass),
+ G_SIGNAL_RUN_FIRST,
+ G_STRUCT_OFFSET (EMailPrinterClass, done),
+ NULL, NULL,
+ e_marshal_VOID__OBJECT_INT,
+ G_TYPE_NONE, 2,
+ GTK_TYPE_PRINT_OPERATION, G_TYPE_INT);
+}
+
+static void
+e_mail_printer_init (EMailPrinter *emp)
+{
+ emp->priv = G_TYPE_INSTANCE_GET_PRIVATE (
+ emp, E_TYPE_MAIL_PRINTER, EMailPrinterPrivate);
+
+ emp->priv->efhp = NULL;
+ emp->priv->headers = NULL;
+ emp->priv->webview = NULL;
+}
+
+EMailPrinter *
+e_mail_printer_new (EMFormatHTML * source)
+{
+ EMailPrinter *emp;
+ EMFormatHTMLPrint *efhp;
+
+ efhp = em_format_html_print_new (source);
+
+ emp = g_object_new (E_TYPE_MAIL_PRINTER,
+ "print-formatter", efhp, NULL);
+
+ g_object_unref (efhp);
+
+ return emp;
+}
+
+void
+e_mail_printer_print (EMailPrinter *emp,
+ gboolean export_mode,
+ GCancellable *cancellable)
+{
+ g_return_if_fail (E_IS_MAIL_PRINTER (emp));
+
+ if (emp->priv->operation)
+ g_object_unref (emp->priv->operation);
+ emp->priv->operation = e_print_operation_new ();
+ gtk_print_operation_set_unit (emp->priv->operation, GTK_UNIT_PIXEL);
+
+ gtk_print_operation_set_show_progress (emp->priv->operation, TRUE);
+ g_signal_connect (emp->priv->operation, "create-custom-widget",
+ G_CALLBACK (emp_create_headers_tab), emp);
+ g_signal_connect (emp->priv->operation, "done",
+ G_CALLBACK (emp_printing_done), emp);
+ g_signal_connect (emp->priv->operation, "draw-page",
+ G_CALLBACK (emp_draw_footer), NULL);
+
+ emp->priv->export_mode = export_mode;
+
+ if (cancellable)
+ g_signal_connect_swapped (cancellable, "cancelled",
+ G_CALLBACK (gtk_print_operation_cancel), emp->priv->operation);
+
+ emp_run_print_operation (emp);
+}
+
+const gchar *
+e_mail_printer_get_export_filename (EMailPrinter *printer)
+{
+ g_return_val_if_fail (E_IS_MAIL_PRINTER (printer), NULL);
+
+ if (!printer->priv->efhp)
+ return NULL;
+
+ return printer->priv->efhp->export_filename;
+}
+
+void
+e_mail_printer_set_export_filename (EMailPrinter *printer,
+ const gchar *filename)
+{
+ g_return_if_fail (E_IS_MAIL_PRINTER (printer));
+ g_return_if_fail (printer->priv->efhp != NULL);
+
+ if (printer->priv->efhp->export_filename && *printer->priv->efhp->export_filename)
+ g_free (printer->priv->efhp->export_filename);
+
+ printer->priv->efhp->export_filename = g_strdup (filename);
+}
+
+EMFormatHTMLPrint *
+e_mail_printer_get_print_formatter (EMailPrinter *emp)
+{
+ g_return_val_if_fail (E_IS_MAIL_PRINTER (emp), NULL);
+
+ return emp->priv->efhp;
+}
+