diff options
Diffstat (limited to 'mail')
-rw-r--r-- | mail/Makefile.am | 2 | ||||
-rw-r--r-- | mail/e-mail-print-config-headers.c | 659 | ||||
-rw-r--r-- | mail/e-mail-print-config-headers.h | 69 | ||||
-rw-r--r-- | mail/e-mail-printer.c | 542 |
4 files changed, 774 insertions, 498 deletions
diff --git a/mail/Makefile.am b/mail/Makefile.am index 8ce0a08f1d..61dc4c3379 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 0000000000..20705004f2 --- /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 0000000000..5b7d923a07 --- /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 2d5af9159d..68ee6ba65b 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, |