No issues found
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 *
16 * Authors:
17 *
18 * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
19 *
20 */
21
22 #ifdef HAVE_CONFIG_H
23 #include <config.h>
24 #endif
25
26 #include <ctype.h>
27 #include <sys/types.h>
28 #include <stdlib.h>
29 #include <string.h>
30
31 #include <libxml/tree.h>
32 #include <libxml/parser.h>
33 #include <libxml/xmlmemory.h>
34 #include <glib/gi18n.h>
35
36 #include "e-util/e-print.h"
37 #include "e-util/e-util.h"
38 #include "e-util/e-util-private.h"
39
40 #include "e-contact-print.h"
41
42 typedef struct _EContactPrintContext EContactPrintContext;
43 typedef struct _ContactPrintItem ContactPrintItem;
44
45 struct _EContactPrintContext
46 {
47 GtkPrintOperationAction action;
48 GtkPrintContext *context;
49 gdouble x;
50 gdouble y;
51 gint column;
52 gdouble column_width;
53 gdouble column_spacing;
54 EContactPrintStyle *style;
55 gboolean first_section;
56
57 gint page_nr, pages;
58
59 PangoFontDescription *letter_heading_font;
60 gchar *section;
61 gboolean first_contact;
62
63 GSList *contact_list;
64 };
65
66 static gdouble
67 get_font_height (PangoFontDescription *desc)
68 {
69 return pango_units_to_double (
70 pango_font_description_get_size (desc));
71 }
72
73 static gdouble
74 get_font_width (GtkPrintContext *context,
75 PangoFontDescription *desc,
76 const gchar *text)
77 {
78 PangoLayout *layout;
79 gint width, height;
80
81 g_return_val_if_fail (desc, .0);
82 g_return_val_if_fail (text, .0);
83
84 layout = gtk_print_context_create_pango_layout (context);
85
86 pango_layout_set_font_description (layout, desc);
87 pango_layout_set_text (layout, text, -1);
88 pango_layout_set_width (layout, -1);
89 pango_layout_set_indent (layout, 0);
90
91 pango_layout_get_size (layout, &width, &height);
92
93 g_object_unref (layout);
94
95 return pango_units_to_double (width);
96 }
97
98 static void
99 e_contact_output (GtkPrintContext *context,
100 PangoFontDescription *font,
101 gdouble x,
102 gdouble y,
103 gdouble width,
104 const gchar *text)
105 {
106 PangoLayout *layout;
107 gdouble indent;
108 cairo_t *cr;
109
110 layout = gtk_print_context_create_pango_layout (context);
111
112 if (width == -1 || get_font_width (context, font, text) <= width)
113 indent = .0;
114 else
115 indent = get_font_width (context, font, " ");
116
117 pango_layout_set_font_description (layout, font);
118 pango_layout_set_text (layout, text, -1);
119 pango_layout_set_width (layout, pango_units_from_double (width));
120 pango_layout_set_indent (layout, pango_units_from_double (indent));
121 pango_layout_set_wrap (layout, PANGO_WRAP_WORD_CHAR);
122
123 cr = gtk_print_context_get_cairo_context (context);
124
125 cairo_save (cr);
126 cairo_move_to (cr, x, y);
127 pango_cairo_show_layout (cr, layout);
128 cairo_restore (cr);
129
130 g_object_unref (layout);
131 }
132
133 static gdouble
134 e_contact_text_height (GtkPrintContext *context,
135 PangoFontDescription *desc,
136 const gchar *text)
137 {
138 PangoLayout *layout;
139 gint width, height;
140
141 layout = gtk_print_context_create_pango_layout (context);
142
143 pango_layout_set_font_description (layout, desc);
144 pango_layout_set_text (layout, text, -1);
145
146 pango_layout_get_size (layout, &width, &height);
147
148 g_object_unref (layout);
149
150 return pango_units_to_double (height);
151 }
152
153 static void
154 e_contact_print_letter_heading (EContactPrintContext *ctxt,
155 gchar *letter)
156 {
157 PangoLayout *layout;
158 PangoFontDescription *desc;
159 PangoFontMetrics *metrics;
160 gint width, height;
161 cairo_t *cr;
162
163 desc = ctxt->letter_heading_font;
164
165 layout = gtk_print_context_create_pango_layout (ctxt->context);
166
167 /* Make the rectangle thrice the average character width.
168 * XXX Works well for English, what about other locales? */
169 metrics = pango_context_get_metrics (
170 pango_layout_get_context (layout),
171 desc, pango_language_get_default ());
172 width = pango_font_metrics_get_approximate_char_width (metrics) * 3;
173 pango_font_metrics_unref (metrics);
174
175 pango_layout_set_alignment (layout, PANGO_ALIGN_CENTER);
176 pango_layout_set_font_description (layout, desc);
177 pango_layout_set_text (layout, letter, -1);
178 pango_layout_set_width (layout, width);
179 pango_layout_get_size (layout, NULL, &height);
180
181 if (ctxt->page_nr == -1 || ctxt->pages != ctxt->page_nr) {
182 /* only calculating number of pages
183 * or on page we do not want to print */
184 ctxt->y += pango_units_to_double (height);
185
186 return;
187 }
188
189 /* Draw white text centered in a black rectangle. */
190 cr = gtk_print_context_get_cairo_context (ctxt->context);
191
192 cairo_save (cr);
193 cairo_set_source_rgb (cr, .0, .0, .0);
194 cairo_rectangle (
195 cr, ctxt->x, ctxt->y,
196 pango_units_to_double (width),
197 pango_units_to_double (height));
198 cairo_fill (cr);
199 cairo_restore (cr);
200
201 cairo_save (cr);
202 cairo_move_to (cr, ctxt->x, ctxt->y);
203 cairo_set_source_rgb (cr, 1., 1., 1.);
204 pango_cairo_show_layout (cr, layout);
205 cairo_restore (cr);
206
207 ctxt->y += pango_units_to_double (height);
208 }
209
210 static void
211 e_contact_start_new_page (EContactPrintContext *ctxt)
212 {
213 ctxt->x = ctxt->y = .0;
214 ctxt->column = 0;
215 ctxt->pages++;
216 }
217
218 static void
219 e_contact_start_new_column (EContactPrintContext *ctxt)
220 {
221 if (++ctxt->column >= ctxt->style->num_columns)
222 e_contact_start_new_page (ctxt);
223 else {
224 ctxt->x = ctxt->column *
225 (ctxt->column_width + ctxt->column_spacing);
226 ctxt->y = .0;
227 }
228 }
229
230 static gdouble
231 e_contact_get_contact_height (EContact *contact,
232 EContactPrintContext *ctxt)
233 {
234 gchar *file_as;
235 gint field;
236 gdouble cntct_height = 0.0;
237
238 cntct_height += get_font_height (ctxt->style->headings_font) * .2;
239
240 file_as = e_contact_get (contact, E_CONTACT_FILE_AS);
241
242 cntct_height += e_contact_text_height (
243 ctxt->context, ctxt->style->headings_font, file_as);
244
245 g_free (file_as);
246
247 cntct_height += get_font_height (ctxt->style->headings_font) * .2;
248
249 for (field = E_CONTACT_FILE_AS; field != E_CONTACT_LAST_SIMPLE_STRING; field++)
250 {
251 const gchar *value;
252 gchar *text;
253
254 value = e_contact_get_const (contact, field);
255 if (value == NULL || *value == '\0')
256 continue;
257
258 text = g_strdup_printf (
259 "%s: %s",
260 e_contact_pretty_name (field), value);
261
262 cntct_height += e_contact_text_height (
263 ctxt->context, ctxt->style->body_font, text);
264
265 cntct_height += .2 * get_font_height (ctxt->style->body_font);
266
267 g_free (text);
268 }
269
270 cntct_height += get_font_height (ctxt->style->headings_font) * .4 + 8;
271
272 return cntct_height;
273 }
274
275 static void
276 e_contact_print_contact (EContact *contact,
277 EContactPrintContext *ctxt)
278 {
279 GtkPageSetup *setup;
280 gchar *file_as;
281 cairo_t *cr;
282 gdouble page_height;
283 gint field;
284
285 setup = gtk_print_context_get_page_setup (ctxt->context);
286 page_height = gtk_page_setup_get_page_height (setup, GTK_UNIT_POINTS);
287
288 cr = gtk_print_context_get_cairo_context (ctxt->context);
289 cairo_save (cr);
290 ctxt->y += get_font_height (ctxt->style->headings_font) * .2;
291
292 file_as = e_contact_get (contact, E_CONTACT_FILE_AS);
293
294 if (ctxt->style->print_using_grey && ctxt->pages == ctxt->page_nr) {
295 cairo_save (cr);
296 cairo_set_source_rgb (cr, .85, .85, .85);
297 cairo_rectangle (
298 cr, ctxt->x, ctxt->y, ctxt->column_width,
299 e_contact_text_height (ctxt->context,
300 ctxt->style->headings_font, file_as));
301 cairo_fill (cr);
302 cairo_restore (cr);
303 }
304
305 if (ctxt->pages == ctxt->page_nr)
306 e_contact_output (
307 ctxt->context, ctxt->style->headings_font,
308 ctxt->x, ctxt->y, ctxt->column_width + 4, file_as);
309 ctxt->y += e_contact_text_height (
310 ctxt->context, ctxt->style->headings_font, file_as);
311
312 g_free (file_as);
313
314 ctxt->y += get_font_height (ctxt->style->headings_font) * .2;
315
316 for (field = E_CONTACT_FILE_AS; field != E_CONTACT_LAST_SIMPLE_STRING; field++)
317 {
318 const gchar *value;
319 gchar *text;
320 gint wrapped_lines = 0;
321
322 if (ctxt->y > page_height)
323 e_contact_start_new_column (ctxt);
324
325 value = e_contact_get_const (contact, field);
326 if (value == NULL || *value == '\0')
327 continue;
328
329 text = g_strdup_printf (
330 "%s: %s",
331 e_contact_pretty_name (field), value);
332
333 if (ctxt->pages == ctxt->page_nr)
334 e_contact_output (
335 ctxt->context, ctxt->style->body_font,
336 ctxt->x, ctxt->y, ctxt->column_width + 4, text);
337
338 if (get_font_width (ctxt->context,
339 ctxt->style->body_font, text) > ctxt->column_width)
340 wrapped_lines =
341 (get_font_width (ctxt->context,
342 ctxt->style->body_font, text) /
343 (ctxt->column_width + 4)) + 1;
344 ctxt->y =
345 ctxt->y + ((wrapped_lines + 1) *
346 e_contact_text_height (
347 ctxt->context,
348 ctxt->style->body_font,
349 text));
350
351 ctxt->y += .2 * get_font_height (ctxt->style->body_font);
352
353 g_free (text);
354 }
355
356 ctxt->y += get_font_height (ctxt->style->headings_font) * .4 + 8;
357
358 cairo_restore (cr);
359 }
360
361 static gint
362 contact_compare (EContact *contact1,
363 EContact *contact2)
364 {
365 const gchar *field1, *field2;
366
367 if (contact1 == NULL || contact2 == NULL)
368 return 0;
369
370 field1 = e_contact_get_const (contact1, E_CONTACT_FILE_AS);
371 field2 = e_contact_get_const (contact2, E_CONTACT_FILE_AS);
372
373 if (field1 != NULL && field2 != NULL)
374 return g_utf8_collate (field1, field2);
375
376 if (field1 != NULL || field2 != NULL)
377 return (field1 != NULL) ? -1 : 1;
378
379 field1 = e_contact_get_const (contact1, E_CONTACT_UID);
380 field2 = e_contact_get_const (contact2, E_CONTACT_UID);
381
382 g_return_val_if_fail (
383 field1 != NULL && field2 != NULL,
384 (field1 != NULL) ? -1 : 1);
385
386 return strcmp (field1, field2);
387 }
388
389 static void
390 contacts_added (EBookClientView *book_view,
391 const GSList *contact_list,
392 EContactPrintContext *ctxt)
393 {
394 while (contact_list != NULL) {
395 ctxt->contact_list = g_slist_prepend (
396 ctxt->contact_list,
397 g_object_ref (contact_list->data));
398 contact_list = contact_list->next;
399 }
400 }
401
402 static void
403 view_complete (EBookClientView *client_view,
404 const GError *error,
405 GtkPrintOperation *operation)
406 {
407 EContactPrintContext *ctxt;
408
409 g_return_if_fail (operation != NULL);
410
411 ctxt = g_object_get_data (G_OBJECT (operation), "contact-print-ctx");
412 g_return_if_fail (ctxt != NULL);
413
414 e_book_client_view_stop (client_view, NULL);
415 g_signal_handlers_disconnect_by_func (
416 client_view, G_CALLBACK (contacts_added), ctxt);
417 g_signal_handlers_disconnect_by_func (
418 client_view, G_CALLBACK (view_complete), operation);
419
420 g_object_unref (client_view);
421
422 gtk_print_operation_run (operation, ctxt->action, NULL, NULL);
423 g_object_unref (operation);
424 }
425
426 static gboolean
427 get_bool (gchar *data)
428 {
429 if (data)
430 return (g_ascii_strcasecmp (data, "true") == 0);
431 else
432 return FALSE;
433 }
434
435 static void
436 get_string (gchar *data,
437 gchar **variable)
438 {
439 g_free (*variable);
440 *variable = g_strdup ((data != NULL) ? data : "");
441 }
442
443 static gint
444 get_integer (gchar *data)
445 {
446 return (data != NULL) ? atoi (data) : 0;
447 }
448
449 static gdouble
450 get_float (gchar *data)
451 {
452 return (data != NULL) ? atof (data) : .0;
453 }
454
455 static void
456 get_font (gchar *data,
457 PangoFontDescription **variable)
458 {
459 PangoFontDescription *desc = NULL;
460
461 if (data != NULL)
462 desc = pango_font_description_from_string (data);
463
464 if (desc != NULL) {
465 pango_font_description_free (*variable);
466 *variable = desc;
467 }
468 }
469
470 static void
471 e_contact_build_style (EContactPrintStyle *style)
472 {
473 xmlDocPtr styledoc;
474 gchar *filename;
475
476 style->title = g_strdup ("");
477 style->type = E_CONTACT_PRINT_TYPE_CARDS;
478 style->sections_start_new_page = TRUE;
479 style->num_columns = 2;
480 style->blank_forms = 2;
481 style->letter_headings = FALSE;
482
483 style->headings_font = pango_font_description_from_string ("Sans Bold 8");
484 style->body_font = pango_font_description_from_string ("Sans 6");
485
486 style->print_using_grey = TRUE;
487 style->paper_type = 0;
488 style->paper_width = 8.5;
489 style->paper_height = 11;
490 style->paper_source = 0;
491 style->top_margin = .5;
492 style->left_margin = .5;
493 style->bottom_margin = .5;
494 style->right_margin = .5;
495 style->page_size = 0;
496 style->page_width = 2.75;
497 style->page_height = 4.25;
498 #if 0
499 style->page_width = 4.25;
500 style->page_height = 5.5;
501 #endif
502 #if 0
503 style->page_width = 5.5;
504 style->page_height = 8.5;
505 #endif
506 style->orientation_portrait = FALSE;
507
508 style->header_font = pango_font_description_copy (style->body_font);
509
510 style->left_header = g_strdup ("");
511 style->center_header = g_strdup ("");
512 style->right_header = g_strdup ("");
513
514 style->footer_font = pango_font_description_copy (style->body_font);
515
516 style->left_footer = g_strdup ("");
517 style->center_footer = g_strdup ("");
518 style->right_footer = g_strdup ("");
519 style->reverse_on_even_pages = FALSE;
520
521 filename = g_build_filename (EVOLUTION_ECPSDIR, "medbook.ecps", NULL);
522 styledoc = e_xml_parse_file (filename);
523 g_free (filename);
524
525 if (styledoc) {
526 xmlNodePtr stylenode = xmlDocGetRootElement (styledoc);
527 xmlNodePtr node;
528 for (node = stylenode->children; node; node = node->next) {
529 gchar *data = (gchar *) xmlNodeGetContent (node);
530 if (!strcmp ((gchar *) node->name, "title")) {
531 get_string (data, &(style->title));
532 } else if (!strcmp ((gchar *) node->name, "type")) {
533 if (g_ascii_strcasecmp (data, "cards") == 0)
534 style->type = E_CONTACT_PRINT_TYPE_CARDS;
535 else if (g_ascii_strcasecmp (data, "memo_style") == 0)
536 style->type = E_CONTACT_PRINT_TYPE_MEMO_STYLE;
537 else if (g_ascii_strcasecmp (data, "phone_list") == 0)
538 style->type = E_CONTACT_PRINT_TYPE_PHONE_LIST;
539 } else if (!strcmp ((gchar *) node->name, "sections_start_new_page")) {
540 style->sections_start_new_page = get_bool (data);
541 } else if (!strcmp ((gchar *) node->name, "num_columns")) {
542 style->num_columns = get_integer (data);
543 } else if (!strcmp ((gchar *) node->name, "blank_forms")) {
544 style->blank_forms = get_integer (data);
545 } else if (!strcmp ((gchar *) node->name, "letter_headings")) {
546 style->letter_headings = get_bool (data);
547 } else if (!strcmp ((gchar *) node->name, "headings_font")) {
548 get_font (data, &(style->headings_font));
549 } else if (!strcmp ((gchar *) node->name, "body_font")) {
550 get_font (data, &(style->body_font));
551 } else if (!strcmp ((gchar *) node->name, "print_using_grey")) {
552 style->print_using_grey = get_bool (data);
553 } else if (!strcmp ((gchar *) node->name, "paper_width")) {
554 style->paper_width = get_float (data);
555 } else if (!strcmp ((gchar *) node->name, "paper_height")) {
556 style->paper_height = get_float (data);
557 } else if (!strcmp ((gchar *) node->name, "top_margin")) {
558 style->top_margin = get_float (data);
559 } else if (!strcmp ((gchar *) node->name, "left_margin")) {
560 style->left_margin = get_float (data);
561 } else if (!strcmp ((gchar *) node->name, "bottom_margin")) {
562 style->bottom_margin = get_float (data);
563 } else if (!strcmp ((gchar *) node->name, "right_margin")) {
564 style->right_margin = get_float (data);
565 } else if (!strcmp ((gchar *) node->name, "page_width")) {
566 style->page_width = get_float (data);
567 } else if (!strcmp ((gchar *) node->name, "page_height")) {
568 style->page_height = get_float (data);
569 } else if (!strcmp ((gchar *) node->name, "orientation")) {
570 if (data) {
571 style->orientation_portrait =
572 (g_ascii_strcasecmp (data, "landscape") != 0);
573 } else {
574 style->orientation_portrait = TRUE;
575 }
576 } else if (!strcmp ((gchar *) node->name, "header_font")) {
577 get_font (data, &(style->header_font));
578 } else if (!strcmp ((gchar *) node->name, "left_header")) {
579 get_string (data, &(style->left_header));
580 } else if (!strcmp ((gchar *) node->name, "center_header")) {
581 get_string (data, &(style->center_header));
582 } else if (!strcmp ((gchar *) node->name, "right_header")) {
583 get_string (data, &(style->right_header));
584 } else if (!strcmp ((gchar *) node->name, "footer_font")) {
585 get_font (data, &(style->footer_font));
586 } else if (!strcmp ((gchar *) node->name, "left_footer")) {
587 get_string (data, &(style->left_footer));
588 } else if (!strcmp ((gchar *) node->name, "center_footer")) {
589 get_string (data, &(style->center_footer));
590 } else if (!strcmp ((gchar *) node->name, "right_footer")) {
591 get_string (data, &(style->right_footer));
592 } else if (!strcmp ((gchar *) node->name, "reverse_on_even_pages")) {
593 style->reverse_on_even_pages = get_bool (data);
594 }
595 if (data)
596 xmlFree (data);
597 }
598 xmlFreeDoc (styledoc);
599 }
600
601 }
602
603 static void
604 contact_draw (EContact *contact,
605 EContactPrintContext *ctxt)
606 {
607 GtkPageSetup *setup;
608 gdouble page_height;
609 gchar *file_as;
610 gboolean new_section = FALSE;
611
612 setup = gtk_print_context_get_page_setup (ctxt->context);
613 page_height = gtk_page_setup_get_page_height (setup, GTK_UNIT_POINTS);
614
615 file_as = e_contact_get (contact, E_CONTACT_FILE_AS);
616
617 if (file_as != NULL) {
618 gchar *section;
619 gsize width;
620
621 width = g_utf8_next_char (file_as) - file_as;
622 section = g_utf8_strup (file_as, width);
623
624 new_section = (ctxt->section == NULL ||
625 g_utf8_collate (ctxt->section, section) != 0);
626
627 if (new_section) {
628 g_free (ctxt->section);
629 ctxt->section = section;
630 } else
631 g_free (section);
632 }
633
634 if (new_section) {
635 if (!ctxt->first_contact) {
636 if (ctxt->style->sections_start_new_page)
637 e_contact_start_new_page (ctxt);
638 else if ((ctxt->y + e_contact_get_contact_height (
639 contact, ctxt)) > page_height)
640 e_contact_start_new_column (ctxt);
641 }
642 if (ctxt->style->letter_headings)
643 e_contact_print_letter_heading (ctxt, ctxt->section);
644 ctxt->first_section = FALSE;
645 }
646
647 else if (!ctxt->first_contact && ((ctxt->y +
648 e_contact_get_contact_height (contact, ctxt)) > page_height)) {
649 e_contact_start_new_column (ctxt);
650 if (ctxt->style->letter_headings)
651 e_contact_print_letter_heading (ctxt, ctxt->section);
652 }
653
654 e_contact_print_contact (contact, ctxt);
655
656 ctxt->first_contact = FALSE;
657 }
658
659 static void
660 contact_begin_print (GtkPrintOperation *operation,
661 GtkPrintContext *context,
662 EContactPrintContext *ctxt)
663 {
664 GtkPageSetup *setup;
665 gdouble page_width;
666
667 e_contact_build_style (ctxt->style);
668
669 setup = gtk_print_context_get_page_setup (context);
670 page_width = gtk_page_setup_get_page_width (setup, GTK_UNIT_POINTS);
671
672 ctxt->context = context;
673 ctxt->x = ctxt->y = .0;
674 ctxt->column = 0;
675 ctxt->first_contact = TRUE;
676 ctxt->first_section = TRUE;
677 ctxt->section = NULL;
678
679 ctxt->column_spacing = gtk_print_context_get_dpi_x (context) / 4;
680 ctxt->column_width = (page_width + ctxt->column_spacing) /
681 ctxt->style->num_columns - ctxt->column_spacing;
682
683 ctxt->letter_heading_font = pango_font_description_new ();
684 pango_font_description_set_family (
685 ctxt->letter_heading_font,
686 pango_font_description_get_family (
687 ctxt->style->headings_font));
688 pango_font_description_set_size (
689 ctxt->letter_heading_font,
690 pango_font_description_get_size (
691 ctxt->style->headings_font) * 1.5);
692
693 if (ctxt->contact_list != NULL) {
694 ctxt->page_nr = -1;
695 ctxt->pages = 1;
696 ctxt->contact_list = g_slist_sort (
697 ctxt->contact_list,
698 (GCompareFunc) contact_compare);
699 g_slist_foreach (ctxt->contact_list, (GFunc) contact_draw, ctxt);
700 gtk_print_operation_set_n_pages (operation, ctxt->pages);
701 }
702 }
703
704 /* contact_page_draw_footer inserts the
705 * page number at the end of each page
706 * while printing*/
707 void
708 contact_page_draw_footer (GtkPrintOperation *operation,
709 GtkPrintContext *context,
710 gint page_nr)
711 {
712 PangoFontDescription *desc;
713 PangoLayout *layout;
714 gdouble x, y, page_height, page_width, page_margin;
715 /*gint n_pages;*/
716 gchar *text;
717 cairo_t *cr;
718 GtkPageSetup *setup;
719
720 /*Uncomment next if it is successful to get total number if pages in list view
721 * g_object_get (operation, "n-pages", &n_pages, NULL)*/
722 text = g_strdup_printf (_("Page %d"), page_nr + 1);
723
724 setup = gtk_print_context_get_page_setup (context);
725 page_height = gtk_page_setup_get_page_height (setup, GTK_UNIT_POINTS);
726 page_width = gtk_page_setup_get_page_width (setup, GTK_UNIT_POINTS);
727 page_margin = gtk_page_setup_get_bottom_margin (setup, GTK_UNIT_POINTS);
728
729 desc = pango_font_description_from_string ("Sans Regular 8");
730 layout = gtk_print_context_create_pango_layout (context);
731 pango_layout_set_alignment (layout, PANGO_ALIGN_CENTER);
732 pango_layout_set_font_description (layout, desc);
733 pango_layout_set_text (layout, text, -1);
734 pango_layout_set_width (layout, -1);
735
736 x = page_width / 2.0 - page_margin;
737 y = page_height - page_margin / 2.0;
738
739 cr = gtk_print_context_get_cairo_context (context);
740
741 cairo_save (cr);
742 cairo_set_source_rgb (cr, .0, .0, .0);
743 cairo_move_to (cr, x, y);
744 pango_cairo_show_layout (cr, layout);
745 cairo_restore (cr);
746
747 g_object_unref (layout);
748 pango_font_description_free (desc);
749
750 g_free (text);
751 }
752
753 static void
754 contact_draw_page (GtkPrintOperation *operation,
755 GtkPrintContext *context,
756 gint page_nr,
757 EContactPrintContext *ctxt)
758 {
759 /* only text on page_nr == pages will be drawn, the pages is recalculated */
760 ctxt->page_nr = page_nr;
761 ctxt->pages = 0;
762
763 ctxt->x = ctxt->y = .0;
764 ctxt->column = 0;
765 ctxt->first_contact = TRUE;
766 ctxt->first_section = TRUE;
767 ctxt->section = NULL;
768
769 g_slist_foreach (ctxt->contact_list, (GFunc) contact_draw, ctxt);
770 contact_page_draw_footer (operation, context, page_nr);
771 }
772
773 static void
774 contact_end_print (GtkPrintOperation *operation,
775 GtkPrintContext *context,
776 EContactPrintContext *ctxt)
777 {
778 pango_font_description_free (ctxt->style->headings_font);
779 pango_font_description_free (ctxt->style->body_font);
780 pango_font_description_free (ctxt->style->header_font);
781 pango_font_description_free (ctxt->style->footer_font);
782 pango_font_description_free (ctxt->letter_heading_font);
783
784 e_client_util_free_object_slist (ctxt->contact_list);
785
786 g_free (ctxt->style);
787 g_free (ctxt->section);
788 }
789
790 static void
791 get_view_ready_cb (GObject *source_object,
792 GAsyncResult *result,
793 gpointer user_data)
794 {
795 GtkPrintOperation *operation = user_data;
796 EBookClient *book_client = E_BOOK_CLIENT (source_object);
797 EBookClientView *client_view = NULL;
798 EContactPrintContext *ctxt;
799 GError *error = NULL;
800
801 e_book_client_get_view_finish (book_client, result, &client_view, &error);
802
803 ctxt = g_object_get_data (G_OBJECT (operation), "contact-print-ctx");
804 g_return_if_fail (ctxt != NULL);
805
806 if (error != NULL) {
807 g_warning (
808 "%s: Failed to get view: %s",
809 G_STRFUNC, error->message);
810 g_error_free (error);
811
812 gtk_print_operation_run (operation, ctxt->action, NULL, NULL);
813 g_object_unref (operation);
814 } else {
815 g_signal_connect (
816 client_view, "objects-added",
817 G_CALLBACK (contacts_added), ctxt);
818 g_signal_connect (
819 client_view, "complete",
820 G_CALLBACK (view_complete), operation);
821
822 e_book_client_view_start (client_view, &error);
823
824 if (error != NULL) {
825 g_warning (
826 "%s: Failed to start view: %s",
827 G_STRFUNC, error->message);
828 g_error_free (error);
829
830 gtk_print_operation_run (operation, ctxt->action, NULL, NULL);
831 g_object_unref (operation);
832 }
833 }
834 }
835
836 void
837 e_contact_print (EBookClient *book_client,
838 EBookQuery *query,
839 const GSList *contact_list,
840 GtkPrintOperationAction action)
841 {
842 GtkPrintOperation *operation;
843 EContactPrintContext *ctxt;
844
845 ctxt = g_new0 (EContactPrintContext, 1);
846 ctxt->action = action;
847 ctxt->contact_list = e_client_util_copy_object_slist (NULL, contact_list);
848 ctxt->style = g_new0 (EContactPrintStyle, 1);
849 ctxt->page_nr = 0;
850 ctxt->pages = 0;
851
852 operation = e_print_operation_new ();
853 gtk_print_operation_set_n_pages (operation, 1);
854
855 g_object_set_data_full (
856 G_OBJECT (operation), "contact-print-ctx", ctxt, g_free);
857
858 g_signal_connect (
859 operation, "begin-print",
860 G_CALLBACK (contact_begin_print), ctxt);
861 g_signal_connect (
862 operation, "draw_page",
863 G_CALLBACK (contact_draw_page), ctxt);
864 g_signal_connect (
865 operation, "end-print",
866 G_CALLBACK (contact_end_print), ctxt);
867
868 if (book_client) {
869 gchar *query_str = e_book_query_to_string (query);
870
871 e_book_client_get_view (
872 book_client, query_str, NULL,
873 get_view_ready_cb, operation);
874
875 g_free (query_str);
876 } else {
877 gtk_print_operation_run (operation, action, NULL, NULL);
878
879 g_object_unref (operation);
880 }
881 }