X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=src%2Fui%2Fgui%2Fpsppire-output-view.c;h=7e8b5b3560c11baa069938cb39532d583a340eb2;hb=01fc7026c655cbea3e0de1e05ace3865d6247513;hp=3a7ce4d357bb70b8e2a9e5a6f5e812fa33826b44;hpb=355f0104f7b496494d4ca4fe71162e3df0754226;p=pspp diff --git a/src/ui/gui/psppire-output-view.c b/src/ui/gui/psppire-output-view.c index 3a7ce4d357..7e8b5b3560 100644 --- a/src/ui/gui/psppire-output-view.c +++ b/src/ui/gui/psppire-output-view.c @@ -21,6 +21,9 @@ #include #include +#if HAVE_RSVG +#include "librsvg/rsvg.h" +#endif #include "libpspp/assertion.h" #include "libpspp/string-map.h" #include "output/cairo.h" @@ -30,6 +33,7 @@ #include "output/group-item.h" #include "output/message-item.h" #include "output/output-item.h" +#include "output/output-item-provider.h" #include "output/table-item.h" #include "output/text-item.h" @@ -59,13 +63,15 @@ struct psppire_output_view struct string_map render_opts; GtkTreeView *overview; - GtkTreeIter cur_command; - bool in_command; + GtkTreePath *cur_group; GtkWidget *toplevel; + guint buttontime; /* Time of the button event */ + struct output_view_item *items; size_t n_items, allocated_items; + struct output_view_item *selected_item; /* Variables pertaining to printing */ GtkPrintSettings *print_settings; @@ -83,21 +89,21 @@ enum N_COLS }; +static GtkTargetList *build_target_list (const struct output_item *item); +static void clipboard_get_cb (GtkClipboard *clipboard, + GtkSelectionData *selection_data, + guint info, + gpointer data); + /* Draws a white background on the GtkLayout to match the white background of each of the output items. */ static gboolean layout_draw_callback (GtkWidget *widget, cairo_t *cr, gpointer data) { - cairo_save (cr); - int width = gtk_widget_get_allocated_width (widget); int height = gtk_widget_get_allocated_height (widget); - cairo_rectangle (cr, 0, 0, width, height); - cairo_set_source_rgb (cr, 1.0, 1.0, 1.0); - cairo_fill (cr); - - cairo_restore (cr); - + GtkStyleContext *context = gtk_widget_get_style_context (widget); + gtk_render_background (context, cr, 0, 0, width, height); return FALSE; /* Continue drawing the GtkDrawingAreas. */ } @@ -109,8 +115,21 @@ draw_callback (GtkWidget *widget, cairo_t *cr, gpointer data) return TRUE; struct xr_rendering *r = g_object_get_data (G_OBJECT (widget), "rendering"); + + /* Draw the background based on the state of the widget + which can be selected or not selected */ + GtkStyleContext *context = gtk_widget_get_style_context (widget); + gtk_render_background (context, cr, clip.x, clip.y, + clip.x + clip.width, clip.y + clip.height); + /* Select the default foreground color based on current style + and state of the widget */ + GtkStateFlags state = gtk_widget_get_state_flags (widget); + GdkRGBA color; + gtk_style_context_get_color (context, state, &color); + cairo_set_source_rgba (cr, color.red, color.green, color.blue, color.alpha); xr_rendering_draw (r, cr, clip.x, clip.y, clip.x + clip.width, clip.y + clip.height); + return TRUE; } @@ -164,18 +183,24 @@ create_xr (struct psppire_output_view *view) struct string_map options; string_map_clone (&options, &view->render_opts); - cairo_t *cr = gdk_cairo_create ( - gtk_widget_get_window (GTK_WIDGET (view->output))); + + GdkWindow *win = gtk_layout_get_bin_window (view->output); + cairo_region_t *region = gdk_window_get_visible_region (win); + GdkDrawingContext *ctx = gdk_window_begin_draw_frame (win, region); + cairo_t *cr = gdk_drawing_context_get_cairo_context (ctx); + view->xr = xr_driver_create (cr, &options); string_map_destroy (&options); struct text_item *text_item = text_item_create (TEXT_ITEM_LOG, "X"); - struct xr_rendering *r = xr_rendering_create ( - view->xr, text_item_super (text_item), cr); + struct xr_rendering *r + = xr_rendering_create (view->xr, text_item_super (text_item), cr); xr_rendering_measure (r, NULL, &view->font_height); + xr_rendering_destroy (r); text_item_unref (text_item); - cairo_destroy (cr); + gdk_window_end_draw_frame (win, ctx); + cairo_region_destroy (region); } /* Return the horizontal position to place a widget whose @@ -190,26 +215,124 @@ get_xpos (const struct psppire_output_view *view, gint child_width) return (gtk_widget_get_direction (GTK_WIDGET (view->output)) == GTK_TEXT_DIR_RTL) ? w - child_width - gutter: gutter; } +static struct output_view_item * +find_selected_item (struct psppire_output_view *view) +{ + struct output_view_item *item = NULL; + if (view == NULL) + return NULL; + if (view->items == NULL) + return NULL; + + for (item = view->items; item < &view->items[view->n_items]; item++) + { + GtkWidget *widget = GTK_WIDGET (item->drawing_area); + if GTK_IS_WIDGET (widget) + { + GtkStateFlags state = gtk_widget_get_state_flags (widget); + if (state & GTK_STATE_FLAG_SELECTED) + return item; + } + } + return NULL; +} + + static void -create_drawing_area (struct psppire_output_view *view, - GtkWidget *drawing_area, struct xr_rendering *r, - int tw, int th) +set_copy_action (struct psppire_output_view *view, + gboolean state) +{ + GtkWidget *toplevel = gtk_widget_get_toplevel (GTK_WIDGET (view->output)); + GAction *copy_action = g_action_map_lookup_action (G_ACTION_MAP (toplevel), + "copy"); + g_object_set (copy_action, + "enabled", state, + NULL); +} + +static void +clear_selection (struct psppire_output_view *view) { - /* Enable this to help with debugging. It shows you which widgets are being - put where. */ - if (0) + if (view == NULL) + return; + struct output_view_item *item = find_selected_item (view); + if (item == NULL) + return; + set_copy_action (view, FALSE); + GtkWidget *widget = GTK_WIDGET (item->drawing_area); + if (GTK_IS_WIDGET (widget)) { - GdkRGBA green = {0, 1, 0, 1}; - gtk_widget_override_background_color (GTK_WIDGET (view->output), - GTK_STATE_FLAG_NORMAL, &green); - GdkRGBA red = {1, 0, 0, 1}; - gtk_widget_override_background_color (drawing_area, - GTK_STATE_FLAG_NORMAL, &red); + gtk_widget_unset_state_flags (widget, GTK_STATE_FLAG_SELECTED); + gtk_widget_queue_draw (widget); } +} + +static gboolean +off_item_button_press_event_cb (GtkWidget *widget, + GdkEventButton *event, + struct psppire_output_view *view) +{ + /* buttontime is set by button_press_event_cb + If our event->time is equal to the time from the + button_press_event_cb, then we handle the same event. + In that case we must not clear the selection because + it was just set by button_press_event_cb from the item */ + if (event->time != view->buttontime) + clear_selection (view); + return FALSE; /* Forward the event -> DragNDrop */ +} + +static gboolean +button_press_event_cb (GtkWidget *widget, + GdkEventButton *event, + struct psppire_output_view *view) +{ + view->buttontime = event->time; + clear_selection (view); + set_copy_action (view, TRUE); + gtk_widget_set_state_flags (widget, GTK_STATE_FLAG_SELECTED, FALSE); + gtk_widget_queue_draw (widget); + return FALSE; /* Forward Event -> off_item will trigger */ +} + +static void +drag_data_get_cb (GtkWidget *widget, GdkDragContext *context, + GtkSelectionData *selection_data, + guint target_type, guint time, + struct psppire_output_view *view) +{ + view->selected_item = find_selected_item (view); + clipboard_get_cb (NULL, selection_data, target_type, view); +} + +static void +create_drawing_area (struct psppire_output_view *view, + GtkWidget *drawing_area, struct xr_rendering *r, + int tw, int th, const struct output_item *item) +{ + struct string_map options = STRING_MAP_INITIALIZER (options); + string_map_insert (&options, "transparent", "true"); + string_map_insert (&options, "systemcolors", "true"); + xr_rendering_apply_options (r, &options); g_object_set_data_full (G_OBJECT (drawing_area), "rendering", r, free_rendering); - + g_signal_connect (drawing_area, "button-press-event", + G_CALLBACK (button_press_event_cb), view); + gtk_widget_add_events (drawing_area, GDK_BUTTON_PRESS_MASK); + + { /* Drag and Drop */ + GtkTargetList *tl = build_target_list (item); + g_assert (tl); + gtk_drag_source_set (drawing_area, GDK_BUTTON1_MASK, NULL, 0, GDK_ACTION_COPY); + gtk_drag_source_set_target_list (drawing_area, tl); + gtk_target_list_unref (tl); + g_signal_connect (drawing_area, "drag-data-get", + G_CALLBACK (drag_data_get_cb), view); + } + GtkStyleContext *context = gtk_widget_get_style_context (drawing_area); + gtk_style_context_add_class (context, + GTK_STYLE_CLASS_VIEW); g_signal_connect (drawing_area, "draw", G_CALLBACK (draw_callback), view); @@ -226,14 +349,18 @@ rerender (struct psppire_output_view *view) { struct output_view_item *item; GdkWindow *gdkw = gtk_widget_get_window (GTK_WIDGET (view->output)); - cairo_t *cr; if (!view->n_items || ! gdkw) return; - cr = gdk_cairo_create (gdkw); if (view->xr == NULL) create_xr (view); + + GdkWindow *win = gtk_layout_get_bin_window (view->output); + cairo_region_t *region = gdk_window_get_visible_region (win); + GdkDrawingContext *ctx = gdk_window_begin_draw_frame (win, region); + cairo_t *cr = gdk_drawing_context_get_cairo_context (ctx); + view->y = 0; view->max_width = 0; for (item = view->items; item < &view->items[view->n_items]; item++) @@ -245,6 +372,9 @@ rerender (struct psppire_output_view *view) if (view->y > 0) view->y += view->font_height / 2; + if (is_group_open_item (item->item)) + continue; + r = xr_rendering_create (view->xr, item->item, cr); if (r == NULL) { @@ -259,7 +389,7 @@ rerender (struct psppire_output_view *view) if (!item->drawing_area) { item->drawing_area = gtk_drawing_area_new (); - create_drawing_area (view, item->drawing_area, r, tw, th); + create_drawing_area (view, item->drawing_area, r, tw, th, item->item); } else { @@ -295,30 +425,32 @@ rerender (struct psppire_output_view *view) gtk_layout_set_size (view->output, view->max_width + view->font_height, view->y + view->font_height); - cairo_destroy (cr); + + gdk_window_end_draw_frame (win, ctx); + cairo_region_destroy (region); } + void psppire_output_view_put (struct psppire_output_view *view, const struct output_item *item) { struct output_view_item *view_item; GtkWidget *drawing_area; - struct xr_rendering *r; struct string name; - GtkTreeStore *store; - cairo_t *cr = NULL; - GtkTreePath *path; - GtkTreeIter iter; int tw, th; if (is_group_close_item (item)) { - if (output_get_group_level () == 0) + if (view->cur_group) { - view->in_command = false; - return; + if (!gtk_tree_path_up (view->cur_group)) + { + gtk_tree_path_free (view->cur_group); + view->cur_group = NULL; + } } + return; } else if (is_text_item (item)) { @@ -335,51 +467,71 @@ psppire_output_view_put (struct psppire_output_view *view, view_item->item = output_item_ref (item); view_item->drawing_area = NULL; - if (gtk_widget_get_window (GTK_WIDGET (view->output))) + GdkWindow *win = gtk_widget_get_window (GTK_WIDGET (view->output)); + if (is_group_open_item (item)) + tw = th = 0; + else if (win) { view_item->drawing_area = drawing_area = gtk_drawing_area_new (); - cr = gdk_cairo_create (gtk_widget_get_window (GTK_WIDGET (view->output))); if (view->xr == NULL) create_xr (view); + cairo_region_t *region = gdk_window_get_visible_region (win); + GdkDrawingContext *ctx = gdk_window_begin_draw_frame (win, region); + cairo_t *cr = gdk_drawing_context_get_cairo_context (ctx); + if (view->y > 0) view->y += view->font_height / 2; - r = xr_rendering_create (view->xr, item, cr); + struct xr_rendering *r = xr_rendering_create (view->xr, item, cr); if (r == NULL) - goto done; + { + gdk_window_end_draw_frame (win, ctx); + cairo_region_destroy (region); + return; + } xr_rendering_measure (r, &tw, &th); - - create_drawing_area (view, drawing_area, r, tw, th); + create_drawing_area (view, drawing_area, r, tw, th, item); + gdk_window_end_draw_frame (win, ctx); + cairo_region_destroy (region); } else tw = th = 0; - if (view->overview - && (!is_text_item (item) - || text_item_get_type (to_text_item (item)) != TEXT_ITEM_SYNTAX - || !view->in_command)) + if (view->overview) { - store = GTK_TREE_STORE (gtk_tree_view_get_model (view->overview)); + GtkTreeStore *store = GTK_TREE_STORE ( + gtk_tree_view_get_model (view->overview)); ds_init_empty (&name); - if (is_group_open_item (item) && output_get_group_level () == 1) - { - gtk_tree_store_append (store, &iter, NULL); - view->cur_command = iter; /* XXX shouldn't save a GtkTreeIter */ - view->in_command = true; - } + + /* Create a new node in the tree and puts a reference to it in 'iter'. */ + GtkTreeIter iter; + GtkTreeIter parent; + if (view->cur_group + && gtk_tree_path_get_depth (view->cur_group) > 0 + && gtk_tree_model_get_iter (GTK_TREE_MODEL (store), + &parent, view->cur_group)) + gtk_tree_store_append (store, &iter, &parent); else + gtk_tree_store_append (store, &iter, NULL); + + if (is_group_open_item (item)) { - GtkTreeIter *p = view->in_command ? &view->cur_command : NULL; - gtk_tree_store_append (store, &iter, p); + gtk_tree_path_free (view->cur_group); + view->cur_group = gtk_tree_model_get_path (GTK_TREE_MODEL (store), + &iter); } ds_clear (&name); if (is_text_item (item)) - ds_put_cstr (&name, text_item_get_text (to_text_item (item))); + { + const struct text_item *text_item = to_text_item (item); + ds_put_cstr (&name, text_item_type_to_string ( + text_item_get_type (text_item))); + } else if (is_message_item (item)) { const struct message_item *msg_item = to_message_item (item); @@ -413,7 +565,8 @@ psppire_output_view_put (struct psppire_output_view *view, -1); ds_destroy (&name); - path = gtk_tree_model_get_path (GTK_TREE_MODEL (store), &iter); + GtkTreePath *path = gtk_tree_model_get_path ( + GTK_TREE_MODEL (store), &iter); gtk_tree_view_expand_row (view->overview, path, TRUE); gtk_tree_path_free (path); } @@ -423,9 +576,6 @@ psppire_output_view_put (struct psppire_output_view *view, view->y += th; gtk_layout_set_size (view->output, view->max_width, view->y); - -done: - cairo_destroy (cr); } static void @@ -484,6 +634,8 @@ enum { SELECT_FMT_TEXT, SELECT_FMT_UTF8, SELECT_FMT_HTML, + SELECT_FMT_SVG, + SELECT_FMT_IMG, SELECT_FMT_ODT }; @@ -493,6 +645,34 @@ enum { # define PATH_MAX 1024 #endif +/* Returns a pixbuf from a svg file */ +/* You must unref the pixbuf after usage */ +static GdkPixbuf * +derive_pixbuf_from_svg (const char *filename) +{ + GError *err = NULL; + GdkPixbuf *pixbuf = NULL; +#if HAVE_RSVG + RsvgHandle *handle = rsvg_handle_new_from_file (filename, &err); + if (err == NULL) + { + rsvg_handle_set_dpi (handle, 300.0); + pixbuf = rsvg_handle_get_pixbuf (handle); + g_object_unref (handle); + } +#else + pixbuf = gdk_pixbuf_new_from_file (filename, &err); +#endif + if (err != NULL) + { + msg (ME, _("Could not open file %s during copy operation: %s"), + filename, err->message); + g_error_free (err); + return NULL; + } + return pixbuf; +} + static void clipboard_get_cb (GtkClipboard *clipboard, GtkSelectionData *selection_data, @@ -507,13 +687,7 @@ clipboard_get_cb (GtkClipboard *clipboard, char dirname[PATH_MAX], *filename; struct string_map options; - GtkTreeSelection *sel = gtk_tree_view_get_selection (view->overview); - GtkTreeModel *model = gtk_tree_view_get_model (view->overview); - - GList *rows = gtk_tree_selection_get_selected_rows (sel, &model); - GList *n = rows; - - if ( n == NULL) + if (view->selected_item == NULL) return; if (path_search (dirname, sizeof dirname, NULL, NULL, true) @@ -543,6 +717,11 @@ clipboard_get_cb (GtkClipboard *clipboard, string_map_insert (&options, "css", "false"); break; + case SELECT_FMT_SVG: + case SELECT_FMT_IMG: + /* see below */ + break; + case SELECT_FMT_ODT: string_map_insert (&options, "format", "odt"); break; @@ -553,39 +732,43 @@ clipboard_get_cb (GtkClipboard *clipboard, break; } - driver = output_driver_create (&options); - if (driver == NULL) - goto finish; - - while (n) + if ((info == SELECT_FMT_IMG) || + (info == SELECT_FMT_SVG) ) { - GtkTreePath *path = n->data ; - GtkTreeIter iter; - struct output_item *item ; - - gtk_tree_model_get_iter (model, &iter, path); - gtk_tree_model_get (model, &iter, COL_ADDR, &item, -1); - - driver->class->submit (driver, item); - - n = n->next; + GtkWidget *widget = view->selected_item->drawing_area; + struct xr_rendering *r = g_object_get_data (G_OBJECT (widget), "rendering"); + xr_draw_svg_file (r, filename); } + else + { + driver = output_driver_create (&options); + if (driver == NULL) + goto finish; - if ( driver->class->flush) - driver->class->flush (driver); + driver->class->submit (driver, view->selected_item->item); + if (driver->class->flush) + driver->class->flush (driver); - /* Some drivers (eg: the odt one) don't write anything until they - are closed */ - output_driver_destroy (driver); - driver = NULL; + /* Some drivers (eg: the odt one) don't write anything until they + are closed */ + output_driver_destroy (driver); + driver = NULL; + } - if ( g_file_get_contents (filename, &text, &length, NULL) ) + if (info == SELECT_FMT_IMG) { - gtk_selection_data_set (selection_data, gtk_selection_data_get_target (selection_data), - 8, - (const guchar *) text, length); + GdkPixbuf *pixbuf = derive_pixbuf_from_svg (filename); + if (pixbuf) + { + gtk_selection_data_set_pixbuf (selection_data, pixbuf); + g_object_unref (pixbuf); + } } + else if (g_file_get_contents (filename, &text, &length, NULL)) + gtk_selection_data_set (selection_data, gtk_selection_data_get_target (selection_data), + 8, + (const guchar *) text, length); finish: @@ -597,8 +780,6 @@ clipboard_get_cb (GtkClipboard *clipboard, unlink (filename); free (filename); rmdir (dirname); - - g_list_free (rows); } static void @@ -607,48 +788,61 @@ clipboard_clear_cb (GtkClipboard *clipboard, { } -static const GtkTargetEntry targets[] = { - - { "STRING", 0, SELECT_FMT_TEXT }, - { "TEXT", 0, SELECT_FMT_TEXT }, - { "COMPOUND_TEXT", 0, SELECT_FMT_TEXT }, - { "text/plain", 0, SELECT_FMT_TEXT }, - - { "UTF8_STRING", 0, SELECT_FMT_UTF8 }, - { "text/plain;charset=utf-8", 0, SELECT_FMT_UTF8 }, - - { "text/html", 0, SELECT_FMT_HTML }, +#define CBTARGETS \ +CT ( ctn1, "STRING", 0, SELECT_FMT_TEXT ) \ +CT ( ctn2, "TEXT", 0, SELECT_FMT_TEXT ) \ +CT ( ctn3, "COMPOUND_TEXT", 0, SELECT_FMT_TEXT ) \ +CT ( ctn4, "text/plain", 0, SELECT_FMT_TEXT ) \ +CT ( ctn5, "UTF8_STRING", 0, SELECT_FMT_UTF8 ) \ +CT ( ctn6, "text/plain;charset=utf-8", 0, SELECT_FMT_UTF8 ) \ +CT ( ctn7, "text/html", 0, SELECT_FMT_HTML ) \ +CT ( ctn8, "image/svg+xml", 0, SELECT_FMT_SVG ) + +#define CT(ID, TARGET, FLAGS, INFO) static gchar ID[] = TARGET; +CBTARGETS +#undef CT +gchar ctnlast[] = "application/vnd.oasis.opendocument.text"; - { "application/vnd.oasis.opendocument.text", 0, SELECT_FMT_ODT } +static const GtkTargetEntry targets[] = { +#define CT(ID, TARGET, FLAGS, INFO) { ID, FLAGS, INFO }, + CBTARGETS +#undef CT + { ctnlast, 0, SELECT_FMT_ODT } }; +static GtkTargetList * +build_target_list (const struct output_item *item) +{ + GtkTargetList *tl = gtk_target_list_new (targets, G_N_ELEMENTS (targets)); + g_return_val_if_fail (tl, NULL); + if (is_table_item (item) || + is_chart_item (item)) + gtk_target_list_add_image_targets (tl, SELECT_FMT_IMG, TRUE); + return tl; +} + static void on_copy (struct psppire_output_view *view) { GtkWidget *widget = GTK_WIDGET (view->overview); GtkClipboard *cb = gtk_widget_get_clipboard (widget, GDK_SELECTION_CLIPBOARD); - if (!gtk_clipboard_set_with_data (cb, targets, G_N_ELEMENTS (targets), + struct output_view_item *ov_item = find_selected_item (view); + if (ov_item == NULL) + return; + view->selected_item = ov_item; + GtkTargetList *tl = build_target_list (ov_item->item); + g_return_if_fail (tl); + gint no_of_targets = 0; + GtkTargetEntry *ta = gtk_target_table_new_from_list (tl, &no_of_targets); + g_return_if_fail (ta); + if (!gtk_clipboard_set_with_data (cb, ta, no_of_targets, clipboard_get_cb, clipboard_clear_cb, view)) clipboard_clear_cb (cb, view); -} -static void -on_selection_change (GtkTreeSelection *sel, GAction *copy_action) -{ - /* The Copy action is available only if there is something selected */ - g_object_set (copy_action, - "enabled", gtk_tree_selection_count_selected_rows (sel) > 0, - NULL); -} - -static void -on_select_all (struct psppire_output_view *view) -{ - GtkTreeSelection *sel = gtk_tree_view_get_selection (view->overview); - gtk_tree_view_expand_all (view->overview); - gtk_tree_selection_select_all (sel); + gtk_target_list_unref (tl); + gtk_target_table_free (ta,no_of_targets); } static void @@ -663,9 +857,6 @@ on_size_allocate (GtkWidget *widget, static void on_realize (GtkWidget *overview, GObject *view) { - GtkTreeSelection *sel = gtk_tree_view_get_selection (GTK_TREE_VIEW (overview)); - gtk_tree_selection_set_mode (sel, GTK_SELECTION_MULTIPLE); - GtkWidget *toplevel = gtk_widget_get_toplevel (GTK_WIDGET (overview)); GAction *copy_action = g_action_map_lookup_action (G_ACTION_MAP (toplevel), @@ -675,15 +866,11 @@ on_realize (GtkWidget *overview, GObject *view) "select-all"); g_object_set (copy_action, "enabled", FALSE, NULL); - - g_signal_connect_swapped (select_all_action, "activate", - G_CALLBACK (on_select_all), view); + g_object_set (select_all_action, "enabled", FALSE, NULL); g_signal_connect_swapped (copy_action, "activate", G_CALLBACK (on_copy), view); - g_signal_connect (sel, "changed", G_CALLBACK (on_selection_change), - copy_action); } struct psppire_output_view * @@ -704,11 +891,12 @@ psppire_output_view_new (GtkLayout *output, GtkTreeView *overview) view->y = 0; string_map_init (&view->render_opts); view->overview = overview; - memset (&view->cur_command, 0, sizeof view->cur_command); - view->in_command = false; + view->cur_group = NULL; view->toplevel = gtk_widget_get_toplevel (GTK_WIDGET (output)); + view->buttontime = 0; view->items = NULL; view->n_items = view->allocated_items = 0; + view->selected_item = NULL; view->print_settings = NULL; view->print_xrd = NULL; view->print_item = 0; @@ -721,6 +909,10 @@ psppire_output_view_new (GtkLayout *output, GtkTreeView *overview) g_signal_connect (output, "size-allocate", G_CALLBACK (on_size_allocate), view); + gtk_widget_add_events (GTK_WIDGET (output), GDK_BUTTON_PRESS_MASK); + g_signal_connect (output, "button-press-event", + G_CALLBACK (off_item_button_press_event_cb), view); + gtk_style_context_add_class (gtk_widget_get_style_context (GTK_WIDGET (output)), GTK_STYLE_CLASS_VIEW); @@ -773,6 +965,9 @@ psppire_output_view_destroy (struct psppire_output_view *view) xr_driver_destroy (view->xr); + if (view->cur_group) + gtk_tree_path_free (view->cur_group); + free (view); } @@ -882,7 +1077,7 @@ paginate (GtkPrintOperation *operation, complete. Don't let that screw up printing. */ return TRUE; } - else if ( view->print_item < view->n_items ) + else if (view->print_item < view->n_items) { xr_driver_output_item (view->print_xrd, view->items[view->print_item++].item);