No issues found
Tool | Failure ID | Location | Function | Message | Data |
---|---|---|---|---|---|
clang-analyzer | no-output-found | e-mail-printer.c | Message(text='Unable to locate XML output from invoke-clang-analyzer') | None | |
clang-analyzer | no-output-found | e-mail-printer.c | Message(text='Unable to locate XML output from invoke-clang-analyzer') | None |
1 /*
2 * This program is free software; you can redistribute it and/or
3 * modify it under the terms of the GNU Lesser General Public
4 * License as published by the Free Software Foundation; either
5 * version 2 of the License, or (at your option) version 3.
6 *
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
10 * Lesser General Public License for more details.
11 *
12 * You should have received a copy of the GNU Lesser General Public
13 * License along with the program; if not, see <http://www.gnu.org/licenses/>
14 *
15 * Copyright (C) 2011 Dan Vratil <dvratil@redhat.com>
16 *
17 */
18
19 #ifdef HAVE_CONFIG_H
20 #include <config.h>
21 #endif
22
23 #include <string.h>
24 #include <glib/gi18n.h>
25 #include <gtk/gtk.h>
26
27 #include <em-format/e-mail-formatter-print.h>
28 #include <em-format/e-mail-part-utils.h>
29
30 #include <e-util/e-print.h>
31 #include <e-util/e-marshal.h>
32
33 #include <webkit/webkitdom.h>
34
35 #include "e-mail-printer.h"
36 #include "e-mail-display.h"
37
38 enum {
39 BUTTON_SELECT_ALL,
40 BUTTON_SELECT_NONE,
41 BUTTON_TOP,
42 BUTTON_UP,
43 BUTTON_DOWN,
44 BUTTON_BOTTOM,
45 BUTTONS_COUNT
46 };
47
48 #define w(x)
49
50 struct _EMailPrinterPrivate {
51 EMailFormatterPrint *formatter;
52 EMailPartList *parts_list;
53
54 gchar *export_filename;
55
56 GtkListStore *headers;
57
58 WebKitWebView *webview; /* WebView to print from */
59 gchar *uri;
60 GtkWidget *buttons[BUTTONS_COUNT];
61 GtkWidget *treeview;
62
63 GtkPrintOperation *operation;
64 GtkPrintOperationAction print_action;
65 };
66
67 G_DEFINE_TYPE (
68 EMailPrinter,
69 e_mail_printer,
70 G_TYPE_OBJECT);
71
72 enum {
73 PROP_0,
74 PROP_PART_LIST
75 };
76
77 enum {
78 SIGNAL_DONE,
79 LAST_SIGNAL
80 };
81
82 enum {
83 COLUMN_ACTIVE,
84 COLUMN_HEADER_NAME,
85 COLUMN_HEADER_VALUE,
86 COLUMN_HEADER_STRUCT,
87 LAST_COLUMN
88 };
89
90 static guint signals[LAST_SIGNAL];
91
92 static gint
93 emp_header_name_equal (const EMailFormatterHeader *h1,
94 const EMailFormatterHeader *h2)
95 {
96 if ((h2->value == NULL) || (h1->value == NULL)) {
97 return g_strcmp0 (h1->name, h2->name);
98 } else {
99 if ((g_strcmp0 (h1->name, h2->name) == 0) &&
100 (g_strcmp0 (h1->value, h2->value) == 0))
101 return 0;
102 else
103 return 1;
104 }
105 }
106
107 static void
108 emp_draw_footer (GtkPrintOperation *operation,
109 GtkPrintContext *context,
110 gint page_nr)
111 {
112 PangoFontDescription *desc;
113 PangoLayout *layout;
114 gint n_pages;
115 gdouble width, height;
116 gchar *text;
117 cairo_t *cr;
118
119 cr = gtk_print_context_get_cairo_context (context);
120 width = gtk_print_context_get_width (context);
121 height = gtk_print_context_get_height (context);
122
123 g_object_get (operation, "n-pages", &n_pages, NULL);
124 text = g_strdup_printf (_("Page %d of %d"), page_nr + 1, n_pages);
125
126 cairo_set_source_rgb (cr, 0.1, 0.1, 0.1);
127 cairo_fill (cr);
128
129 desc = pango_font_description_from_string ("Sans Regular 10");
130 layout = gtk_print_context_create_pango_layout (context);
131 pango_layout_set_alignment (layout, PANGO_ALIGN_CENTER);
132 pango_layout_set_font_description (layout, desc);
133 pango_layout_set_text (layout, text, -1);
134 pango_layout_set_width (layout, width * PANGO_SCALE);
135 pango_font_description_free (desc);
136
137 cairo_move_to (cr, 0, height + 5);
138 pango_cairo_show_layout (cr, layout);
139
140 g_object_unref (layout);
141 g_free (text);
142 }
143
144 static void
145 emp_printing_done (GtkPrintOperation *operation,
146 GtkPrintOperationResult result,
147 gpointer user_data)
148 {
149 EMailPrinter *emp = user_data;
150
151 g_signal_emit (emp, signals[SIGNAL_DONE], 0, operation, result);
152 }
153
154 static gboolean
155 do_run_print_operation (EMailPrinter *emp)
156 {
157 WebKitWebFrame *frame;
158
159 frame = webkit_web_view_get_main_frame (emp->priv->webview);
160
161 webkit_web_frame_print_full (
162 frame, emp->priv->operation, emp->priv->print_action, NULL);
163
164 return FALSE;
165 }
166
167 static void
168 emp_start_printing (GObject *object,
169 GParamSpec *pspec,
170 gpointer user_data)
171 {
172 WebKitWebView *web_view;
173 WebKitLoadStatus load_status;
174 EMailPrinter *emp = user_data;
175
176 web_view = WEBKIT_WEB_VIEW (object);
177 load_status = webkit_web_view_get_load_status (web_view);
178
179 if (load_status != WEBKIT_LOAD_FINISHED)
180 return;
181
182 /* WebKit reloads the page once more right before starting to print, so
183 * disconnect this handler after the first time, so that we don't start
184 * another printing operation */
185 g_signal_handlers_disconnect_by_func (
186 object, emp_start_printing, user_data);
187
188 if (emp->priv->print_action == GTK_PRINT_OPERATION_ACTION_EXPORT) {
189 gtk_print_operation_set_export_filename (
190 emp->priv->operation, emp->priv->export_filename);
191 }
192
193 /* Give WebKit some time to perform layouting and rendering before
194 * we start printing. 500ms should be enough in most cases... */
195 g_timeout_add_full (
196 G_PRIORITY_DEFAULT, 500,
197 (GSourceFunc) do_run_print_operation,
198 g_object_ref (emp), g_object_unref);
199 }
200
201 static void
202 emp_run_print_operation (EMailPrinter *emp,
203 EMailFormatter *formatter)
204 {
205 gchar *mail_uri;
206 const gchar *default_charset, *charset;
207
208 default_charset = formatter ? e_mail_formatter_get_default_charset (formatter) : NULL;
209 charset = formatter ? e_mail_formatter_get_charset (formatter) : NULL;
210
211 if (!default_charset)
212 default_charset = "";
213 if (!charset)
214 charset = "";
215
216 mail_uri = e_mail_part_build_uri (
217 emp->priv->parts_list->folder,
218 emp->priv->parts_list->message_uid,
219 "__evo-load-image", G_TYPE_BOOLEAN, TRUE,
220 "mode", G_TYPE_INT, E_MAIL_FORMATTER_MODE_PRINTING,
221 "formatter_default_charset", G_TYPE_STRING, default_charset,
222 "formatter_charset", G_TYPE_STRING, charset,
223 NULL);
224
225 /* Print_layout is a special EMPart created by EMFormatHTMLPrint */
226 if (emp->priv->webview == NULL) {
227 EMailFormatter *emp_formatter;
228
229 emp->priv->webview = g_object_new (
230 E_TYPE_MAIL_DISPLAY,
231 "mode", E_MAIL_FORMATTER_MODE_PRINTING, NULL);
232 e_web_view_set_enable_frame_flattening (E_WEB_VIEW (emp->priv->webview), FALSE);
233 e_mail_display_set_force_load_images (
234 E_MAIL_DISPLAY (emp->priv->webview), TRUE);
235
236 emp_formatter = e_mail_display_get_formatter (E_MAIL_DISPLAY (emp->priv->webview));
237 if (default_charset && *default_charset)
238 e_mail_formatter_set_default_charset (emp_formatter, default_charset);
239 if (charset && *charset)
240 e_mail_formatter_set_charset (emp_formatter, charset);
241
242 g_object_ref_sink (emp->priv->webview);
243 g_signal_connect (
244 emp->priv->webview, "notify::load-status",
245 G_CALLBACK (emp_start_printing), emp);
246
247 w ({
248 GtkWidget *window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
249 GtkWidget *sw = gtk_scrolled_window_new (NULL, NULL);
250 gtk_container_add (GTK_CONTAINER (window), sw);
251 gtk_container_add (
252 GTK_CONTAINER (sw),
253 GTK_WIDGET (emp->priv->webview));
254 gtk_widget_show_all (window);
255 });
256 }
257 e_mail_display_set_parts_list (
258 E_MAIL_DISPLAY (emp->priv->webview), emp->priv->parts_list);
259 webkit_web_view_load_uri (emp->priv->webview, mail_uri);
260
261 g_free (mail_uri);
262 }
263
264 static void
265 set_header_visible (EMailPrinter *emp,
266 EMailFormatterHeader *header,
267 gint index,
268 gboolean visible)
269 {
270 WebKitDOMDocument *document;
271 WebKitDOMNodeList *headers;
272 WebKitDOMElement *element;
273 WebKitDOMCSSStyleDeclaration *style;
274
275 document = webkit_web_view_get_dom_document (emp->priv->webview);
276 headers = webkit_dom_document_get_elements_by_class_name (document, "header-item");
277
278 g_return_if_fail (index < webkit_dom_node_list_get_length (headers));
279
280 element = WEBKIT_DOM_ELEMENT (webkit_dom_node_list_item (headers, index));
281 style = webkit_dom_element_get_style (element);
282 webkit_dom_css_style_declaration_set_property (
283 style,
284 "display", (visible ? "table-row" : "none"), "", NULL);
285 }
286
287 static void
288 header_active_renderer_toggled_cb (GtkCellRendererToggle *renderer,
289 gchar *path,
290 EMailPrinter *emp)
291 {
292 GtkTreeIter iter;
293 GtkTreePath *p;
294 gboolean active;
295 EMailFormatterHeader *header;
296 gint *indices;
297
298 gtk_tree_model_get_iter_from_string (
299 GTK_TREE_MODEL (emp->priv->headers),
300 &iter, path);
301
302 gtk_tree_model_get (
303 GTK_TREE_MODEL (emp->priv->headers), &iter,
304 COLUMN_ACTIVE, &active, -1);
305 gtk_tree_model_get (
306 GTK_TREE_MODEL (emp->priv->headers), &iter,
307 COLUMN_HEADER_STRUCT, &header, -1);
308 gtk_list_store_set (
309 GTK_LIST_STORE (emp->priv->headers), &iter,
310 COLUMN_ACTIVE, !active, -1);
311
312 p = gtk_tree_path_new_from_string (path);
313 indices = gtk_tree_path_get_indices (p);
314 set_header_visible (emp, header, indices[0], !active);
315 gtk_tree_path_free (p);
316 }
317
318 static void
319 emp_headers_tab_toggle_selection (GtkWidget *button,
320 gpointer user_data)
321 {
322 EMailPrinter *emp = user_data;
323 GtkTreeIter iter;
324 gboolean select;
325
326 if (button == emp->priv->buttons[BUTTON_SELECT_ALL])
327 select = TRUE;
328 else if (button == emp->priv->buttons[BUTTON_SELECT_NONE])
329 select = FALSE;
330 else
331 return;
332
333 if (!gtk_tree_model_get_iter_first (GTK_TREE_MODEL (emp->priv->headers), &iter))
334 return;
335
336 do {
337 EMailFormatterHeader *header;
338 GtkTreePath *path;
339 gint *indices;
340
341 gtk_tree_model_get (
342 GTK_TREE_MODEL (emp->priv->headers), &iter,
343 COLUMN_HEADER_STRUCT, &header, -1);
344 gtk_list_store_set (
345 GTK_LIST_STORE (emp->priv->headers), &iter,
346 COLUMN_ACTIVE, select, -1);
347
348 path = gtk_tree_model_get_path (GTK_TREE_MODEL (emp->priv->headers), &iter);
349 indices = gtk_tree_path_get_indices (path);
350 set_header_visible (emp, header, indices[0], select);
351 gtk_tree_path_free (path);
352
353 } while (gtk_tree_model_iter_next (GTK_TREE_MODEL (emp->priv->headers), &iter));
354 }
355
356 static void
357 emp_headers_tab_selection_changed (GtkTreeSelection *selection,
358 gpointer user_data)
359 {
360 EMailPrinter *emp = user_data;
361 gboolean enabled;
362 GList *selected_rows;
363 GtkTreeIter iter;
364 GtkTreeModel *model;
365 GtkTreePath *path;
366
367 if (gtk_tree_selection_count_selected_rows (selection) == 0) {
368 gtk_widget_set_sensitive (emp->priv->buttons[BUTTON_TOP], FALSE);
369 gtk_widget_set_sensitive (emp->priv->buttons[BUTTON_UP], FALSE);
370 gtk_widget_set_sensitive (emp->priv->buttons[BUTTON_DOWN], FALSE);
371 gtk_widget_set_sensitive (emp->priv->buttons[BUTTON_BOTTOM], FALSE);
372
373 return;
374 }
375
376 model = GTK_TREE_MODEL (emp->priv->headers);
377 selected_rows = gtk_tree_selection_get_selected_rows (selection, &model);
378
379 path = gtk_tree_path_copy (selected_rows->data);
380 enabled = gtk_tree_path_prev (path);
381 gtk_widget_set_sensitive (emp->priv->buttons[BUTTON_TOP], enabled);
382 gtk_widget_set_sensitive (emp->priv->buttons[BUTTON_UP], enabled);
383
384 gtk_tree_model_get_iter (model, &iter, g_list_last (selected_rows)->data);
385 enabled = gtk_tree_model_iter_next (model, &iter);
386 gtk_widget_set_sensitive (emp->priv->buttons[BUTTON_DOWN], enabled);
387 gtk_widget_set_sensitive (emp->priv->buttons[BUTTON_BOTTOM], enabled);
388
389 g_list_foreach (selected_rows, (GFunc) gtk_tree_path_free, NULL);
390 g_list_free (selected_rows);
391 gtk_tree_path_free (path);
392 }
393
394 static void
395 emp_headers_tab_move (GtkWidget *button,
396 gpointer user_data)
397 {
398 EMailPrinter *emp = user_data;
399 GtkTreeSelection *selection;
400 GList *selected_rows, *references, *l;
401 GtkTreePath *path;
402 GtkTreeModel *model;
403 GtkTreeIter iter;
404 GtkTreeRowReference *selection_middle;
405 gint *indices;
406
407 WebKitDOMDocument *document;
408 WebKitDOMNodeList *headers;
409 WebKitDOMNode *header, *parent;
410
411 model = GTK_TREE_MODEL (emp->priv->headers);
412 selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (emp->priv->treeview));
413 selected_rows = gtk_tree_selection_get_selected_rows (selection, &model);
414
415 /* The order of header rows in the HMTL document should be in sync with
416 order of headers in the listview and in efhp->headers_list */
417 document = webkit_web_view_get_dom_document (emp->priv->webview);
418 headers = webkit_dom_document_get_elements_by_class_name (document, "header-item");
419
420 l = g_list_nth (selected_rows, g_list_length (selected_rows) / 2);
421 selection_middle = gtk_tree_row_reference_new (model, l->data);
422
423 references = NULL;
424 for (l = selected_rows; l; l = l->next) {
425 references = g_list_prepend (
426 references,
427 gtk_tree_row_reference_new (model, l->data));
428 }
429
430 if (button == emp->priv->buttons[BUTTON_TOP]) {
431
432 for (l = references; l; l = l->next) {
433 /* Move the rows in the view */
434 path = gtk_tree_row_reference_get_path (l->data);
435 gtk_tree_model_get_iter (model, &iter, path);
436 gtk_list_store_move_after (emp->priv->headers, &iter, NULL);
437
438 /* Move the header row in HTML document */
439 indices = gtk_tree_path_get_indices (path);
440 header = webkit_dom_node_list_item (headers, indices[0]);
441 parent = webkit_dom_node_get_parent_node (header);
442 webkit_dom_node_remove_child (parent, header, NULL);
443 webkit_dom_node_insert_before (parent, header,
444 webkit_dom_node_get_first_child (parent), NULL);
445
446 gtk_tree_path_free (path);
447 }
448
449 } else if (button == emp->priv->buttons[BUTTON_UP]) {
450
451 GtkTreeIter *iter_prev;
452 WebKitDOMNode *node2;
453
454 references = g_list_reverse (references);
455
456 for (l = references; l; l = l->next) {
457
458 path = gtk_tree_row_reference_get_path (l->data);
459 gtk_tree_model_get_iter (model, &iter, path);
460 iter_prev = gtk_tree_iter_copy (&iter);
461 gtk_tree_model_iter_previous (model, iter_prev);
462
463 gtk_list_store_move_before (emp->priv->headers, &iter, iter_prev);
464
465 indices = gtk_tree_path_get_indices (path);
466 header = webkit_dom_node_list_item (headers, indices[0]);
467 node2 = webkit_dom_node_get_previous_sibling (header);
468 parent = webkit_dom_node_get_parent_node (header);
469
470 webkit_dom_node_remove_child (parent, header, NULL);
471 webkit_dom_node_insert_before (parent, header, node2, NULL);
472
473 gtk_tree_path_free (path);
474 gtk_tree_iter_free (iter_prev);
475 }
476
477 } else if (button == emp->priv->buttons[BUTTON_DOWN]) {
478
479 GtkTreeIter *iter_next;
480 WebKitDOMNode *node2;
481
482 for (l = references; l; l = l->next) {
483
484 path = gtk_tree_row_reference_get_path (l->data);
485 gtk_tree_model_get_iter (model, &iter, path);
486 iter_next = gtk_tree_iter_copy (&iter);
487 gtk_tree_model_iter_next (model, iter_next);
488
489 gtk_list_store_move_after (emp->priv->headers, &iter, iter_next);
490
491 indices = gtk_tree_path_get_indices (path);
492 header = webkit_dom_node_list_item (headers, indices[0]);
493 node2 = webkit_dom_node_get_next_sibling (header);
494 parent = webkit_dom_node_get_parent_node (header);
495
496 webkit_dom_node_remove_child (parent, header, NULL);
497 webkit_dom_node_insert_before (parent, header,
498 webkit_dom_node_get_next_sibling (node2), NULL);
499
500 gtk_tree_path_free (path);
501 gtk_tree_iter_free (iter_next);
502 }
503
504 } else if (button == emp->priv->buttons[BUTTON_BOTTOM]) {
505
506 references = g_list_reverse (references);
507
508 for (l = references; l; l = l->next) {
509 path = gtk_tree_row_reference_get_path (l->data);
510 gtk_tree_model_get_iter (model, &iter, path);
511 gtk_list_store_move_before (emp->priv->headers, &iter, NULL);
512
513 /* Move the header row in HTML document */
514 indices = gtk_tree_path_get_indices (path);
515 header = webkit_dom_node_list_item (headers, indices[0]);
516 parent = webkit_dom_node_get_parent_node (header);
517 webkit_dom_node_remove_child (parent, header, NULL);
518 webkit_dom_node_append_child (parent, header, NULL);
519
520 gtk_tree_path_free (path);
521 }
522 };
523
524 g_list_foreach (references, (GFunc) gtk_tree_row_reference_free, NULL);
525 g_list_free (references);
526
527 /* Keep the selection in middle of the screen */
528 path = gtk_tree_row_reference_get_path (selection_middle);
529 gtk_tree_view_scroll_to_cell (
530 GTK_TREE_VIEW (emp->priv->treeview),
531 path, COLUMN_ACTIVE, TRUE, 0.5, 0.5);
532 gtk_tree_path_free (path);
533 gtk_tree_row_reference_free (selection_middle);
534
535 g_list_foreach (selected_rows, (GFunc) gtk_tree_path_free, NULL);
536 g_list_free (selected_rows);
537
538 emp_headers_tab_selection_changed (selection, user_data);
539 }
540
541 static GtkWidget *
542 emp_create_headers_tab (GtkPrintOperation *operation,
543 EMailPrinter *emp)
544 {
545 GtkWidget *vbox, *hbox, *scw, *button;
546 GtkTreeView *view;
547 GtkTreeSelection *selection;
548 GtkTreeViewColumn *column;
549 GtkCellRenderer *renderer;
550
551 hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 5);
552 vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 5);
553 gtk_box_pack_end (GTK_BOX (hbox), vbox, FALSE, FALSE, 5);
554
555 emp->priv->treeview = gtk_tree_view_new_with_model (
556 GTK_TREE_MODEL (emp->priv->headers));
557 view = GTK_TREE_VIEW (emp->priv->treeview);
558 selection = gtk_tree_view_get_selection (view);
559 gtk_tree_selection_set_mode (selection, GTK_SELECTION_MULTIPLE);
560 g_signal_connect (
561 selection, "changed",
562 G_CALLBACK (emp_headers_tab_selection_changed), emp);
563
564 renderer = gtk_cell_renderer_toggle_new ();
565 g_signal_connect (
566 renderer, "toggled",
567 G_CALLBACK (header_active_renderer_toggled_cb), emp);
568 column = gtk_tree_view_column_new_with_attributes (
569 _("Print"), renderer,
570 "active", COLUMN_ACTIVE, NULL);
571 gtk_tree_view_append_column (view, column);
572
573 renderer = gtk_cell_renderer_text_new ();
574 column = gtk_tree_view_column_new_with_attributes (
575 _("Header Name"), renderer,
576 "text", COLUMN_HEADER_NAME, NULL);
577 gtk_tree_view_append_column (view, column);
578
579 renderer = gtk_cell_renderer_text_new ();
580 column = gtk_tree_view_column_new_with_attributes (
581 _("Header Value"), renderer,
582 "text", COLUMN_HEADER_VALUE, NULL);
583 gtk_tree_view_append_column (view, column);
584
585 scw = gtk_scrolled_window_new (NULL, NULL);
586 gtk_container_add (GTK_CONTAINER (scw), GTK_WIDGET (view));
587 gtk_box_pack_start (GTK_BOX (hbox), scw, TRUE, TRUE, 0);
588
589 button = gtk_button_new_from_stock (GTK_STOCK_SELECT_ALL);
590 emp->priv->buttons[BUTTON_SELECT_ALL] = button;
591 g_signal_connect (
592 button, "clicked",
593 G_CALLBACK (emp_headers_tab_toggle_selection), emp);
594 gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, TRUE, 5);
595
596 button = gtk_button_new_from_stock (GTK_STOCK_CLEAR);
597 emp->priv->buttons[BUTTON_SELECT_NONE] = button;
598 g_signal_connect (
599 button, "clicked",
600 G_CALLBACK (emp_headers_tab_toggle_selection), emp);
601 gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, TRUE, 5);
602
603 button = gtk_button_new_from_stock (GTK_STOCK_GOTO_TOP);
604 emp->priv->buttons[BUTTON_TOP] = button;
605 gtk_widget_set_sensitive (button, FALSE);
606 g_signal_connect (
607 button, "clicked",
608 G_CALLBACK (emp_headers_tab_move), emp);
609 gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, TRUE, 5);
610
611 button = gtk_button_new_from_stock (GTK_STOCK_GO_UP);
612 emp->priv->buttons[BUTTON_UP] = button;
613 gtk_widget_set_sensitive (button, FALSE);
614 g_signal_connect (
615 button, "clicked",
616 G_CALLBACK (emp_headers_tab_move), emp);
617 gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, TRUE, 5);
618
619 button = gtk_button_new_from_stock (GTK_STOCK_GO_DOWN);
620 emp->priv->buttons[BUTTON_DOWN] = button;
621 gtk_widget_set_sensitive (button, FALSE);
622 g_signal_connect (
623 button, "clicked",
624 G_CALLBACK (emp_headers_tab_move), emp);
625 gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, TRUE, 5);
626
627 button = gtk_button_new_from_stock (GTK_STOCK_GOTO_BOTTOM);
628 emp->priv->buttons[BUTTON_BOTTOM] = button;
629 gtk_widget_set_sensitive (button, FALSE);
630 g_signal_connect (
631 button, "clicked",
632 G_CALLBACK (emp_headers_tab_move), emp);
633 gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, TRUE, 5);
634
635 gtk_print_operation_set_custom_tab_label (operation, _("Headers"));
636 gtk_widget_show_all (hbox);
637
638 return hbox;
639 }
640
641 static void
642 emp_set_parts_list (EMailPrinter *emp,
643 EMailPartList *parts_list)
644 {
645 CamelMediumHeader *header;
646 GArray *headers;
647 gint i;
648 GtkTreeIter last_known = { 0 };
649
650 g_return_if_fail (parts_list);
651
652 emp->priv->parts_list = g_object_ref (parts_list);
653
654 if (emp->priv->headers)
655 g_object_unref (emp->priv->headers);
656 emp->priv->headers = gtk_list_store_new (
657 5,
658 G_TYPE_BOOLEAN, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_POINTER, G_TYPE_INT);
659
660 headers = camel_medium_get_headers (CAMEL_MEDIUM (parts_list->message));
661 if (!headers)
662 return;
663
664 for (i = 0; i < headers->len; i++) {
665 GtkTreeIter iter;
666 GList *found_header;
667 EMailFormatterHeader *emfh;
668
669 header = &g_array_index (headers, CamelMediumHeader, i);
670 emfh = e_mail_formatter_header_new (header->name, header->value);
671
672 found_header = g_queue_find_custom (
673 (GQueue *) e_mail_formatter_get_headers (
674 E_MAIL_FORMATTER (emp->priv->formatter)),
675 emfh, (GCompareFunc) emp_header_name_equal);
676
677 if (!found_header) {
678 emfh->flags |= E_MAIL_FORMATTER_HEADER_FLAG_HIDDEN;
679 e_mail_formatter_add_header_struct (
680 E_MAIL_FORMATTER (emp->priv->formatter), emfh);
681 gtk_list_store_append (emp->priv->headers, &iter);
682 } else {
683 if (gtk_list_store_iter_is_valid (emp->priv->headers, &last_known))
684 gtk_list_store_insert_after (emp->priv->headers, &iter, &last_known);
685 else
686 gtk_list_store_insert_after (emp->priv->headers, &iter, NULL);
687
688 last_known = iter;
689 }
690
691 gtk_list_store_set (
692 emp->priv->headers, &iter,
693 COLUMN_ACTIVE, (found_header != NULL),
694 COLUMN_HEADER_NAME, emfh->name,
695 COLUMN_HEADER_VALUE, emfh->value,
696 COLUMN_HEADER_STRUCT, emfh, -1);
697 }
698
699 camel_medium_free_headers (CAMEL_MEDIUM (parts_list->message), headers);
700 }
701
702 static void
703 emp_set_property (GObject *object,
704 guint property_id,
705 const GValue *value,
706 GParamSpec *pspec)
707 {
708 EMailPrinter *emp = E_MAIL_PRINTER (object);
709
710 switch (property_id) {
711
712 case PROP_PART_LIST:
713 emp_set_parts_list (emp, g_value_get_pointer (value));
714 return;
715 }
716
717 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
718 }
719
720 static void
721 emp_get_property (GObject *object,
722 guint property_id,
723 GValue *value,
724 GParamSpec *pspec)
725 {
726 EMailPrinter *emp = E_MAIL_PRINTER (object);
727
728 switch (property_id) {
729
730 case PROP_PART_LIST:
731 g_value_set_pointer (value, emp->priv->parts_list);
732 return;
733 }
734
735 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
736 }
737
738 static void
739 emp_finalize (GObject *object)
740 {
741 EMailPrinterPrivate *priv = E_MAIL_PRINTER (object)->priv;
742
743 if (priv->formatter) {
744 g_object_unref (priv->formatter);
745 priv->formatter = NULL;
746 }
747
748 if (priv->headers) {
749 GtkTreeIter iter;
750
751 if (gtk_tree_model_get_iter_first (GTK_TREE_MODEL (priv->headers), &iter)) {
752 do {
753 EMailFormatterHeader *header = NULL;
754 gtk_tree_model_get (
755 GTK_TREE_MODEL (priv->headers), &iter,
756 COLUMN_HEADER_STRUCT, &header, -1);
757 e_mail_formatter_header_free (header);
758 } while (gtk_tree_model_iter_next (GTK_TREE_MODEL (priv->headers), &iter));
759 }
760 g_object_unref (priv->headers);
761 priv->headers = NULL;
762 }
763
764 if (priv->webview) {
765 g_object_unref (priv->webview);
766 priv->webview = NULL;
767 }
768
769 if (priv->uri) {
770 g_free (priv->uri);
771 priv->uri = NULL;
772 }
773
774 if (priv->operation) {
775 g_object_unref (priv->operation);
776 priv->operation = NULL;
777 }
778
779 if (priv->parts_list) {
780 g_object_unref (priv->parts_list);
781 priv->parts_list = NULL;
782 }
783
784 /* Chain up to parent's finalize() method. */
785 G_OBJECT_CLASS (e_mail_printer_parent_class)->finalize (object);
786 }
787
788 static void
789 e_mail_printer_class_init (EMailPrinterClass *class)
790 {
791 GObjectClass *object_class;
792
793 g_type_class_add_private (class, sizeof (EMailPrinterPrivate));
794
795 object_class = G_OBJECT_CLASS (class);
796 object_class->set_property = emp_set_property;
797 object_class->get_property = emp_get_property;
798 object_class->finalize = emp_finalize;
799
800 g_object_class_install_property (
801 object_class,
802 PROP_PART_LIST,
803 g_param_spec_pointer (
804 "parts-list",
805 "Parts List",
806 NULL,
807 G_PARAM_READWRITE |
808 G_PARAM_CONSTRUCT_ONLY));
809
810 signals[SIGNAL_DONE] = g_signal_new (
811 "done",
812 G_TYPE_FROM_CLASS (class),
813 G_SIGNAL_RUN_FIRST,
814 G_STRUCT_OFFSET (EMailPrinterClass, done),
815 NULL, NULL,
816 e_marshal_VOID__OBJECT_INT,
817 G_TYPE_NONE, 2,
818 GTK_TYPE_PRINT_OPERATION, G_TYPE_INT);
819 }
820
821 static void
822 e_mail_printer_init (EMailPrinter *emp)
823 {
824 emp->priv = G_TYPE_INSTANCE_GET_PRIVATE (
825 emp, E_TYPE_MAIL_PRINTER, EMailPrinterPrivate);
826
827 emp->priv->formatter = (EMailFormatterPrint *) e_mail_formatter_print_new ();
828 emp->priv->headers = NULL;
829 emp->priv->webview = NULL;
830 }
831
832 EMailPrinter *
833 e_mail_printer_new (EMailPartList *source)
834 {
835 EMailPrinter *emp;
836
837 emp = g_object_new (
838 E_TYPE_MAIL_PRINTER,
839 "parts-list", source, NULL);
840
841 return emp;
842 }
843
844 void
845 e_mail_printer_print (EMailPrinter *emp,
846 GtkPrintOperationAction action,
847 EMailFormatter *formatter,
848 GCancellable *cancellable)
849 {
850 g_return_if_fail (E_IS_MAIL_PRINTER (emp));
851
852 if (emp->priv->operation)
853 g_object_unref (emp->priv->operation);
854 emp->priv->operation = e_print_operation_new ();
855 emp->priv->print_action = action;
856 gtk_print_operation_set_unit (emp->priv->operation, GTK_UNIT_PIXEL);
857
858 gtk_print_operation_set_show_progress (emp->priv->operation, TRUE);
859 g_signal_connect (
860 emp->priv->operation, "create-custom-widget",
861 G_CALLBACK (emp_create_headers_tab), emp);
862 g_signal_connect (
863 emp->priv->operation, "done",
864 G_CALLBACK (emp_printing_done), emp);
865 g_signal_connect (
866 emp->priv->operation, "draw-page",
867 G_CALLBACK (emp_draw_footer), NULL);
868
869 if (cancellable)
870 g_signal_connect_swapped (
871 cancellable, "cancelled",
872 G_CALLBACK (gtk_print_operation_cancel), emp->priv->operation);
873
874 emp_run_print_operation (emp, formatter);
875 }
876
877 const gchar *
878 e_mail_printer_get_export_filename (EMailPrinter *printer)
879 {
880 g_return_val_if_fail (E_IS_MAIL_PRINTER (printer), NULL);
881
882 return printer->priv->export_filename;
883 }
884
885 void
886 e_mail_printer_set_export_filename (EMailPrinter *printer,
887 const gchar *filename)
888 {
889 g_return_if_fail (E_IS_MAIL_PRINTER (printer));
890
891 if (printer->priv->export_filename)
892 g_free (printer->priv->export_filename);
893
894 printer->priv->export_filename = g_strdup (filename);
895 }