diff options
Diffstat (limited to 'addressbook/printing/e-contact-print.c')
-rw-r--r-- | addressbook/printing/e-contact-print.c | 1015 |
1 files changed, 390 insertions, 625 deletions
diff --git a/addressbook/printing/e-contact-print.c b/addressbook/printing/e-contact-print.c index 32098689d9..002e284366 100644 --- a/addressbook/printing/e-contact-print.c +++ b/addressbook/printing/e-contact-print.c @@ -33,19 +33,11 @@ #include <libxml/xmlmemory.h> #include <libgnome/gnome-util.h> #include <glib/gi18n.h> -#include <libgnomeui/gnome-dialog.h> -#include <libgnomeprint/gnome-print.h> -#include <libgnomeprint/gnome-print-unit.h> -#include <libgnomeprint/gnome-print-config.h> -#include <libgnomeprint/gnome-font.h> -#include <libgnomeprint/gnome-print-job.h> -#include <libgnomeprintui/gnome-print-dialog.h> -#include <libgnomeprintui/gnome-print-job-preview.h> #include <libebook/e-book.h> #include <libebook/e-contact.h> #include <gtk/gtk.h> -#include <gtk/gtkprintunixdialog.h> +#include <libedataserver/e-flag.h> #include <libedataserver/e-xml-utils.h> #include "e-util/e-print.h" @@ -53,556 +45,340 @@ #include "e-util/e-util-private.h" #include "e-contact-print.h" - -#define SCALE 5 -#define HYPHEN_PIXELS 20 -#define HYPHEN_PENALTY ( (SCALE) * (SCALE) * (HYPHEN_PIXELS) * (HYPHEN_PIXELS) ) typedef struct _EContactPrintContext EContactPrintContext; typedef struct _ContactPrintItem ContactPrintItem; struct _EContactPrintContext { - GtkPrintContext *pc; - GtkPrintOperation *print; - GnomePrintJob *master; - PangoLayout *pl; + GtkPrintContext *context; gdouble x; gdouble y; gint column; + gdouble column_width; + gdouble column_spacing; EContactPrintStyle *style; gboolean first_section; PangoFontDescription *letter_heading_font; - char *character; + gchar *section; gboolean first_contact; - gboolean uses_book; - int type; - gint response_id; EBook *book; EBookQuery *query; - GList *contacts; -}; - -struct _ContactPrintItem -{ - EContactPrintContext *ctxt; - EContactPrintStyle *style; - EContact *contact; GList *contact_list; - EBook *book; - GtkPrintSettings *settings; - gboolean uses_book, uses_list; }; -static void -contact_draw_page (GtkPrintOperation *print, GtkPrintContext *context, gint page_nr, ContactPrintItem *cpi); - -static void -print_func (EBookView *book_view, const GList *contacts, EContactPrintContext *ctxt); - -static double -get_font_height (PangoFontDescription *font) +static gdouble +get_font_height (PangoFontDescription *desc) { - return (double)pango_font_description_get_size (font)/(double)PANGO_SCALE; + return pango_units_to_double ( + pango_font_description_get_size (desc)); } -static double -get_font_width (EContactPrintContext *context, PangoFontDescription *font, const char *text) +static gdouble +get_font_width (GtkPrintContext *context, + PangoFontDescription *desc, + const gchar *text) { - int width; - int height; + PangoLayout *layout; + gint width, height; - g_return_val_if_fail (font, 0.0); - g_return_val_if_fail (text, 0.0); + g_return_val_if_fail (desc, .0); + g_return_val_if_fail (text, .0); - g_assert (context->pl); - pango_layout_set_font_description (context->pl, font); - pango_layout_set_text (context->pl, text, -1); - pango_layout_set_width (context->pl, -1); - pango_layout_set_indent (context->pl, 0); + layout = gtk_print_context_create_pango_layout (context); - pango_layout_get_size (context->pl, - &width, - &height); + pango_layout_set_font_description (layout, desc); + pango_layout_set_text (layout, text, -1); + pango_layout_set_width (layout, -1); + pango_layout_set_indent (layout, 0); - return (double)width/(double)PANGO_SCALE; -} + pango_layout_get_size (layout, &width, &height); -static PangoFontDescription* -find_font (const char *name, double height) -{ - PangoFontDescription *desc = pango_font_description_new (); - pango_font_description_set_family (desc, name); - pango_font_description_set_size (desc, height * PANGO_SCALE); + g_object_unref (layout); - return desc; + return pango_units_to_double (width); } -static PangoFontDescription* -find_closest_font_from_weight_slant (const guchar *family, GnomeFontWeight weight, gboolean italic, gdouble size) +static void +e_contact_output (GtkPrintContext *context, + PangoFontDescription *font, + gdouble x, gdouble y, gdouble width, + const gchar *text) { - PangoFontDescription *desc = pango_font_description_new (); - pango_font_description_set_family (desc, family); - - /* GnomePrintWeight and PangoWeight values should be interchangeable: */ - pango_font_description_set_weight (desc, (PangoWeight)weight); + PangoLayout *layout; + gdouble indent; + cairo_t *cr; - if (italic) { - pango_font_description_set_style (desc, PANGO_STYLE_ITALIC); - } - pango_font_description_set_size (desc, size * PANGO_SCALE); + layout = gtk_print_context_create_pango_layout (context); - return desc; -} + if (width == -1 || get_font_width (context, font, text) <= width) + indent = .0; + else + indent = get_font_width (context, font, " "); -static void -e_contact_output(EContactPrintContext *ctxt, PangoFontDescription *font, double x, double y, double width, const gchar *text) -{ - double indent; - cairo_t *cr = gtk_print_context_get_cairo_context (ctxt->pc); - cairo_save(cr); + pango_layout_set_font_description (layout, font); + pango_layout_set_text (layout, text, -1); + pango_layout_set_width (layout, pango_units_from_double (width)); + pango_layout_set_indent (layout, pango_units_from_double (indent)); - if ( width == -1 || get_font_width(ctxt, font, text) <= width ) { - indent = 0.0; - } else { - indent = get_font_width (ctxt, font, " "); - } + cr = gtk_print_context_get_cairo_context (context); - g_assert (ctxt->pl); - pango_layout_set_font_description (ctxt->pl, font); - pango_layout_set_text (ctxt->pl, text, -1); - pango_layout_set_width (ctxt->pl, width*PANGO_SCALE); - pango_layout_set_indent (ctxt->pl, indent*PANGO_SCALE); - - cairo_move_to(cr, x, y); - pango_cairo_show_layout (cr, ctxt->pl); + cairo_save (cr); + cairo_move_to (cr, x, y); + pango_cairo_show_layout (cr, layout); cairo_restore (cr); + g_object_unref (layout); } static gdouble -e_contact_text_height(EContactPrintContext *ctxt, PangoFontDescription *font, double width, const gchar *text) +e_contact_text_height (GtkPrintContext *context, + PangoFontDescription *desc, + const gchar *text) { - gint w, h; + PangoLayout *layout; + gint width, height; - g_assert (ctxt->pl); - pango_layout_set_font_description (ctxt->pl, font); - pango_layout_set_text (ctxt->pl, text, -1); - pango_layout_set_width (ctxt->pl, 1); /* fix me width hard coded */ - pango_layout_set_indent (ctxt->pl, 0); - pango_layout_get_size (ctxt->pl, &w, &h); + layout = gtk_print_context_create_pango_layout (context); - return (double)h/(double)PANGO_SCALE; -} + pango_layout_set_font_description (layout, desc); + pango_layout_set_text (layout, text, -1); -#if 0 -static void -e_contact_output_and_advance(EContactPrintContext *ctxt, PangoFontDescription *font, double x, double width, gchar *text) -{ - ctxt->y -= .1 * get_font_height (font); - e_contact_output(ctxt->pc, font, x, ctxt->y, width, text); - ctxt->y -= e_contact_text_height(ctxt->pc, font, width, text); - ctxt->y -= .1 * get_font_height (font); -} -#endif + pango_layout_get_size (layout, &width, &height); -static void -e_contact_rectangle(GtkPrintContext *pc, - gdouble x0, - gdouble y0, - gdouble x1, - gdouble y1, - gdouble r, - gdouble g, - gdouble b) -{ - cairo_t *cr; - cr = gtk_print_context_get_cairo_context (pc); - cairo_save(cr); - cairo_set_source_rgb(cr, r, g, b); - cairo_rectangle (cr,x0, y0, x1, y1); - cairo_fill (cr); - cairo_restore (cr); -} + g_object_unref (layout); -static double -e_contact_get_letter_heading_height (EContactPrintContext *ctxt) -{ - return get_font_height (ctxt->letter_heading_font); + return pango_units_to_double (height); } static void -e_contact_print_letter_heading (EContactPrintContext *ctxt, gchar *character) +e_contact_print_letter_heading (EContactPrintContext *ctxt, gchar *letter) { - gdouble height; - gdouble width; + PangoLayout *layout; + PangoFontDescription *desc; + PangoFontMetrics *metrics; + gint width, height; cairo_t *cr; - width = get_font_width(ctxt, ctxt->letter_heading_font, "m") * 1.7; - height = get_font_height (ctxt->letter_heading_font); - - cr = gtk_print_context_get_cairo_context (ctxt->pc); - cairo_save(cr); + desc = ctxt->letter_heading_font; - e_contact_rectangle( ctxt->pc, ctxt->x, ctxt->y, width, height + 6, 0, 0, 0); - cairo_set_source_rgb(cr, 1, 1, 1); - ctxt->y += 4; - e_contact_output(ctxt, ctxt->letter_heading_font, - ctxt->x + (width - get_font_width(ctxt, ctxt->letter_heading_font, character))/ 2 - 5, - ctxt->y - 5, - -1, - character); - ctxt->y += height; - ctxt->y += 2; - ctxt->y += 3; - - cairo_restore(cr); -} + layout = gtk_print_context_create_pango_layout (ctxt->context); -static void -e_contact_start_new_page(EContactPrintContext *ctxt) -{ - cairo_t *cr; - cr = gtk_print_context_get_cairo_context (ctxt->pc); - ctxt->x = ctxt->style->left_margin; - ctxt->y = ctxt->style->top_margin; - cairo_show_page (cr); - ctxt->column = 0; -} + /* Make the rectangle thrice the average character width. + * XXX Works well for English, what about other locales? */ + metrics = pango_context_get_metrics ( + pango_layout_get_context (layout), + desc, pango_language_get_default ()); + width = pango_font_metrics_get_approximate_char_width (metrics) * 3; + pango_font_metrics_unref (metrics); -static double -e_contact_get_contact_size(EContact *contact, EContactPrintContext *ctxt) -{ - const char *file_as; - gdouble height = 0; - gdouble page_width = 72 * (ctxt->style->page_width - ctxt->style->left_margin - ctxt->style->right_margin); - gdouble column_width; - gint field; - column_width = (page_width + 18) / ctxt->style->num_columns - 18; + pango_layout_set_alignment (layout, PANGO_ALIGN_CENTER); + pango_layout_set_font_description (layout, desc); + pango_layout_set_text (layout, letter, -1); + pango_layout_set_width (layout, width); + pango_layout_get_size (layout, NULL, &height); - height += get_font_height (ctxt->style->headings_font) * .2; + /* Draw white text centered in a black rectangle. */ - height += get_font_height (ctxt->style->headings_font) * .2; + cr = gtk_print_context_get_cairo_context (ctxt->context); - file_as = e_contact_get_const (contact, E_CONTACT_FILE_AS); + cairo_save (cr); + cairo_set_source_rgb (cr, .0, .0, .0); + cairo_rectangle ( + cr, ctxt->x, ctxt->y, + pango_units_to_double (width), + pango_units_to_double (height)); + cairo_fill (cr); + cairo_restore (cr); - height += e_contact_text_height(ctxt, ctxt->style->headings_font, column_width - 4, file_as); + cairo_save (cr); + cairo_move_to (cr, ctxt->x, ctxt->y); + cairo_set_source_rgb (cr, 1., 1., 1.); + pango_cairo_show_layout (cr, layout); + cairo_restore (cr); - height += get_font_height (ctxt->style->headings_font) * .2; + ctxt->y += pango_units_to_double (height); +} - height += get_font_height (ctxt->style->headings_font) * .2; - - for(field = E_CONTACT_FILE_AS; field != E_CONTACT_LAST_SIMPLE_STRING; field++) { - char *string; - string = e_contact_get(contact, field); - if (string && *string) { - double xoff = 0; - xoff += get_font_width(ctxt, ctxt->style->body_font, e_contact_pretty_name (field)); - xoff += get_font_width(ctxt, ctxt->style->body_font, ": "); - height += e_contact_text_height(ctxt, ctxt->style->body_font, column_width - xoff, string); - height += .2 * get_font_height (ctxt->style->body_font); - } - g_free(string); - } - height += get_font_height (ctxt->style->headings_font) * .4; +static void +e_contact_start_new_page (EContactPrintContext *ctxt) +{ + cairo_t *cr; - /* g_message ("%s %g", e_card_simple_get (simple, E_CARD_SIMPLE_FIELD_FILE_AS), height); */ - return height; -} + cr = gtk_print_context_get_cairo_context (ctxt->context); + cairo_show_page (cr); + + ctxt->x = ctxt->y = .0; + ctxt->column = 0; +} static void e_contact_print_contact (EContact *contact, EContactPrintContext *ctxt) { - gdouble page_width = 72 * (ctxt->style->page_width - ctxt->style->left_margin - ctxt->style->right_margin); - gdouble column_width; char *file_as; cairo_t *cr; int field; - column_width = (page_width + 18) / ctxt->style->num_columns - 18; - cr = gtk_print_context_get_cairo_context (ctxt->pc); + cr = gtk_print_context_get_cairo_context (ctxt->context); cairo_save(cr); ctxt->y += get_font_height (ctxt->style->headings_font) * .2; - ctxt->y += get_font_height (ctxt->style->headings_font) * .2; file_as = e_contact_get (contact, E_CONTACT_FILE_AS); - if (ctxt->style->print_using_grey) - e_contact_rectangle(ctxt->pc, - ctxt->x,ctxt->y + get_font_height (ctxt->style->headings_font) * .3, - column_width, - e_contact_text_height(ctxt, - ctxt->style->headings_font, - column_width - 4, file_as) - + get_font_height (ctxt->style->headings_font) * .3, - .85, .85, .85); - - - e_contact_output(ctxt, ctxt->style->headings_font, ctxt->x + 2, ctxt->y + 5, column_width + 4, file_as); - ctxt->y += e_contact_text_height(ctxt, ctxt->style->headings_font, column_width + 4, file_as); + if (ctxt->style->print_using_grey) { + cairo_save (cr); + cairo_set_source_rgb (cr, .85, .85, .85); + cairo_rectangle (cr, ctxt->x, ctxt->y, ctxt->column_width, + e_contact_text_height (ctxt->context, + ctxt->style->headings_font, file_as)); + cairo_fill (cr); + cairo_restore (cr); + } + + e_contact_output ( + ctxt->context, ctxt->style->headings_font, + ctxt->x, ctxt->y, ctxt->column_width + 4, file_as); + ctxt->y += e_contact_text_height ( + ctxt->context, ctxt->style->headings_font, file_as); + g_free (file_as); ctxt->y += get_font_height (ctxt->style->headings_font) * .2; - ctxt->y += get_font_height (ctxt->style->headings_font) * .2; - - for(field = E_CONTACT_FILE_AS; field != E_CONTACT_LAST_SIMPLE_STRING;field++) + + for (field = E_CONTACT_FILE_AS; field != E_CONTACT_LAST_SIMPLE_STRING; field++) { - char *string; - string = e_contact_get(contact, field); - - if (string && *string) { - double xoff = 0; - - e_contact_output(ctxt, - ctxt->style->body_font, - ctxt->x + xoff, - ctxt->y + 5, - -1, - e_contact_pretty_name (field)); - - xoff += get_font_width(ctxt, ctxt->style->body_font, e_contact_pretty_name (field)); - e_contact_output(ctxt, ctxt->style->body_font, ctxt->x + xoff, ctxt->y + 5, -1, ": "); - xoff += get_font_width(ctxt, ctxt->style->body_font, ": "); - - e_contact_output(ctxt, - ctxt->style->body_font, - ctxt->x + xoff, - ctxt->y + 5, - column_width - xoff, - string); - - ctxt->y += e_contact_text_height(ctxt, ctxt->style->body_font, column_width - xoff, string); - ctxt->y += .2 * get_font_height (ctxt->style->body_font); + const gchar *value; + gchar *text; - } - g_free(string); - } - ctxt->y += get_font_height (ctxt->style->headings_font) * .4 + 8; - cairo_restore(cr); -} + value = e_contact_get_const (contact, field); + if (value == NULL || *value == '\0') + continue; -static void -e_contact_start_new_column (EContactPrintContext *ctxt) -{ - gdouble page_width = 72 * (ctxt->style->page_width - ctxt->style->left_margin - ctxt->style->right_margin); - gdouble column_offset; + text = g_strdup_printf ("%s: %s", + e_contact_pretty_name (field), value); - column_offset = (page_width + 18) / ctxt->style->num_columns; - ctxt->column ++; + e_contact_output ( + ctxt->context, ctxt->style->body_font, + ctxt->x, ctxt->y, -1, text); - if (ctxt->column >= ctxt->style->num_columns) { - e_contact_start_new_page(ctxt); - ctxt->column = 0; + ctxt->y += e_contact_text_height ( + ctxt->context, ctxt->style->body_font, text); + + ctxt->y += .2 * get_font_height (ctxt->style->body_font); + + g_free (text); } - ctxt->x = ctxt->style->left_margin + column_offset * ctxt->column; - ctxt->y = ctxt->style->top_margin + 12; + + ctxt->y += get_font_height (ctxt->style->headings_font) * .4 + 8; + + cairo_restore (cr); } static void -complete_sequence (EBookView *book_view, EBookViewStatus status, EContactPrintContext *ctxt) +e_contact_start_new_column (EContactPrintContext *ctxt) { - GList *contacts = ctxt->contacts; - - ctxt->first_contact = TRUE; - ctxt->character = NULL; - ctxt->y = ctxt->style->page_height + ctxt->style->top_margin; - ctxt->x = (ctxt->style->left_margin); - - for(; contacts; contacts = contacts->next) { - EContact *contact = contacts->data; - guchar *file_as; - gchar *letter_str = NULL; - - file_as = e_contact_get (contact, E_CONTACT_FILE_AS); - - if (file_as != NULL) { - letter_str = g_strndup (file_as, g_utf8_next_char (file_as) - (gchar *) file_as); - } - if ( file_as && (!ctxt->character || g_utf8_collate (ctxt->character, letter_str) != 0) ) { - g_free (ctxt->character); - ctxt->character = g_strdup (letter_str); - if (ctxt->style->sections_start_new_page && ! ctxt->first_contact) { - e_contact_start_new_page(ctxt); - } - else if ((!ctxt->first_contact) && (ctxt->y > ctxt->style->page_height * 60 )) - e_contact_start_new_column(ctxt); - if ( ctxt->style->letter_headings ) - e_contact_print_letter_heading(ctxt, ctxt->character); - ctxt->first_section = FALSE; - } - - else if ( (!ctxt->first_contact) && (ctxt->y > ctxt->style->page_height * 60)) { - e_contact_start_new_column(ctxt); - if ( ctxt->style->letter_headings ) - e_contact_print_letter_heading(ctxt, ctxt->character); - } - - g_free (letter_str); - e_contact_print_contact(contact, ctxt); - ctxt->first_contact = FALSE; + if (++ctxt->column >= ctxt->style->num_columns) + e_contact_start_new_page (ctxt); + else { + ctxt->x = ctxt->column * + (ctxt->column_width + ctxt->column_spacing); + ctxt->y = .0; } - - if (book_view) - g_object_unref(book_view); - - g_object_unref(ctxt->pc); - g_object_unref(ctxt->pl); - if (ctxt->book) - g_object_unref(ctxt->book); - - g_free(ctxt->character); - if (ctxt->query) - e_book_query_unref (ctxt->query); - g_list_foreach(ctxt->contacts, (GFunc) g_object_unref, NULL); - g_list_free(ctxt->contacts); - pango_font_description_free(ctxt->style->headings_font); - pango_font_description_free(ctxt->style->body_font); - pango_font_description_free(ctxt->style->header_font); - pango_font_description_free(ctxt->style->footer_font); - pango_font_description_free(ctxt->letter_heading_font); - g_free(ctxt->style); } static int contact_compare (EContact *contact1, EContact *contact2) { - if (contact1 && contact2) { - const char *file_as1, *file_as2; - file_as1 = e_contact_get_const (contact1, E_CONTACT_FILE_AS); - file_as2 = e_contact_get_const (contact2, E_CONTACT_FILE_AS); - - if (file_as1 && file_as2) - return g_utf8_collate(file_as1, file_as2); - if (file_as1) - return -1; - if (file_as2) - return 1; - return strcmp(e_contact_get_const(contact1, E_CONTACT_UID), e_contact_get_const(contact2, E_CONTACT_UID)); - } else { + const gchar *field1, *field2; + + if (contact1 == NULL || contact2 == NULL) return 0; - } -} -static void -create_contact(EBookView *book_view, const GList *contacts, EContactPrintContext *ctxt) -{ - for(; contacts; contacts = contacts->next) { - EContact *contact = contacts->data; - g_object_ref(contact); - ctxt->contacts = g_list_insert_sorted(ctxt->contacts, contact, (GCompareFunc) contact_compare); - } -} + field1 = e_contact_get_const (contact1, E_CONTACT_FILE_AS); + field2 = e_contact_get_const (contact2, E_CONTACT_FILE_AS); -static void -book_view_loaded (EBook *book, EBookStatus status, EBookView *book_view, EContactPrintContext *ctxt) -{ - g_object_ref(book_view); - - g_signal_connect(book_view, - "contacts_added", - G_CALLBACK(create_contact), - ctxt); - g_signal_connect(book_view, - "sequence_complete", - G_CALLBACK(print_func), - ctxt); - e_book_view_start (book_view); -} + if (field1 != NULL && field2 != NULL) + return g_utf8_collate (field1, field2); -static void -print_func (EBookView *book_view, const GList *contacts, EContactPrintContext *ctxt) -{ - GtkPrintSettings *settings; - settings = gtk_print_settings_new (); - /* runs a print dialog, emittings signals */ - if(ctxt->response_id == GTK_RESPONSE_APPLY) - gtk_print_operation_run (ctxt->print, GTK_PRINT_OPERATION_ACTION_PREVIEW, NULL, NULL); - else - gtk_print_operation_run (ctxt->print, GTK_PRINT_OPERATION_ACTION_PRINT_DIALOG, NULL, NULL); - settings = gtk_print_operation_get_print_settings (ctxt->print); - e_print_save_settings (settings); -} + if (field1 != NULL || field2 != NULL) + return (field1 != NULL) ? -1 : 1; -static void -e_contact_do_print_contacts (EBook *book, EBookQuery *query, EContactPrintContext *ctxt) -{ - EBookView *bookview; - gboolean status; + field1 = e_contact_get_const (contact1, E_CONTACT_UID); + field2 = e_contact_get_const (contact2, E_CONTACT_UID); + + g_assert (field1 != NULL && field2 != NULL); - status = e_book_get_book_view (book, query, NULL, -1, &bookview, NULL); - book_view_loaded (book, 1, bookview, ctxt); + return strcmp (field1, field2); } - -static void -e_contact_do_print (EBook *book, EBookQuery *query, EContactPrintContext *ctxt) -{ - switch ( ctxt->style->type ) { - case E_CONTACT_PRINT_TYPE_CARDS: - e_contact_do_print_contacts( book, query, ctxt); - break; - default: - break; + +static void +contacts_added (EBookView *book_view, const GList *contact_list, + EContactPrintContext *ctxt) +{ + while (contact_list != NULL) { + ctxt->contact_list = g_list_insert_sorted( + ctxt->contact_list, + g_object_ref (contact_list->data), + (GCompareFunc) contact_compare); + contact_list = contact_list->next; } } -static void lowify( char *data ) +static void +sequence_complete (EBookView *book_view, const GList *contact_list, + EFlag *book_view_started) { - for ( ; *data; data++ ) - *data = tolower((unsigned char) *data); + e_flag_set (book_view_started); } -static gboolean get_bool( char *data ) +static gboolean +get_bool (gchar *data) { - if ( data ) { - lowify ( data ); - return ! strcmp(data, "true"); - } else + if (data) + return (g_ascii_strcasecmp (data, "true") == 0); + else return FALSE; } -static void get_string( char *data, char **variable ) +static void +get_string (gchar *data, gchar **variable) { - g_free ( *variable ); - if ( data ) - *variable = g_strdup( data ); - else - *variable = g_strdup( "" ); + g_free (*variable); + *variable = g_strdup ((data != NULL) ? data : ""); } -static int get_integer( char *data ) +static gint +get_integer (gchar *data) { - if ( data ) - return atoi(data); - else - return 0; + return (data != NULL) ? atoi (data) : 0; } -static double get_float( char *data ) +static gdouble +get_float (gchar *data) { - if ( data ) - return atof(data); - else - return 0; + return (data != NULL) ? atof (data) : .0; } -static void get_font( char *data, PangoFontDescription **variable ) +static void +get_font (gchar *data, PangoFontDescription **variable) { - if ( data ) { - PangoFontDescription *font = pango_font_description_from_string ( data ); - if ( font ) { - pango_font_description_free(*variable); - *variable = font; - } + PangoFontDescription *desc = NULL; + + if (data != NULL) + desc = pango_font_description_from_string (data); + + if (desc != NULL) { + pango_font_description_free (*variable); + *variable = desc; } } - static void -e_contact_build_style(EContactPrintStyle *style, GtkPrintSettings *config) +e_contact_build_style (EContactPrintStyle *style) { xmlDocPtr styledoc; gchar *filename; @@ -614,8 +390,8 @@ e_contact_build_style(EContactPrintStyle *style, GtkPrintSettings *config) style->blank_forms = 2; style->letter_headings = FALSE; - style->headings_font = find_closest_font_from_weight_slant ("Sans", GNOME_FONT_BOLD, FALSE, 8); - style->body_font = find_closest_font_from_weight_slant ("Sans", GNOME_FONT_BOOK, FALSE, 6); + style->headings_font = pango_font_description_from_string ("Sans Bold 8"); + style->body_font = pango_font_description_from_string ("Sans 6"); style->print_using_grey = TRUE; style->paper_type = 0; @@ -639,21 +415,23 @@ e_contact_build_style(EContactPrintStyle *style, GtkPrintSettings *config) #endif style->orientation_portrait = FALSE; - style->header_font = find_closest_font_from_weight_slant ("Sans", GNOME_FONT_BOOK, FALSE, 6); + style->header_font = pango_font_description_copy (style->body_font); style->left_header = g_strdup(""); style->center_header = g_strdup(""); style->right_header = g_strdup(""); - style->footer_font = find_closest_font_from_weight_slant ("Sans", GNOME_FONT_BOOK, FALSE, 6); + style->footer_font = pango_font_description_copy (style->body_font); - style->left_footer = g_strdup(""); - style->center_footer = g_strdup(""); - style->right_footer = g_strdup(""); + style->left_footer = g_strdup (""); + style->center_footer = g_strdup (""); + style->right_footer = g_strdup (""); style->reverse_on_even_pages = FALSE; - filename = g_build_filename(EVOLUTION_ECPSDIR, "medbook.ecps", NULL); + + filename = g_build_filename (EVOLUTION_ECPSDIR, "medbook.ecps", NULL); styledoc = e_xml_parse_file (filename); - g_free(filename); + g_free (filename); + if (styledoc) { xmlNodePtr stylenode = xmlDocGetRootElement(styledoc); xmlNodePtr node; @@ -662,12 +440,11 @@ e_contact_build_style(EContactPrintStyle *style, GtkPrintSettings *config) if ( !strcmp( node->name, "title" ) ) { get_string(data, &(style->title)); } else if ( !strcmp( node->name, "type" ) ) { - lowify( data ); - if ( !strcmp( data, "cards" ) ) + if (g_ascii_strcasecmp (data, "cards") == 0) style->type = E_CONTACT_PRINT_TYPE_CARDS; - else if ( !strcmp( data, "memo_style" ) ) + else if (g_ascii_strcasecmp (data, "memo_style") == 0) style->type = E_CONTACT_PRINT_TYPE_MEMO_STYLE; - else if ( !strcmp( data, "phone_list" ) ) + else if (g_ascii_strcasecmp (data, "phone_list") == 0) style->type = E_CONTACT_PRINT_TYPE_PHONE_LIST; } else if ( !strcmp( node->name, "sections_start_new_page" ) ) { style->sections_start_new_page = get_bool(data); @@ -701,8 +478,8 @@ e_contact_build_style(EContactPrintStyle *style, GtkPrintSettings *config) style->page_height = get_float(data); } else if ( !strcmp( node->name, "orientation" ) ) { if ( data ) { - lowify(data); - style->orientation_portrait = strcmp(data, "landscape"); + style->orientation_portrait = + (g_ascii_strcasecmp (data, "landscape") != 0); } else { style->orientation_portrait = TRUE; } @@ -733,204 +510,192 @@ e_contact_build_style(EContactPrintStyle *style, GtkPrintSettings *config) } -static gint -e_contact_print_close(GnomeDialog *dialog, gpointer data) +static void +load_contacts (EContactPrintContext *ctxt) { - return FALSE; + /* Load contacts from the EBook. This is an asynchronous operation + * but we force it to be synchronous here. */ + + EBookView *book_view; + EFlag *book_view_started; + + book_view_started = e_flag_new (); + + e_book_get_book_view ( + ctxt->book, ctxt->query, NULL, -1, &book_view, NULL); + + g_signal_connect ( + book_view, "contacts_added", + G_CALLBACK (contacts_added), ctxt); + g_signal_connect ( + book_view, "sequence_complete", + G_CALLBACK (sequence_complete), book_view_started); + + e_book_view_start (book_view); + + while (!e_flag_is_set (book_view_started)) + g_main_context_iteration (NULL, TRUE); + + e_flag_free (book_view_started); } -void -e_contact_print_response(GtkWidget *dialog, gint response_id, gpointer data) +static void +free_contacts (EContactPrintContext *ctxt) { -#ifdef G_OS_UNIX /* Just to get it to build on Win32 */ - GtkPrintSettings *settings; - GtkPaperSize *paper_size; - GtkPageSetup *page_setup; - GList *contact_list = NULL; - EBook *book = NULL; - EBookQuery *query = NULL; - EContact *contact = NULL; - gdouble font_size; - gboolean uses_book = FALSE, uses_list = FALSE, uses_range = FALSE; - - EContactPrintContext *ctxt = g_new0 (EContactPrintContext, 1); - EContactPrintStyle *style = g_new0 (EContactPrintStyle, 1); - ContactPrintItem *cpi = g_new0 (ContactPrintItem, 1); - - settings = gtk_print_unix_dialog_get_settings (GTK_PRINT_UNIX_DIALOG (dialog)); - uses_range = GPOINTER_TO_INT (g_object_get_data(G_OBJECT (dialog),"uses_range")); - - if (uses_range) { - if (gtk_print_settings_get_print_pages (settings) == GTK_PRINT_PAGES_ALL) { - uses_book = TRUE; - } - if (gtk_print_settings_get_print_pages (settings) == GTK_PRINT_PAGES_CURRENT) - uses_list = TRUE; - } - else { - uses_book = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (dialog), "uses_book")); - uses_list = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (dialog), "uses_list")); - } - if (uses_book) { - book = g_object_get_data(G_OBJECT(dialog), "book"); - query = g_object_get_data(G_OBJECT(dialog), "query"); - e_book_query_ref (query); - } - else if (uses_list) { - contact_list = g_object_get_data(G_OBJECT(dialog), "contact_list"); - } - else { - contact = g_object_get_data(G_OBJECT(dialog), "contact"); - } - - page_setup = gtk_page_setup_new (); - paper_size = gtk_paper_size_new ("iso_a4"); /* FIXME paper size hardcoded */ - gtk_page_setup_set_paper_size (page_setup, paper_size); - ctxt->print = gtk_print_operation_new (); - gtk_print_operation_set_default_page_setup (ctxt->print, page_setup); - gtk_print_operation_set_n_pages (ctxt->print, 1); - gtk_print_settings_set_print_pages (settings, GTK_PRINT_PAGES_ALL); - - /* style information */ - e_contact_build_style(style, settings); - style->page_height = gtk_page_setup_get_paper_height (page_setup, GTK_UNIT_INCH); - style->page_width = gtk_page_setup_get_paper_width (page_setup, GTK_UNIT_INCH); - ctxt->x = 0; - ctxt->y = 0; + g_list_foreach (ctxt->contact_list, (GFunc) g_object_unref, NULL); + g_list_free (ctxt->contact_list); +} + +static void +contact_begin_print (GtkPrintOperation *operation, + GtkPrintContext *context, + EContactPrintContext *ctxt) +{ + GtkPageSetup *setup; + gdouble page_width; + + e_contact_build_style (ctxt->style); + + setup = gtk_print_context_get_page_setup (context); + page_width = gtk_page_setup_get_page_width (setup, GTK_UNIT_POINTS); + + ctxt->context = context; + ctxt->x = ctxt->y = .0; ctxt->column = 0; - ctxt->style = style; + ctxt->first_contact = TRUE; ctxt->first_section = TRUE; - ctxt->type = GTK_RESPONSE_OK; - font_size = 72 * ctxt->style->page_height / 27.0 / 2.0; - ctxt->letter_heading_font = find_font (pango_font_description_get_family (ctxt->style->headings_font), - get_font_height (ctxt->style->headings_font)*1.5); - ctxt->book = book; - ctxt->query = query; - ctxt->response_id = response_id; - cpi->uses_book = uses_book; - cpi->uses_list = uses_list; - cpi->settings = settings; - cpi->ctxt = ctxt; - cpi->contact= contact; - cpi->ctxt->contacts = NULL; - cpi->contact_list= contact_list; - cpi->book = book; - gtk_print_operation_set_print_settings (ctxt->print, settings); - g_signal_connect (ctxt->print, "draw_page",G_CALLBACK (contact_draw_page), cpi); - - if (!uses_book) { - if(ctxt->response_id == GTK_RESPONSE_APPLY) - gtk_print_operation_run (ctxt->print, GTK_PRINT_OPERATION_ACTION_PREVIEW, NULL, NULL); - else - gtk_print_operation_run (ctxt->print, GTK_PRINT_OPERATION_ACTION_PRINT_DIALOG, NULL, NULL); - settings = gtk_print_operation_get_print_settings (ctxt->print); - e_print_save_settings (settings); - } - else - e_contact_do_print_contacts (book, query, ctxt); - - g_object_unref (cpi); - if (!uses_book) { - g_object_unref (ctxt->print); - g_free (ctxt); - } - gtk_widget_destroy (dialog); -#else - g_warning ("Not implemented currently on Windows"); -#endif -} + ctxt->section = NULL; + ctxt->column_spacing = gtk_print_context_get_dpi_x (context) / 4; + ctxt->column_width = (page_width + ctxt->column_spacing) / + ctxt->style->num_columns - ctxt->column_spacing; + + ctxt->letter_heading_font = pango_font_description_new (); + pango_font_description_set_family ( + ctxt->letter_heading_font, + pango_font_description_get_family ( + ctxt->style->headings_font)); + pango_font_description_set_size ( + ctxt->letter_heading_font, + pango_font_description_get_size ( + ctxt->style->headings_font) * 1.5); + + if (ctxt->book != NULL) + load_contacts (ctxt); +} -GtkWidget * -e_contact_print_dialog_new(EBook *book, char *query, GList *list) +static void +contact_draw (EContact *contact, EContactPrintContext *ctxt) { - GtkWidget *dialog; - GList *copied_list = NULL; - GList *l; - - dialog = e_print_get_dialog(_("Print contacts"), 0); - - if (list != NULL) { - copied_list = g_list_copy (list); - for (l = copied_list; l; l = l->next) - l->data = e_contact_duplicate (E_CONTACT (l->data)); + GtkPageSetup *setup; + gdouble page_height; + gchar *file_as; + gboolean new_section = FALSE; + + setup = gtk_print_context_get_page_setup (ctxt->context); + page_height = gtk_page_setup_get_page_height (setup, GTK_UNIT_POINTS); + + file_as = e_contact_get (contact, E_CONTACT_FILE_AS); + + if (file_as != NULL) { + gchar *section; + gsize width; + + width = g_utf8_next_char (file_as) - file_as; + section = g_utf8_strup (file_as, width); + + new_section = (ctxt->section == NULL || + g_utf8_collate (ctxt->section, section) != 0); + + if (new_section) { + g_free (ctxt->section); + ctxt->section = section; + } else + g_free (section); + } + + if (new_section) { + if (!ctxt->first_contact) { + if (ctxt->style->sections_start_new_page) + e_contact_start_new_page (ctxt); + else if (ctxt->y > page_height) + e_contact_start_new_column (ctxt); + } + if (ctxt->style->letter_headings) + e_contact_print_letter_heading (ctxt, ctxt->section); + ctxt->first_section = FALSE; + } + + else if (!ctxt->first_contact && (ctxt->y > page_height)) { + e_contact_start_new_column (ctxt); + if (ctxt->style->letter_headings) + e_contact_print_letter_heading (ctxt, ctxt->section); } - g_object_ref(book); - g_object_set_data(G_OBJECT(dialog), "contact_list", copied_list); - g_object_set_data(G_OBJECT(dialog), "book", book); - g_object_set_data(G_OBJECT(dialog), "query", e_book_query_from_string (query)); - g_object_set_data(G_OBJECT(dialog), "uses_range", GINT_TO_POINTER (TRUE)); - - g_signal_connect(dialog, - "response", G_CALLBACK(e_contact_print_response), NULL); - g_signal_connect(dialog, - "close", G_CALLBACK(e_contact_print_close), NULL); - return dialog; + e_contact_print_contact (contact, ctxt); + + ctxt->first_contact = FALSE; } -GtkWidget * -e_contact_print_contact_dialog_new(EContact *contact) +static void +contact_draw_page (GtkPrintOperation *operation, + GtkPrintContext *context, + gint page_nr, + EContactPrintContext *ctxt) { - GtkWidget *dialog; - - dialog = e_print_get_dialog(_("Print contact"), 0); - contact = e_contact_duplicate(contact); - g_object_set_data(G_OBJECT(dialog), "contact", contact); - g_object_set_data(G_OBJECT(dialog), "uses_list", GINT_TO_POINTER (FALSE)); - g_object_set_data(G_OBJECT(dialog), "uses_book", GINT_TO_POINTER (FALSE)); - g_object_set_data(G_OBJECT(dialog), "uses_range", GINT_TO_POINTER (FALSE)); - g_signal_connect(dialog, - "response", G_CALLBACK(e_contact_print_response), NULL); - g_signal_connect(dialog, - "close", G_CALLBACK(e_contact_print_close), NULL); - return dialog; + g_list_foreach (ctxt->contact_list, (GFunc) contact_draw, ctxt); } - -GtkWidget * -e_contact_print_contact_list_dialog_new(GList *list) + +static void +contact_end_print (GtkPrintOperation *operation, + GtkPrintContext *context, + EContactPrintContext *ctxt) { - GtkWidget *dialog; - GList *copied_list; - GList *l; - - if (list == NULL) - return NULL; - - copied_list = g_list_copy (list); - for (l = copied_list; l; l = l->next) - l->data = e_contact_duplicate (E_CONTACT (l->data)); - - dialog = e_print_get_dialog(_("Print contact"), 0); - - g_object_set_data(G_OBJECT(dialog), "contact_list", copied_list); - g_object_set_data(G_OBJECT(dialog), "uses_list", GINT_TO_POINTER (TRUE)); - g_object_set_data(G_OBJECT(dialog), "uses_book", GINT_TO_POINTER (FALSE)); - g_object_set_data(G_OBJECT(dialog), "uses_range", GINT_TO_POINTER (FALSE)); - g_signal_connect(dialog, - "response", G_CALLBACK(e_contact_print_response), NULL); - g_signal_connect(dialog, - "close", G_CALLBACK(e_contact_print_close), NULL); - return dialog; + pango_font_description_free (ctxt->style->headings_font); + pango_font_description_free (ctxt->style->body_font); + pango_font_description_free (ctxt->style->header_font); + pango_font_description_free (ctxt->style->footer_font); + pango_font_description_free (ctxt->letter_heading_font); + + g_free (ctxt->section); + + if (ctxt->book != NULL) + free_contacts (ctxt); } -static void -contact_draw_page (GtkPrintOperation *print, GtkPrintContext *context, gint page_nr, ContactPrintItem *cpi) +void +e_contact_print (EBook *book, EBookQuery *query, + GList *contact_list, GtkPrintOperationAction action) { - cpi->ctxt->pc = context; - g_object_ref (cpi->ctxt->pc); - cpi->ctxt->pl =gtk_print_context_create_pango_layout (context); - - if (cpi->uses_book) { - complete_sequence(NULL, E_BOOK_VIEW_STATUS_OK, cpi->ctxt); - } - - else if (cpi->uses_list) { - cpi->ctxt->contacts = cpi->contact_list; - complete_sequence(NULL, E_BOOK_VIEW_STATUS_OK, cpi->ctxt); - } - else { - cpi->ctxt->contacts = g_list_append(NULL,cpi->contact); - complete_sequence(NULL, E_BOOK_VIEW_STATUS_OK, cpi->ctxt); - } + GtkPrintOperation *operation; + EContactPrintContext ctxt; + EContactPrintStyle style; + + if (book != NULL) { + ctxt.book = book; + ctxt.query = query; + ctxt.contact_list = NULL; + } else { + ctxt.book = NULL; + ctxt.query = NULL; + ctxt.contact_list = contact_list; + } + ctxt.style = &style; + + operation = e_print_operation_new (); + gtk_print_operation_set_n_pages (operation, 1); + + g_signal_connect ( + operation, "begin-print", + G_CALLBACK (contact_begin_print), &ctxt); + g_signal_connect ( + operation, "draw_page", + G_CALLBACK (contact_draw_page), &ctxt); + g_signal_connect ( + operation, "end-print", + G_CALLBACK (contact_end_print), &ctxt); + + gtk_print_operation_run (operation, action, NULL, NULL); + + g_object_unref (operation); } |