Compilation: don't compile dialogs separately.
[gnumeric.git] / src / dialogs / dialog-stf-export.c
blob99e82d485fde5432e2c2fcb4c238e949273cc90c
1 /*
2 * dialog-stf-export.c : implementation of the STF export dialog
4 * Copyright (C) Almer. S. Tigelaar.
5 * EMail: almer1@dds.nl or almer-t@bigfoot.com
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, see <https://www.gnu.org/licenses/>.
21 #include <gnumeric-config.h>
22 #include <gnumeric.h>
23 #include "dialog-stf-export.h"
25 #include <command-context.h>
26 #include <workbook.h>
27 #include <workbook-control.h>
28 #include <wbc-gtk.h>
29 #include <sheet.h>
30 #include <gui-util.h>
31 #include <gnumeric-conf.h>
32 #include <goffice/goffice.h>
34 #include <gtk/gtk.h>
35 #include <glib/gi18n-lib.h>
36 #include <string.h>
38 typedef enum {
39 PAGE_SHEETS,
40 PAGE_FORMAT
41 } TextExportPage;
42 enum {
43 STF_EXPORT_COL_EXPORTED,
44 STF_EXPORT_COL_SHEET_NAME,
45 STF_EXPORT_COL_SHEET,
46 STF_EXPORT_COL_NON_EMPTY,
47 STF_EXPORT_COL_MAX
50 typedef struct {
51 Workbook *wb;
53 GtkBuilder *gui;
54 WBCGtk *wbcg;
55 GtkWindow *window;
56 GtkWidget *notebook;
57 GtkWidget *back_button, *next_button, *finish_button;
59 struct {
60 GtkListStore *model;
61 GtkTreeView *view;
62 GtkWidget *select_all, *select_none;
63 GtkWidget *up, *down, *top, *bottom;
64 int num, num_selected, non_empty;
65 } sheets;
66 struct {
67 GtkComboBox *termination;
68 GtkComboBox *separator;
69 GtkWidget *custom;
70 GtkComboBox *quote;
71 GtkComboBoxText *quotechar;
72 GtkWidget *charset;
73 GtkWidget *locale;
74 GtkComboBox *transliterate;
75 GtkComboBox *format;
76 } format;
78 GnmStfExport *stfe;
79 gboolean cancelled;
80 } TextExportState;
82 static const char *format_seps[] = {
83 " ", "\t", "!", ":", ",", "-", "|", ";", "/", NULL
86 static void
87 sheet_page_separator_menu_changed (TextExportState *state)
89 unsigned active = gtk_combo_box_get_active (state->format.separator);
90 if (active >= G_N_ELEMENTS (format_seps))
91 active = 0;
93 if (!format_seps[active]) {
94 gtk_widget_grab_focus (state->format.custom);
95 gtk_editable_select_region (GTK_EDITABLE (state->format.custom), 0, -1);
96 } else {
97 gtk_entry_set_text (GTK_ENTRY (state->format.custom),
98 format_seps[active]);
102 static void
103 cb_custom_separator_changed (TextExportState *state)
105 const char *text = gtk_entry_get_text (GTK_ENTRY (state->format.custom));
106 unsigned active = gtk_combo_box_get_active (state->format.separator);
107 unsigned ui;
109 for (ui = 0; format_seps[ui]; ui++)
110 if (strcmp (text, format_seps[ui]) == 0)
111 break;
113 if (ui != active)
114 gtk_combo_box_set_active (state->format.separator, ui);
117 static void
118 stf_export_dialog_format_page_init (TextExportState *state)
120 GtkWidget *grid;
121 GObject *sobj = G_OBJECT (state->stfe);
124 char *eol;
125 int i;
127 state->format.termination = GTK_COMBO_BOX (go_gtk_builder_get_widget (state->gui, "format_termination"));
128 g_object_get (sobj, "eol", &eol, NULL);
129 if (strcmp (eol, "\r") == 0)
130 i = 1;
131 else if (strcmp (eol, "\r\n") == 0)
132 i = 2;
133 else
134 i = 0;
135 gtk_combo_box_set_active (state->format.termination, i);
136 g_free (eol);
140 char *s;
141 unsigned ui;
142 gint pos = 0;
144 state->format.separator = GTK_COMBO_BOX (go_gtk_builder_get_widget (state->gui, "format_separator"));
145 state->format.custom = go_gtk_builder_get_widget (state->gui, "format_custom");
146 g_object_get (sobj, "separator", &s, NULL);
147 for (ui = 0; ui < G_N_ELEMENTS (format_seps) - 1; ui++)
148 if (strcmp (s, format_seps[ui]) == 0)
149 break;
150 gtk_combo_box_set_active (state->format.separator, ui);
151 if (!format_seps[ui]) {
152 gtk_editable_insert_text (GTK_EDITABLE (state->format.custom),
153 s, -1,
154 &pos);
156 g_free (s);
160 GsfOutputCsvQuotingMode quotingmode;
161 int i;
163 state->format.quote = GTK_COMBO_BOX (go_gtk_builder_get_widget (state->gui, "format_quote"));
164 g_object_get (sobj, "quoting-mode", &quotingmode, NULL);
165 switch (quotingmode) {
166 default:
167 case GSF_OUTPUT_CSV_QUOTING_MODE_AUTO: i = 0; break;
168 case GSF_OUTPUT_CSV_QUOTING_MODE_ALWAYS: i = 1; break;
169 case GSF_OUTPUT_CSV_QUOTING_MODE_NEVER: i = 2; break;
171 gtk_combo_box_set_active (state->format.quote, i);
175 char *s;
176 gint pos;
178 state->format.quotechar = GTK_COMBO_BOX_TEXT (go_gtk_builder_get_widget (state->gui, "format_quotechar"));
179 g_object_get (sobj, "quote", &s, NULL);
181 gtk_editable_insert_text (GTK_EDITABLE (gtk_bin_get_child (GTK_BIN (state->format.quotechar))),
182 s, -1, &pos);
183 g_free (s);
187 GnmStfFormatMode format;
188 int i;
190 state->format.format = GTK_COMBO_BOX (go_gtk_builder_get_widget (state->gui, "format"));
191 g_object_get (sobj, "format", &format, NULL);
192 switch (format) {
193 default:
194 case GNM_STF_FORMAT_AUTO: i = 0; break;
195 case GNM_STF_FORMAT_RAW: i = 1; break;
196 case GNM_STF_FORMAT_PRESERVE: i = 2; break;
198 gtk_combo_box_set_active (state->format.format, i);
202 char *charset;
203 state->format.charset = go_charmap_sel_new (GO_CHARMAP_SEL_FROM_UTF8);
204 g_object_get (sobj, "charset", &charset, NULL);
205 if (charset) {
206 go_charmap_sel_set_encoding (GO_CHARMAP_SEL (state->format.charset),
207 charset);
208 g_free (charset);
213 char *locale;
214 state->format.locale = go_locale_sel_new ();
215 g_object_get (sobj, "locale", &locale, NULL);
216 if (locale) {
217 go_locale_sel_set_locale (GO_LOCALE_SEL (state->format.locale),
218 locale);
219 g_free (locale);
224 GnmStfTransliterateMode mode;
225 int i;
227 state->format.transliterate = GTK_COMBO_BOX (go_gtk_builder_get_widget (state->gui, "format_transliterate"));
228 g_object_get (sobj, "transliterate-mode", &mode, NULL);
229 if (!gnm_stf_export_can_transliterate ()) {
230 if (mode == GNM_STF_TRANSLITERATE_MODE_TRANS)
231 mode = GNM_STF_TRANSLITERATE_MODE_ESCAPE;
232 /* It might be better to render insensitive
233 * only one option than the whole list as in
234 * the following line but it is not possible
235 * with gtk-2.4. May be it should be changed
236 * when 2.6 is available (inactivate only the
237 * transliterate item)
239 gtk_widget_set_sensitive (GTK_WIDGET (state->format.transliterate), FALSE);
241 switch (mode) {
242 default:
243 case GNM_STF_TRANSLITERATE_MODE_TRANS: i = 0; break;
244 case GNM_STF_TRANSLITERATE_MODE_ESCAPE: i = 1; break;
246 gtk_combo_box_set_active (state->format.transliterate, i);
249 gnm_editable_enters (state->window, state->format.custom);
250 gnm_editable_enters (state->window,
251 gtk_bin_get_child (GTK_BIN (state->format.quotechar)));
253 grid = go_gtk_builder_get_widget (state->gui, "format-grid");
254 gtk_grid_attach (GTK_GRID (grid), state->format.charset,
255 1, 6, 1, 1);
256 gtk_grid_attach (GTK_GRID (grid), state->format.locale,
257 1, 7, 1, 1);
258 gtk_widget_show_all (grid);
260 g_signal_connect_swapped (state->format.separator,
261 "changed",
262 G_CALLBACK (sheet_page_separator_menu_changed), state);
263 g_signal_connect_swapped (state->format.custom,
264 "changed",
265 G_CALLBACK (cb_custom_separator_changed), state);
267 sheet_page_separator_menu_changed (state);
270 static gboolean
271 cb_collect_exported_sheets (GtkTreeModel *model, G_GNUC_UNUSED GtkTreePath *path, GtkTreeIter *iter,
272 TextExportState *state)
274 gboolean exported;
275 Sheet *sheet;
277 gtk_tree_model_get (model, iter,
278 STF_EXPORT_COL_EXPORTED, &exported,
279 STF_EXPORT_COL_SHEET, &sheet,
280 -1);
281 if (exported)
282 gnm_stf_export_options_sheet_list_add (state->stfe, sheet);
283 g_object_unref (sheet);
284 return FALSE;
286 static void
287 stf_export_dialog_finish (TextExportState *state)
289 GsfOutputCsvQuotingMode quotingmode;
290 GnmStfTransliterateMode transliteratemode;
291 GnmStfFormatMode format;
292 const char *eol;
293 GString *triggers = g_string_new (NULL);
294 char *separator, *quote;
295 const char *charset;
296 char *locale;
298 /* What options */
299 switch (gtk_combo_box_get_active (state->format.termination)) {
300 default:
301 case 0: eol = "\n"; break;
302 case 1: eol = "\r"; break;
303 case 2: eol = "\r\n"; break;
306 switch (gtk_combo_box_get_active (state->format.quote)) {
307 default:
308 case 0: quotingmode = GSF_OUTPUT_CSV_QUOTING_MODE_AUTO; break;
309 case 1: quotingmode = GSF_OUTPUT_CSV_QUOTING_MODE_ALWAYS; break;
310 case 2: quotingmode = GSF_OUTPUT_CSV_QUOTING_MODE_NEVER; break;
313 switch (gtk_combo_box_get_active (state->format.transliterate)) {
314 case 0 : transliteratemode = GNM_STF_TRANSLITERATE_MODE_TRANS; break;
315 default:
316 case 1 : transliteratemode = GNM_STF_TRANSLITERATE_MODE_ESCAPE; break;
319 switch (gtk_combo_box_get_active (state->format.format)) {
320 default:
321 case 0: format = GNM_STF_FORMAT_AUTO; break;
322 case 1: format = GNM_STF_FORMAT_RAW; break;
323 case 2: format = GNM_STF_FORMAT_PRESERVE; break;
326 quote = gtk_editable_get_chars (GTK_EDITABLE (gtk_bin_get_child (GTK_BIN (state->format.quotechar))), 0, -1);
329 unsigned u = gtk_combo_box_get_active (state->format.separator);
330 if (u >= G_N_ELEMENTS (format_seps))
331 u = 4;
332 separator = format_seps[u]
333 ? g_strdup (format_seps[u])
334 : gtk_editable_get_chars (GTK_EDITABLE (state->format.custom), 0, -1);
337 charset = go_charmap_sel_get_encoding (GO_CHARMAP_SEL (state->format.charset));
338 locale = go_locale_sel_get_locale (GO_LOCALE_SEL (state->format.locale));
340 if (quotingmode == GSF_OUTPUT_CSV_QUOTING_MODE_AUTO) {
341 g_string_append (triggers, " \t");
342 g_string_append (triggers, eol);
343 g_string_append (triggers, quote);
344 g_string_append (triggers, separator);
347 g_object_set (state->stfe,
348 "eol", eol,
349 "quote", quote,
350 "quoting-mode", quotingmode,
351 "quoting-triggers", triggers->str,
352 "separator", separator,
353 "transliterate-mode", transliteratemode,
354 "format", format,
355 "charset", charset,
356 "locale", locale,
357 NULL);
359 if (gtk_toggle_button_get_active
360 (GTK_TOGGLE_BUTTON (go_gtk_builder_get_widget (state->gui,
361 "save-as-default-check")))) {
362 gnm_conf_set_stf_export_separator (separator);
363 gnm_conf_set_stf_export_stringindicator (quote);
364 gnm_conf_set_stf_export_terminator (eol);
365 gnm_conf_set_stf_export_quoting (quotingmode);
366 gnm_conf_set_stf_export_format (format);
367 gnm_conf_set_stf_export_transliteration (transliteratemode == GNM_STF_TRANSLITERATE_MODE_TRANS);
368 gnm_conf_set_stf_export_locale (locale);
369 gnm_conf_set_stf_export_encoding (charset);
372 /* Which sheets? */
373 gnm_stf_export_options_sheet_list_clear (state->stfe);
374 gtk_tree_model_foreach (GTK_TREE_MODEL (state->sheets.model),
375 (GtkTreeModelForeachFunc) cb_collect_exported_sheets, state);
377 g_free (separator);
378 g_free (quote);
379 g_string_free (triggers, TRUE);
380 g_free (locale);
382 state->cancelled = FALSE;
383 gtk_dialog_response (GTK_DIALOG (state->window), GTK_RESPONSE_OK);
386 static void
387 set_sheet_selection_count (TextExportState *state, int n)
389 state->sheets.num_selected = n;
390 gtk_widget_set_sensitive (state->sheets.select_all,
391 state->sheets.non_empty > n);
392 gtk_widget_set_sensitive (state->sheets.select_none, n != 0);
393 gtk_widget_set_sensitive (state->next_button, n != 0);
396 static gboolean
397 cb_set_sheet (GtkTreeModel *model, G_GNUC_UNUSED GtkTreePath *path, GtkTreeIter *iter,
398 gpointer data)
400 gboolean value;
402 gtk_tree_model_get (GTK_TREE_MODEL (model), iter,
403 STF_EXPORT_COL_NON_EMPTY, &value,
404 -1);
405 if (value)
406 gtk_list_store_set (GTK_LIST_STORE (model), iter,
407 STF_EXPORT_COL_EXPORTED,
408 GPOINTER_TO_INT (data),
409 -1);
410 return FALSE;
413 static void
414 cb_sheet_select_all (TextExportState *state)
416 gtk_tree_model_foreach (GTK_TREE_MODEL (state->sheets.model),
417 cb_set_sheet, GINT_TO_POINTER (TRUE));
418 set_sheet_selection_count (state, state->sheets.non_empty);
420 static void
421 cb_sheet_select_none (TextExportState *state)
423 gtk_tree_model_foreach (GTK_TREE_MODEL (state->sheets.model),
424 cb_set_sheet, GINT_TO_POINTER (FALSE));
425 set_sheet_selection_count (state, 0);
429 * Refreshes the buttons on a row (un)selection and selects the chosen sheet
430 * for this view.
432 static void
433 cb_selection_changed (GtkTreeSelection *new_selection,
434 TextExportState *state)
436 GtkTreeIter iter, it;
437 gboolean first_selected = TRUE, last_selected = TRUE;
439 GtkTreeSelection *selection =
440 (new_selection == NULL)
441 ? gtk_tree_view_get_selection (state->sheets.view)
442 : new_selection;
444 if (selection != NULL
445 && gtk_tree_selection_count_selected_rows (selection) > 0
446 && gtk_tree_model_get_iter_first
447 (GTK_TREE_MODEL (state->sheets.model),
448 &iter)) {
449 first_selected = gtk_tree_selection_iter_is_selected
450 (selection, &iter);
451 it = iter;
452 while (gtk_tree_model_iter_next
453 (GTK_TREE_MODEL (state->sheets.model),
454 &it))
455 iter = it;
456 last_selected = gtk_tree_selection_iter_is_selected
457 (selection, &iter);
460 gtk_widget_set_sensitive (state->sheets.top, !first_selected);
461 gtk_widget_set_sensitive (state->sheets.up, !first_selected);
462 gtk_widget_set_sensitive (state->sheets.bottom, !last_selected);
463 gtk_widget_set_sensitive (state->sheets.down, !last_selected);
465 return;
468 static void
469 move_element (TextExportState *state, gnm_iter_search_t iter_search)
471 GtkTreeSelection *selection = gtk_tree_view_get_selection (state->sheets.view);
472 GtkTreeModel *model;
473 GtkTreeIter a, b;
475 g_return_if_fail (selection != NULL);
477 if (!gtk_tree_selection_get_selected (selection, &model, &a))
478 return;
480 b = a;
481 if (!iter_search (model, &b))
482 return;
484 gtk_list_store_swap (state->sheets.model, &a, &b);
485 cb_selection_changed (NULL, state);
488 static void
489 cb_sheet_up (TextExportState *state)
491 move_element (state, gtk_tree_model_iter_previous);
494 static void
495 cb_sheet_down (TextExportState *state)
497 move_element (state, gtk_tree_model_iter_next);
500 static void
501 cb_sheet_top (TextExportState *state)
503 GtkTreeIter this_iter;
504 GtkTreeSelection *selection = gtk_tree_view_get_selection (state->sheets.view);
506 g_return_if_fail (selection != NULL);
508 if (!gtk_tree_selection_get_selected (selection, NULL, &this_iter))
509 return;
511 gtk_list_store_move_after (state->sheets.model, &this_iter, NULL);
512 cb_selection_changed (NULL, state);
515 static void
516 cb_sheet_bottom (TextExportState *state)
518 GtkTreeIter this_iter;
519 GtkTreeSelection *selection = gtk_tree_view_get_selection (state->sheets.view);
521 g_return_if_fail (selection != NULL);
523 if (!gtk_tree_selection_get_selected (selection, NULL, &this_iter))
524 return;
525 gtk_list_store_move_before (state->sheets.model, &this_iter, NULL);
526 cb_selection_changed (NULL, state);
529 static void
530 cb_sheet_export_toggled (G_GNUC_UNUSED GtkCellRendererToggle *cell,
531 const gchar *path_string,
532 TextExportState *state)
534 GtkTreePath *path = gtk_tree_path_new_from_string (path_string);
535 GtkTreeIter iter;
536 gboolean value;
538 if (gtk_tree_model_get_iter (GTK_TREE_MODEL (state->sheets.model),
539 &iter, path)) {
540 gtk_tree_model_get
541 (GTK_TREE_MODEL (state->sheets.model), &iter,
542 STF_EXPORT_COL_EXPORTED, &value,
543 -1);
544 gtk_list_store_set
545 (state->sheets.model, &iter,
546 STF_EXPORT_COL_EXPORTED, !value,
547 -1);
548 set_sheet_selection_count
549 (state,
550 state->sheets.num_selected + (value ? -1 : 1));
551 } else {
552 g_warning ("Did not get a valid iterator");
554 gtk_tree_path_free (path);
557 static void
558 stf_export_dialog_sheet_page_init (TextExportState *state)
560 int i;
561 GtkTreeSelection *selection;
562 GtkTreeIter iter;
563 GtkCellRenderer *renderer;
564 GSList *sheet_list;
566 state->sheets.select_all = go_gtk_builder_get_widget (state->gui, "sheet_select_all");
567 state->sheets.select_none = go_gtk_builder_get_widget (state->gui, "sheet_select_none");
568 state->sheets.up = go_gtk_builder_get_widget (state->gui, "sheet_up");
569 state->sheets.down = go_gtk_builder_get_widget (state->gui, "sheet_down");
570 state->sheets.top = go_gtk_builder_get_widget (state->gui, "sheet_top");
571 state->sheets.bottom = go_gtk_builder_get_widget (state->gui, "sheet_bottom");
572 gtk_button_set_alignment (GTK_BUTTON (state->sheets.up), 0., .5);
573 gtk_button_set_alignment (GTK_BUTTON (state->sheets.down), 0., .5);
574 gtk_button_set_alignment (GTK_BUTTON (state->sheets.top), 0., .5);
575 gtk_button_set_alignment (GTK_BUTTON (state->sheets.bottom), 0., .5);
577 state->sheets.model = gtk_list_store_new (STF_EXPORT_COL_MAX,
578 G_TYPE_BOOLEAN, G_TYPE_STRING, G_TYPE_OBJECT, G_TYPE_BOOLEAN);
579 state->sheets.view = GTK_TREE_VIEW (
580 go_gtk_builder_get_widget (state->gui, "sheet_list"));
581 gtk_tree_view_set_model (state->sheets.view, GTK_TREE_MODEL (state->sheets.model));
583 renderer = gtk_cell_renderer_toggle_new ();
584 g_signal_connect (G_OBJECT (renderer),
585 "toggled",
586 G_CALLBACK (cb_sheet_export_toggled), state);
587 gtk_tree_view_append_column (GTK_TREE_VIEW (state->sheets.view),
588 gtk_tree_view_column_new_with_attributes
589 (_("Export"),
590 renderer,
591 "active", STF_EXPORT_COL_EXPORTED,
592 "activatable", STF_EXPORT_COL_NON_EMPTY,
593 NULL));
594 gtk_tree_view_append_column (GTK_TREE_VIEW (state->sheets.view),
595 gtk_tree_view_column_new_with_attributes (_("Sheet"),
596 gtk_cell_renderer_text_new (),
597 "text", STF_EXPORT_COL_SHEET_NAME, NULL));
599 selection = gtk_tree_view_get_selection (state->sheets.view);
600 gtk_tree_selection_set_mode (selection, GTK_SELECTION_BROWSE);
602 state->sheets.num = workbook_sheet_count (state->wb);
603 state->sheets.num_selected = 0;
604 state->sheets.non_empty = 0;
606 sheet_list = gnm_stf_export_options_sheet_list_get (state->stfe);
608 for (i = 0 ; i < state->sheets.num ; i++) {
609 Sheet *sheet = workbook_sheet_by_index (state->wb, i);
610 GnmRange total_range = sheet_get_extent (sheet, TRUE, TRUE);
611 gboolean empty = sheet_is_region_empty (sheet, &total_range);
612 gboolean export =
613 !sheet_list || g_slist_find (sheet_list, sheet);
614 /* The above adds up to n^2 in number of sheets. Tough. */
616 gtk_list_store_append (state->sheets.model, &iter);
617 gtk_list_store_set (state->sheets.model, &iter,
618 STF_EXPORT_COL_EXPORTED, export && !empty,
619 STF_EXPORT_COL_SHEET_NAME, sheet->name_quoted,
620 STF_EXPORT_COL_SHEET, sheet,
621 STF_EXPORT_COL_NON_EMPTY, !empty,
622 -1);
623 if (!empty)
624 state->sheets.non_empty++;
626 if (export)
627 state->sheets.num_selected++;
629 set_sheet_selection_count (state, state->sheets.num_selected);
631 g_signal_connect_swapped (G_OBJECT (state->sheets.select_all),
632 "clicked",
633 G_CALLBACK (cb_sheet_select_all), state);
634 g_signal_connect_swapped (G_OBJECT (state->sheets.select_none),
635 "clicked",
636 G_CALLBACK (cb_sheet_select_none), state);
637 g_signal_connect_swapped (G_OBJECT (state->sheets.up),
638 "clicked",
639 G_CALLBACK (cb_sheet_up), state);
640 g_signal_connect_swapped (G_OBJECT (state->sheets.down),
641 "clicked",
642 G_CALLBACK (cb_sheet_down), state);
643 g_signal_connect_swapped (G_OBJECT (state->sheets.top),
644 "clicked",
645 G_CALLBACK (cb_sheet_top), state);
646 g_signal_connect_swapped (G_OBJECT (state->sheets.bottom),
647 "clicked",
648 G_CALLBACK (cb_sheet_bottom), state);
650 cb_selection_changed (NULL, state);
651 g_signal_connect (selection,
652 "changed",
653 G_CALLBACK (cb_selection_changed), state);
655 gtk_tree_view_set_reorderable (state->sheets.view, TRUE);
658 static void
659 stf_export_dialog_switch_page (TextExportState *state, TextExportPage new_page)
661 gtk_notebook_set_current_page (GTK_NOTEBOOK (state->notebook),
662 new_page);
663 if (new_page == PAGE_FORMAT) {
664 gtk_widget_hide (state->next_button);
665 gtk_widget_show (state->finish_button);
666 gtk_widget_grab_default (state->finish_button);
667 gtk_widget_grab_focus (state->finish_button);
668 } else {
669 gtk_widget_show (state->next_button);
670 gtk_widget_hide (state->finish_button);
671 gtk_widget_grab_default (state->next_button);
672 gtk_widget_grab_focus (state->next_button);
675 if (state->sheets.non_empty > 1) {
676 gtk_widget_show (state->back_button);
677 gtk_widget_set_sensitive (state->back_button, new_page > 0);
678 } else
679 gtk_widget_hide (state->back_button);
682 static void
683 cb_back_page (TextExportState *state)
685 int p = gtk_notebook_get_current_page (GTK_NOTEBOOK (state->notebook));
686 stf_export_dialog_switch_page (state, p - 1);
689 static void
690 cb_next_page (TextExportState *state)
692 int p = gtk_notebook_get_current_page (GTK_NOTEBOOK (state->notebook));
693 stf_export_dialog_switch_page (state, p + 1);
697 * stf_export_dialog:
698 * @wbcg: #WBCGtk (can be NULL)
699 * @stfe: An exporter to set up (and take defaults from)
700 * @wb: The #Workbook to export
702 * This will start the export assistant.
703 * returns : TRUE if cancelled.
705 gboolean
706 stf_export_dialog (WBCGtk *wbcg, GnmStfExport *stfe, Workbook *wb)
708 TextExportState state;
710 g_return_val_if_fail (GNM_IS_WORKBOOK (wb), TRUE);
711 g_return_val_if_fail (GNM_IS_STF_EXPORT (stfe), TRUE);
713 state.gui = gnm_gtk_builder_load ("res:ui/dialog-stf-export.ui", NULL, GO_CMD_CONTEXT (wbcg));
714 if (state.gui == NULL)
715 return TRUE;
717 state.wb = wb;
718 state.wbcg = wbcg;
719 state.window = GTK_WINDOW (go_gtk_builder_get_widget (state.gui, "text-export"));
720 state.notebook = go_gtk_builder_get_widget (state.gui, "text-export-notebook");
721 state.back_button = go_gtk_builder_get_widget (state.gui, "button-back");
722 state.next_button = go_gtk_builder_get_widget (state.gui, "button-next");
723 state.finish_button = go_gtk_builder_get_widget (state.gui, "button-finish");
724 state.cancelled = TRUE;
725 state.stfe = stfe;
726 stf_export_dialog_sheet_page_init (&state);
727 stf_export_dialog_format_page_init (&state);
728 if (state.sheets.non_empty == 0) {
729 gtk_widget_destroy (GTK_WIDGET (state.window));
730 go_gtk_notice_dialog (wbcg_toplevel (wbcg), GTK_MESSAGE_ERROR,
731 _("This workbook does not contain any "
732 "exportable content."));
733 } else {
734 stf_export_dialog_switch_page
735 (&state,
736 (1 >= state.sheets.non_empty) ?
737 PAGE_FORMAT : PAGE_SHEETS);
738 g_signal_connect_swapped (G_OBJECT (state.back_button),
739 "clicked",
740 G_CALLBACK (cb_back_page), &state);
741 g_signal_connect_swapped (G_OBJECT (state.next_button),
742 "clicked",
743 G_CALLBACK (cb_next_page), &state);
744 g_signal_connect_swapped (G_OBJECT (state.finish_button),
745 "clicked",
746 G_CALLBACK (stf_export_dialog_finish),
747 &state);
749 go_gtk_dialog_run (GTK_DIALOG (state.window), wbcg_toplevel (wbcg));
751 g_object_unref (state.gui);
752 g_object_unref (state.sheets.model);
754 return state.cancelled;