diff options
Diffstat (limited to 'mail/e-mail-printer.c')
-rw-r--r-- | mail/e-mail-printer.c | 859 |
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; +} + |