This is a very simple way to print a treeview.
Is based on the Foundations_of_GTK_Development book chapter 12.
Code:
#include <gtk/gtk.h>
#include <math.h>
#define HEADER_HEIGHT 20.0
#define HEADER_GAP 8.5
#define MAX_LIN 100
enum
{
COL_1,
COL_2,
COL_3,
COL_4,
COL_5,
COL_6,
COL_7,
COL_8,
COL_9,
N_COLS
};
typedef struct
{
gdouble font_size;
gint lines_per_page;
gint total_lines;
gint total_pages;
GtkTreeModel *model;
GtkTreePath *path;
GtkTreeIter iter;
gint height;
} PrintData;
typedef struct
{
GtkWidget *window, *chooser;
GtkWidget *treeview;
PrintData *data;
} Widgets;
GtkPrintSettings *settings;
static void print_treeview (GtkButton*, Widgets*);
static void begin_print (GtkPrintOperation*, GtkPrintContext*, Widgets*);
static void draw_page (GtkPrintOperation*, GtkPrintContext*, gint, Widgets*);
static void end_print (GtkPrintOperation*, GtkPrintContext*, Widgets*);
int main (int argc, char *argv[])
{
GtkWidget *hbox, *print;
Widgets *w;
GtkWidget *scroll;
GtkListStore *store;
GtkTreeIter iter;
GtkTreeViewColumn *column;
GtkCellRenderer *renderer;
gint i;
gtk_init (&argc, &argv);
w = g_slice_new (Widgets);
w->window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
gtk_window_set_title (GTK_WINDOW (w->window), "Printing");
gtk_container_set_border_width (GTK_CONTAINER (w->window), 10);
gtk_widget_set_size_request (w->window, 200, -1);
//gtk_window_maximize(GTK_WINDOW (w->window));
g_signal_connect (G_OBJECT (w->window), "destroy",G_CALLBACK (gtk_main_quit), NULL);
print = gtk_button_new_from_stock (GTK_STOCK_PRINT);
g_signal_connect (G_OBJECT (print), "clicked",G_CALLBACK (print_treeview), (gpointer) w);
scroll = gtk_scrolled_window_new (NULL, NULL);
gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scroll),GTK_POLICY_AUTOMATIC,GTK_POLICY_AUTOMATIC);
w->treeview = gtk_tree_view_new();
gtk_tree_view_set_grid_lines(GTK_TREE_VIEW(w->treeview),GTK_TREE_VIEW_GRID_LINES_BOTH);
gtk_tree_view_set_rules_hint(GTK_TREE_VIEW(w->treeview),TRUE); //diferent colors in each line
store = gtk_list_store_new(N_COLS,G_TYPE_UINT,G_TYPE_STRING,G_TYPE_STRING,G_TYPE_STRING
,G_TYPE_STRING, G_TYPE_STRING,G_TYPE_STRING,G_TYPE_STRING,G_TYPE_STRING);
for( i = 0; i < MAX_LIN; i++ )
{
gtk_list_store_append( store, &iter );
gtk_list_store_set( store, &iter,
COL_1, i,
COL_2, g_strdup_printf( "Sample %d", i + 1),
COL_3, g_strdup_printf( "S3 %d", i + 1 ),
COL_4, g_strdup_printf( "S4 %d", i + 1),
COL_5, g_strdup_printf( "S5 %d", i + 1),
COL_6, g_strdup_printf( "S6 %d", i + 1 ),
COL_7, g_strdup_printf( "S7 %d", i + 1),
COL_8, g_strdup_printf( "S8 %d", i + 1 ),
COL_9, g_strdup_printf( "S9 %d", i + 1),
-1 );
}
gtk_tree_view_set_model( GTK_TREE_VIEW( w->treeview ),
GTK_TREE_MODEL( store ) );
g_object_unref( G_OBJECT( store ) );
for(i=0;i < 9;i++)
{
renderer = gtk_cell_renderer_text_new();
column = gtk_tree_view_column_new();
gtk_cell_layout_pack_start(GTK_CELL_LAYOUT(column), renderer, TRUE );
gtk_tree_view_column_set_attributes(column, renderer,"text",i, NULL );
gtk_tree_view_column_set_title(column,g_strdup_printf( "Column %d",i + 1));
gtk_tree_view_column_set_resizable(column,TRUE);
gtk_tree_view_column_set_sizing(column,GTK_TREE_VIEW_COLUMN_FIXED);
gtk_tree_view_column_set_fixed_width(column,40);
gtk_tree_view_append_column( GTK_TREE_VIEW(w->treeview),column);
}
gtk_container_add(GTK_CONTAINER(scroll),w->treeview);
hbox = gtk_hbox_new (FALSE, 5);
gtk_box_pack_start (GTK_BOX (hbox), print, FALSE, FALSE, 0);
gtk_box_pack_start (GTK_BOX (hbox), scroll, TRUE, TRUE, 0);
gtk_container_add (GTK_CONTAINER (w->window), hbox);
gtk_widget_show_all (w->window);
gtk_main ();
return 0;
}
static void print_treeview (GtkButton *button,Widgets *w)
{
GtkPrintOperation *operation;
GtkWidget *dialog;
GError *error = NULL;
gint res;
operation = gtk_print_operation_new ();
if (settings != NULL) gtk_print_operation_set_print_settings (operation, settings);
w->data = g_slice_new (PrintData);
w->data->font_size = 10.0;
g_signal_connect (G_OBJECT (operation), "begin_print", G_CALLBACK (begin_print), (gpointer) w);
g_signal_connect (G_OBJECT (operation), "draw_page", G_CALLBACK (draw_page), (gpointer) w);
g_signal_connect (G_OBJECT (operation), "end_print", G_CALLBACK (end_print), (gpointer) w);
res = gtk_print_operation_run (operation, GTK_PRINT_OPERATION_ACTION_PRINT_DIALOG, GTK_WINDOW (w->window), &error);
//gtk_print_operation_run (operation, GTK_PRINT_OPERATION_ACTION_PREVIEW,GTK_WINDOW(w->window),NULL);
if (res == GTK_PRINT_OPERATION_RESULT_APPLY)
{
if (settings != NULL) g_object_unref (settings);
settings = g_object_ref (gtk_print_operation_get_print_settings (operation));
}
else if (error)
{
dialog = gtk_message_dialog_new (GTK_WINDOW (w->window),
GTK_DIALOG_DESTROY_WITH_PARENT,
GTK_MESSAGE_ERROR, GTK_BUTTONS_CLOSE,
error->message);
g_error_free (error);
gtk_dialog_run (GTK_DIALOG (dialog));
gtk_widget_destroy (dialog);
}
g_object_unref (operation);
}
static void begin_print (GtkPrintOperation *operation, GtkPrintContext *context, Widgets *w)
{
gdouble height;
GdkRectangle rect;
w->data->total_lines = MAX_LIN;
w->data->model = gtk_tree_view_get_model(GTK_TREE_VIEW(w->treeview));
w->data->path = gtk_tree_path_new_first();
gtk_tree_view_get_cell_area(GTK_TREE_VIEW(w->treeview),w->data->path,NULL,&rect);
w->data->height = rect.height;
height = gtk_print_context_get_height (context) - HEADER_HEIGHT - HEADER_GAP;
w->data->lines_per_page = floor (height / w->data->height);
w->data->total_pages = (w->data->total_lines - 1) / w->data->lines_per_page + 1;
gtk_print_operation_set_n_pages (operation, w->data->total_pages);
}
static void draw_page (GtkPrintOperation *operation,GtkPrintContext *context,gint page_nr,Widgets *w)
{
cairo_t *cr;
PangoLayout *layout;
gdouble width, text_height;
gint text_width, layout_height;
PangoFontDescription *desc;
gchar *page_str;
GtkTreeViewColumn *column;
gboolean visible;
GValue value = {0};
GString *text;
gint col_num;
GdkRectangle rect;
gint i,x,y;
text = g_string_new("");
cr = gtk_print_context_get_cairo_context (context);
width = gtk_print_context_get_width (context);
layout = gtk_print_context_create_pango_layout (context);
desc = pango_font_description_from_string ("Monospace");
pango_font_description_set_size (desc, w->data->font_size * PANGO_SCALE);
pango_layout_set_font_description (layout, desc);
pango_layout_set_text (layout, "print tree view", -1);
pango_layout_set_width (layout, -1);
pango_layout_set_alignment (layout, PANGO_ALIGN_LEFT);
pango_layout_get_size (layout, NULL, &layout_height);
text_height = (gdouble) layout_height / PANGO_SCALE;
cairo_move_to (cr, 0, (HEADER_HEIGHT - text_height) / 2);
pango_cairo_show_layout (cr, layout);
page_str = g_strdup_printf ("%d of %d", page_nr + 1, w->data->total_pages);
pango_layout_set_text (layout, page_str, -1);
pango_layout_get_size (layout, &text_width, NULL);
pango_layout_set_alignment (layout, PANGO_ALIGN_RIGHT);
cairo_move_to (cr, width - (text_width / PANGO_SCALE),
(HEADER_HEIGHT - text_height) / 2);
pango_cairo_show_layout (cr, layout);
cairo_move_to (cr, 0, HEADER_HEIGHT + HEADER_GAP);
y = HEADER_HEIGHT;
for (i = 0; i < w->data->lines_per_page && gtk_tree_model_get_iter(w->data->model,&w->data->iter,w->data->path); i++)
{
x = 0;
for(col_num=0;col_num < gtk_tree_model_get_n_columns(w->data->model);col_num++)
{
column = gtk_tree_view_get_column(GTK_TREE_VIEW(w->treeview),col_num);
visible = gtk_tree_view_column_get_visible(column);
if(visible)
{
gtk_tree_model_get_value(w->data->model,&w->data->iter,col_num,&value);
switch(G_VALUE_TYPE(&value))
{
case G_TYPE_STRING:
{
if(g_value_get_string(&value) != NULL) g_string_assign(text,g_value_get_string(&value));
} break;
case G_TYPE_UINT:
{
g_string_printf(text,"%d",g_value_get_uint(&value));
} break;
case G_TYPE_ULONG:
{
g_string_printf(text,"%lu",g_value_get_ulong(&value));
} break;
}
g_value_unset(&value);
}
gtk_tree_view_get_background_area(GTK_TREE_VIEW(w->treeview),w->data->path,column,&rect);
pango_layout_set_text(layout,text->str, -1);
pango_layout_set_width(layout,rect.width * PANGO_SCALE);
pango_layout_set_wrap(layout,PANGO_WRAP_CHAR);
pango_layout_set_ellipsize(layout,PANGO_ELLIPSIZE_END);
cairo_move_to (cr, x, y);
pango_cairo_show_layout (cr, layout);
x += (rect.width+3);
}
y += w->data->height;
gtk_tree_path_next(w->data->path);
}
g_string_free(text,TRUE);
g_free (page_str);
g_object_unref (layout);
pango_font_description_free (desc);
}
static void end_print (GtkPrintOperation *operation, GtkPrintContext *context,Widgets *w)
{
gtk_tree_path_free(w->data->path);
g_slice_free1 (sizeof (PrintData), w->data);
w->data = NULL;
}