From 03d066d9f7e4f3d076a63e64708633bdf5e1c93c Mon Sep 17 00:00:00 2001 From: Ben Pfaff Date: Sat, 16 Jan 2010 19:48:57 -0800 Subject: [PATCH] psppire: Add File|Export command to output viewer window. This should really pick the default export format based on the extension typed by the user, but it does work. --- src/ui/gui/output-viewer.glade | 14 +-- src/ui/gui/psppire-output-window.c | 149 +++++++++++++++++++++++++++++ src/ui/gui/psppire-output-window.h | 3 + 3 files changed, 154 insertions(+), 12 deletions(-) diff --git a/src/ui/gui/output-viewer.glade b/src/ui/gui/output-viewer.glade index 50d92d46..dfc2663f 100644 --- a/src/ui/gui/output-viewer.glade +++ b/src/ui/gui/output-viewer.glade @@ -25,21 +25,11 @@ True GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - - gtk-save + True GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + _Export True - True - - - - - gtk-save-as - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - True - True diff --git a/src/ui/gui/psppire-output-window.c b/src/ui/gui/psppire-output-window.c index af47d3be..b2e821e2 100644 --- a/src/ui/gui/psppire-output-window.c +++ b/src/ui/gui/psppire-output-window.c @@ -22,8 +22,10 @@ #include #include +#include #include #include +#include #include #include @@ -93,10 +95,29 @@ psppire_output_window_finalize (GObject *object) } +static void +psppire_output_window_dispose (GObject *obj) +{ + PsppireOutputWindow *viewer = PSPPIRE_OUTPUT_WINDOW (obj); + size_t i; + + for (i = 0; i < viewer->n_items; i++) + output_item_unref (viewer->items[i]); + free (viewer->items); + viewer->items = NULL; + viewer->n_items = viewer->allocated_items = 0; + + /* Chain up to the parent class */ + G_OBJECT_CLASS (parent_class)->dispose (obj); +} + static void psppire_output_window_class_init (PsppireOutputWindowClass *class) { + GObjectClass *object_class = G_OBJECT_CLASS (class); + parent_class = g_type_class_peek_parent (class); + object_class->dispose = psppire_output_window_dispose; } @@ -152,6 +173,7 @@ psppire_output_submit (struct output_driver *this, const struct output_item *item) { struct psppire_output_driver *pod = psppire_output_cast (this); + PsppireOutputWindow *viewer; GtkWidget *drawing_area; struct xr_rendering *r; cairo_t *cr; @@ -163,6 +185,7 @@ psppire_output_submit (struct output_driver *this, gtk_widget_show_all (GTK_WIDGET (pod->viewer)); pod->viewer->driver = pod; } + viewer = pod->viewer; cr = gdk_cairo_create (GTK_WIDGET (pod->viewer)->window); if (pod->xr == NULL) @@ -172,6 +195,11 @@ psppire_output_submit (struct output_driver *this, if (r == NULL) goto done; + if (viewer->n_items >= viewer->allocated_items) + viewer->items = x2nrealloc (viewer->items, &viewer->allocated_items, + sizeof *viewer->items); + viewer->items[viewer->n_items++] = output_item_ref (item); + xr_rendering_measure (r, &tw, &th); drawing_area = gtk_drawing_area_new (); @@ -274,6 +302,121 @@ on_row_activate (GtkTreeView *overview, gtk_adjustment_set_value (vadj, y); } +static GtkFileFilter * +add_filter (GtkFileChooser *chooser, const char *name, const char *pattern) +{ + GtkFileFilter *filter = gtk_file_filter_new (); + g_object_ref_sink (G_OBJECT (filter)); + gtk_file_filter_set_name (filter, name); + gtk_file_filter_add_pattern (filter, pattern); + gtk_file_chooser_add_filter (chooser, filter); + return filter; +} + +static void +export_output (PsppireOutputWindow *window, struct string_map *options, + const char *class_name) +{ + struct output_driver *driver; + size_t i; + + driver = output_driver_create (class_name, options); + if (driver == NULL) + return; + + for (i = 0; i < window->n_items; i++) + driver->class->submit (driver, window->items[i]); + output_driver_destroy (driver); +} + +static void +psppire_output_window_export (PsppireOutputWindow *window) +{ + gint response; + + GtkFileFilter *pdf_filter; + GtkFileFilter *html_filter; + GtkFileFilter *odt_filter; + GtkFileFilter *txt_filter; + GtkFileFilter *ps_filter; + GtkFileFilter *csv_filter; + GtkFileChooser *chooser; + GtkWidget *dialog; + + dialog = gtk_file_chooser_dialog_new (_("Export Output"), + GTK_WINDOW (window), + GTK_FILE_CHOOSER_ACTION_SAVE, + GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, + GTK_STOCK_SAVE, GTK_RESPONSE_ACCEPT, + NULL); + chooser = GTK_FILE_CHOOSER (dialog); + + pdf_filter = add_filter (chooser, _("PDF Files (*.pdf)"), "*.pdf"); + html_filter = add_filter (chooser, _("HTML Files (*.html)"), "*.html"); + odt_filter = add_filter (chooser, _("OpenDocument Files (*.odt)"), "*.odt"); + txt_filter = add_filter (chooser, _("Text Files (*.txt)"), "*.txt"); + ps_filter = add_filter (chooser, _("PostScript Files (*.ps)"), "*.ps"); + csv_filter = add_filter (chooser, _("Comma-Separated Value Files (*.csv)"), + "*.csv"); + + gtk_file_chooser_set_do_overwrite_confirmation (chooser, TRUE); + gtk_file_chooser_set_filter (chooser, pdf_filter); + + response = gtk_dialog_run (GTK_DIALOG (dialog)); + + if ( response == GTK_RESPONSE_ACCEPT ) + { + char *filename = gtk_file_chooser_get_filename (chooser); + GtkFileFilter *filter = gtk_file_chooser_get_filter (chooser); + struct string_map options; + + g_return_if_fail (filename); + g_return_if_fail (filter); + + string_map_init (&options); + string_map_insert (&options, "output-file", filename); + if (filter == pdf_filter) + { + string_map_insert (&options, "output-type", "pdf"); + export_output (window, &options, "cairo"); + } + else if (filter == html_filter) + export_output (window, &options, "html"); + else if (filter == odt_filter) + export_output (window, &options, "odf"); + else if (filter == txt_filter) + { + string_map_insert (&options, "headers", "false"); + string_map_insert (&options, "paginate", "false"); + string_map_insert (&options, "squeeze", "true"); + string_map_insert (&options, "emphasis", "none"); + string_map_insert (&options, "chart-type", "none"); + string_map_insert (&options, "top-margin", "0"); + string_map_insert (&options, "bottom-margin", "0"); + export_output (window, &options, "ascii"); + } + else if (filter == ps_filter) + { + string_map_insert (&options, "output-type", "ps"); + export_output (window, &options, "cairo"); + } + else if (filter == csv_filter) + export_output (window, &options, "csv"); + else + g_return_if_reached (); + + free (filename); + } + + g_object_unref (G_OBJECT (pdf_filter)); + g_object_unref (G_OBJECT (html_filter)); + g_object_unref (G_OBJECT (txt_filter)); + g_object_unref (G_OBJECT (ps_filter)); + g_object_unref (G_OBJECT (csv_filter)); + + gtk_widget_destroy (dialog); +} + static void psppire_output_window_init (PsppireOutputWindow *window) { @@ -296,6 +439,9 @@ psppire_output_window_init (PsppireOutputWindow *window) G_TYPE_LONG))); /* COL_Y */ window->last_table_num = -1; + window->items = NULL; + window->n_items = window->allocated_items = 0; + column = gtk_tree_view_column_new (); gtk_tree_view_append_column (GTK_TREE_VIEW (window->overview), column); renderer = gtk_cell_renderer_text_new (); @@ -337,6 +483,9 @@ psppire_output_window_init (PsppireOutputWindow *window) GTK_MENU_SHELL (gtk_ui_manager_get_widget (uim,"/ui/menubar1/windows_menuitem/windows_minimise-all")->parent); } + g_signal_connect_swapped (get_action_assert (xml, "file_export"), "activate", + G_CALLBACK (psppire_output_window_export), window); + g_object_unref (xml); g_signal_connect (window, "delete-event", diff --git a/src/ui/gui/psppire-output-window.h b/src/ui/gui/psppire-output-window.h index 16752b14..bc0da853 100644 --- a/src/ui/gui/psppire-output-window.h +++ b/src/ui/gui/psppire-output-window.h @@ -60,6 +60,9 @@ struct _PsppireOutputWindow GtkTreeView *overview; int last_table_num; GtkTreeIter last_top_level; + + struct output_item **items; + size_t n_items, allocated_items; }; struct _PsppireOutputWindowClass -- 2.30.2