Introspecion and doc fixes.
[gnumeric.git] / src / dialogs / dialog-stf-export.c
blob668f8639f84e0813b82e26333b6525619d9aa467
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 <dialogs/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 <glib/gi18n-lib.h>
35 #include <string.h>
37 typedef enum {
38 PAGE_SHEETS,
39 PAGE_FORMAT
40 } TextExportPage;
41 enum {
42 STF_EXPORT_COL_EXPORTED,
43 STF_EXPORT_COL_SHEET_NAME,
44 STF_EXPORT_COL_SHEET,
45 STF_EXPORT_COL_NON_EMPTY,
46 STF_EXPORT_COL_MAX
49 typedef struct {
50 Workbook *wb;
52 GtkBuilder *gui;
53 WBCGtk *wbcg;
54 GtkWindow *window;
55 GtkWidget *notebook;
56 GtkWidget *back_button, *next_button, *finish_button;
58 struct {
59 GtkListStore *model;
60 GtkTreeView *view;
61 GtkWidget *select_all, *select_none;
62 GtkWidget *up, *down, *top, *bottom;
63 int num, num_selected, non_empty;
64 } sheets;
65 struct {
66 GtkComboBox *termination;
67 GtkComboBox *separator;
68 GtkWidget *custom;
69 GtkComboBox *quote;
70 GtkComboBoxText *quotechar;
71 GtkWidget *charset;
72 GtkWidget *locale;
73 GtkComboBox *transliterate;
74 GtkComboBox *format;
75 } format;
77 GnmStfExport *stfe;
78 gboolean cancelled;
79 } TextExportState;
81 static const char *format_seps[] = {
82 " ", "\t", "!", ":", ",", "-", "|", ";", "/", NULL
85 static void
86 sheet_page_separator_menu_changed (TextExportState *state)
88 unsigned active = gtk_combo_box_get_active (state->format.separator);
89 if (active >= G_N_ELEMENTS (format_seps))
90 active = 0;
92 if (!format_seps[active]) {
93 gtk_widget_grab_focus (state->format.custom);
94 gtk_editable_select_region (GTK_EDITABLE (state->format.custom), 0, -1);
95 } else {
96 gtk_entry_set_text (GTK_ENTRY (state->format.custom),
97 format_seps[active]);
101 static void
102 cb_custom_separator_changed (TextExportState *state)
104 const char *text = gtk_entry_get_text (GTK_ENTRY (state->format.custom));
105 unsigned active = gtk_combo_box_get_active (state->format.separator);
106 unsigned ui;
108 for (ui = 0; format_seps[ui]; ui++)
109 if (strcmp (text, format_seps[ui]) == 0)
110 break;
112 if (ui != active)
113 gtk_combo_box_set_active (state->format.separator, ui);
116 static void
117 stf_export_dialog_format_page_init (TextExportState *state)
119 GtkWidget *grid;
120 GObject *sobj = G_OBJECT (state->stfe);
123 char *eol;
124 int i;
126 state->format.termination = GTK_COMBO_BOX (go_gtk_builder_get_widget (state->gui, "format_termination"));
127 g_object_get (sobj, "eol", &eol, NULL);
128 if (strcmp (eol, "\r") == 0)
129 i = 1;
130 else if (strcmp (eol, "\r\n") == 0)
131 i = 2;
132 else
133 i = 0;
134 gtk_combo_box_set_active (state->format.termination, i);
135 g_free (eol);
139 char *s;
140 unsigned ui;
141 gint pos = 0;
143 state->format.separator = GTK_COMBO_BOX (go_gtk_builder_get_widget (state->gui, "format_separator"));
144 state->format.custom = go_gtk_builder_get_widget (state->gui, "format_custom");
145 g_object_get (sobj, "separator", &s, NULL);
146 for (ui = 0; ui < G_N_ELEMENTS (format_seps) - 1; ui++)
147 if (strcmp (s, format_seps[ui]) == 0)
148 break;
149 gtk_combo_box_set_active (state->format.separator, ui);
150 if (!format_seps[ui]) {
151 gtk_editable_insert_text (GTK_EDITABLE (state->format.custom),
152 s, -1,
153 &pos);
155 g_free (s);
159 GsfOutputCsvQuotingMode quotingmode;
160 int i;
162 state->format.quote = GTK_COMBO_BOX (go_gtk_builder_get_widget (state->gui, "format_quote"));
163 g_object_get (sobj, "quoting-mode", &quotingmode, NULL);
164 switch (quotingmode) {
165 default:
166 case GSF_OUTPUT_CSV_QUOTING_MODE_AUTO: i = 0; break;
167 case GSF_OUTPUT_CSV_QUOTING_MODE_ALWAYS: i = 1; break;
168 case GSF_OUTPUT_CSV_QUOTING_MODE_NEVER: i = 2; break;
170 gtk_combo_box_set_active (state->format.quote, i);
174 char *s;
175 gint pos;
177 state->format.quotechar = GTK_COMBO_BOX_TEXT (go_gtk_builder_get_widget (state->gui, "format_quotechar"));
178 g_object_get (sobj, "quote", &s, NULL);
180 gtk_editable_insert_text (GTK_EDITABLE (gtk_bin_get_child (GTK_BIN (state->format.quotechar))),
181 s, -1, &pos);
182 g_free (s);
186 GnmStfFormatMode format;
187 int i;
189 state->format.format = GTK_COMBO_BOX (go_gtk_builder_get_widget (state->gui, "format"));
190 g_object_get (sobj, "format", &format, NULL);
191 switch (format) {
192 default:
193 case GNM_STF_FORMAT_AUTO: i = 0; break;
194 case GNM_STF_FORMAT_RAW: i = 1; break;
195 case GNM_STF_FORMAT_PRESERVE: i = 2; break;
197 gtk_combo_box_set_active (state->format.format, i);
201 char *charset;
202 state->format.charset = go_charmap_sel_new (GO_CHARMAP_SEL_FROM_UTF8);
203 g_object_get (sobj, "charset", &charset, NULL);
204 if (charset) {
205 go_charmap_sel_set_encoding (GO_CHARMAP_SEL (state->format.charset),
206 charset);
207 g_free (charset);
212 char *locale;
213 state->format.locale = go_locale_sel_new ();
214 g_object_get (sobj, "locale", &locale, NULL);
215 if (locale) {
216 go_locale_sel_set_locale (GO_LOCALE_SEL (state->format.locale),
217 locale);
218 g_free (locale);
223 GnmStfTransliterateMode mode;
224 int i;
226 state->format.transliterate = GTK_COMBO_BOX (go_gtk_builder_get_widget (state->gui, "format_transliterate"));
227 g_object_get (sobj, "transliterate-mode", &mode, NULL);
228 if (!gnm_stf_export_can_transliterate ()) {
229 if (mode == GNM_STF_TRANSLITERATE_MODE_TRANS)
230 mode = GNM_STF_TRANSLITERATE_MODE_ESCAPE;
231 /* It might be better to render insensitive
232 * only one option than the whole list as in
233 * the following line but it is not possible
234 * with gtk-2.4. May be it should be changed
235 * when 2.6 is available (inactivate only the
236 * transliterate item)
238 gtk_widget_set_sensitive (GTK_WIDGET (state->format.transliterate), FALSE);
240 switch (mode) {
241 default:
242 case GNM_STF_TRANSLITERATE_MODE_TRANS: i = 0; break;
243 case GNM_STF_TRANSLITERATE_MODE_ESCAPE: i = 1; break;
245 gtk_combo_box_set_active (state->format.transliterate, i);
248 gnm_editable_enters (state->window, state->format.custom);
249 gnm_editable_enters (state->window,
250 gtk_bin_get_child (GTK_BIN (state->format.quotechar)));
252 grid = go_gtk_builder_get_widget (state->gui, "format-grid");
253 gtk_grid_attach (GTK_GRID (grid), state->format.charset,
254 1, 6, 1, 1);
255 gtk_grid_attach (GTK_GRID (grid), state->format.locale,
256 1, 7, 1, 1);
257 gtk_widget_show_all (grid);
259 g_signal_connect_swapped (state->format.separator,
260 "changed",
261 G_CALLBACK (sheet_page_separator_menu_changed), state);
262 g_signal_connect_swapped (state->format.custom,
263 "changed",
264 G_CALLBACK (cb_custom_separator_changed), state);
266 sheet_page_separator_menu_changed (state);
269 static gboolean
270 cb_collect_exported_sheets (GtkTreeModel *model, G_GNUC_UNUSED GtkTreePath *path, GtkTreeIter *iter,
271 TextExportState *state)
273 gboolean exported;
274 Sheet *sheet;
276 gtk_tree_model_get (model, iter,
277 STF_EXPORT_COL_EXPORTED, &exported,
278 STF_EXPORT_COL_SHEET, &sheet,
279 -1);
280 if (exported)
281 gnm_stf_export_options_sheet_list_add (state->stfe, sheet);
282 g_object_unref (sheet);
283 return FALSE;
285 static void
286 stf_export_dialog_finish (TextExportState *state)
288 GsfOutputCsvQuotingMode quotingmode;
289 GnmStfTransliterateMode transliteratemode;
290 GnmStfFormatMode format;
291 const char *eol;
292 GString *triggers = g_string_new (NULL);
293 char *separator, *quote;
294 const char *charset;
295 char *locale;
297 /* What options */
298 switch (gtk_combo_box_get_active (state->format.termination)) {
299 default:
300 case 0: eol = "\n"; break;
301 case 1: eol = "\r"; break;
302 case 2: eol = "\r\n"; break;
305 switch (gtk_combo_box_get_active (state->format.quote)) {
306 default:
307 case 0: quotingmode = GSF_OUTPUT_CSV_QUOTING_MODE_AUTO; break;
308 case 1: quotingmode = GSF_OUTPUT_CSV_QUOTING_MODE_ALWAYS; break;
309 case 2: quotingmode = GSF_OUTPUT_CSV_QUOTING_MODE_NEVER; break;
312 switch (gtk_combo_box_get_active (state->format.transliterate)) {
313 case 0 : transliteratemode = GNM_STF_TRANSLITERATE_MODE_TRANS; break;
314 default:
315 case 1 : transliteratemode = GNM_STF_TRANSLITERATE_MODE_ESCAPE; break;
318 switch (gtk_combo_box_get_active (state->format.format)) {
319 default:
320 case 0: format = GNM_STF_FORMAT_AUTO; break;
321 case 1: format = GNM_STF_FORMAT_RAW; break;
322 case 2: format = GNM_STF_FORMAT_PRESERVE; break;
325 quote = gtk_editable_get_chars (GTK_EDITABLE (gtk_bin_get_child (GTK_BIN (state->format.quotechar))), 0, -1);
328 unsigned u = gtk_combo_box_get_active (state->format.separator);
329 if (u >= G_N_ELEMENTS (format_seps))
330 u = 4;
331 separator = format_seps[u]
332 ? g_strdup (format_seps[u])
333 : gtk_editable_get_chars (GTK_EDITABLE (state->format.custom), 0, -1);
336 charset = go_charmap_sel_get_encoding (GO_CHARMAP_SEL (state->format.charset));
337 locale = go_locale_sel_get_locale (GO_LOCALE_SEL (state->format.locale));
339 if (quotingmode == GSF_OUTPUT_CSV_QUOTING_MODE_AUTO) {
340 g_string_append (triggers, " \t");
341 g_string_append (triggers, eol);
342 g_string_append (triggers, quote);
343 g_string_append (triggers, separator);
346 g_object_set (state->stfe,
347 "eol", eol,
348 "quote", quote,
349 "quoting-mode", quotingmode,
350 "quoting-triggers", triggers->str,
351 "separator", separator,
352 "transliterate-mode", transliteratemode,
353 "format", format,
354 "charset", charset,
355 "locale", locale,
356 NULL);
358 if (gtk_toggle_button_get_active
359 (GTK_TOGGLE_BUTTON (go_gtk_builder_get_widget (state->gui,
360 "save-as-default-check")))) {
361 gnm_conf_set_stf_export_separator (separator);
362 gnm_conf_set_stf_export_stringindicator (quote);
363 gnm_conf_set_stf_export_terminator (eol);
364 gnm_conf_set_stf_export_quoting (quotingmode);
365 gnm_conf_set_stf_export_format (format);
366 gnm_conf_set_stf_export_transliteration (transliteratemode == GNM_STF_TRANSLITERATE_MODE_TRANS);
367 gnm_conf_set_stf_export_locale (locale);
368 gnm_conf_set_stf_export_encoding (charset);
371 /* Which sheets? */
372 gnm_stf_export_options_sheet_list_clear (state->stfe);
373 gtk_tree_model_foreach (GTK_TREE_MODEL (state->sheets.model),
374 (GtkTreeModelForeachFunc) cb_collect_exported_sheets, state);
376 g_free (separator);
377 g_free (quote);
378 g_string_free (triggers, TRUE);
379 g_free (locale);
381 state->cancelled = FALSE;
382 gtk_dialog_response (GTK_DIALOG (state->window), GTK_RESPONSE_OK);
385 static void
386 set_sheet_selection_count (TextExportState *state, int n)
388 state->sheets.num_selected = n;
389 gtk_widget_set_sensitive (state->sheets.select_all,
390 state->sheets.non_empty > n);
391 gtk_widget_set_sensitive (state->sheets.select_none, n != 0);
392 gtk_widget_set_sensitive (state->next_button, n != 0);
395 static gboolean
396 cb_set_sheet (GtkTreeModel *model, G_GNUC_UNUSED GtkTreePath *path, GtkTreeIter *iter,
397 gpointer data)
399 gboolean value;
401 gtk_tree_model_get (GTK_TREE_MODEL (model), iter,
402 STF_EXPORT_COL_NON_EMPTY, &value,
403 -1);
404 if (value)
405 gtk_list_store_set (GTK_LIST_STORE (model), iter,
406 STF_EXPORT_COL_EXPORTED,
407 GPOINTER_TO_INT (data),
408 -1);
409 return FALSE;
412 static void
413 cb_sheet_select_all (TextExportState *state)
415 gtk_tree_model_foreach (GTK_TREE_MODEL (state->sheets.model),
416 cb_set_sheet, GINT_TO_POINTER (TRUE));
417 set_sheet_selection_count (state, state->sheets.non_empty);
419 static void
420 cb_sheet_select_none (TextExportState *state)
422 gtk_tree_model_foreach (GTK_TREE_MODEL (state->sheets.model),
423 cb_set_sheet, GINT_TO_POINTER (FALSE));
424 set_sheet_selection_count (state, 0);
428 * Refreshes the buttons on a row (un)selection and selects the chosen sheet
429 * for this view.
431 static void
432 cb_selection_changed (GtkTreeSelection *new_selection,
433 TextExportState *state)
435 GtkTreeIter iter, it;
436 gboolean first_selected = TRUE, last_selected = TRUE;
438 GtkTreeSelection *selection =
439 (new_selection == NULL)
440 ? gtk_tree_view_get_selection (state->sheets.view)
441 : new_selection;
443 if (selection != NULL
444 && gtk_tree_selection_count_selected_rows (selection) > 0
445 && gtk_tree_model_get_iter_first
446 (GTK_TREE_MODEL (state->sheets.model),
447 &iter)) {
448 first_selected = gtk_tree_selection_iter_is_selected
449 (selection, &iter);
450 it = iter;
451 while (gtk_tree_model_iter_next
452 (GTK_TREE_MODEL (state->sheets.model),
453 &it))
454 iter = it;
455 last_selected = gtk_tree_selection_iter_is_selected
456 (selection, &iter);
459 gtk_widget_set_sensitive (state->sheets.top, !first_selected);
460 gtk_widget_set_sensitive (state->sheets.up, !first_selected);
461 gtk_widget_set_sensitive (state->sheets.bottom, !last_selected);
462 gtk_widget_set_sensitive (state->sheets.down, !last_selected);
464 return;
467 static void
468 move_element (TextExportState *state, gnm_iter_search_t iter_search)
470 GtkTreeSelection *selection = gtk_tree_view_get_selection (state->sheets.view);
471 GtkTreeModel *model;
472 GtkTreeIter a, b;
474 g_return_if_fail (selection != NULL);
476 if (!gtk_tree_selection_get_selected (selection, &model, &a))
477 return;
479 b = a;
480 if (!iter_search (model, &b))
481 return;
483 gtk_list_store_swap (state->sheets.model, &a, &b);
484 cb_selection_changed (NULL, state);
487 static void
488 cb_sheet_up (TextExportState *state)
490 move_element (state, gtk_tree_model_iter_previous);
493 static void
494 cb_sheet_down (TextExportState *state)
496 move_element (state, gtk_tree_model_iter_next);
499 static void
500 cb_sheet_top (TextExportState *state)
502 GtkTreeIter this_iter;
503 GtkTreeSelection *selection = gtk_tree_view_get_selection (state->sheets.view);
505 g_return_if_fail (selection != NULL);
507 if (!gtk_tree_selection_get_selected (selection, NULL, &this_iter))
508 return;
510 gtk_list_store_move_after (state->sheets.model, &this_iter, NULL);
511 cb_selection_changed (NULL, state);
514 static void
515 cb_sheet_bottom (TextExportState *state)
517 GtkTreeIter this_iter;
518 GtkTreeSelection *selection = gtk_tree_view_get_selection (state->sheets.view);
520 g_return_if_fail (selection != NULL);
522 if (!gtk_tree_selection_get_selected (selection, NULL, &this_iter))
523 return;
524 gtk_list_store_move_before (state->sheets.model, &this_iter, NULL);
525 cb_selection_changed (NULL, state);
528 static void
529 cb_sheet_export_toggled (G_GNUC_UNUSED GtkCellRendererToggle *cell,
530 const gchar *path_string,
531 TextExportState *state)
533 GtkTreePath *path = gtk_tree_path_new_from_string (path_string);
534 GtkTreeIter iter;
535 gboolean value;
537 if (gtk_tree_model_get_iter (GTK_TREE_MODEL (state->sheets.model),
538 &iter, path)) {
539 gtk_tree_model_get
540 (GTK_TREE_MODEL (state->sheets.model), &iter,
541 STF_EXPORT_COL_EXPORTED, &value,
542 -1);
543 gtk_list_store_set
544 (state->sheets.model, &iter,
545 STF_EXPORT_COL_EXPORTED, !value,
546 -1);
547 set_sheet_selection_count
548 (state,
549 state->sheets.num_selected + (value ? -1 : 1));
550 } else {
551 g_warning ("Did not get a valid iterator");
553 gtk_tree_path_free (path);
556 static void
557 stf_export_dialog_sheet_page_init (TextExportState *state)
559 int i;
560 GtkTreeSelection *selection;
561 GtkTreeIter iter;
562 GtkCellRenderer *renderer;
563 GSList *sheet_list;
565 state->sheets.select_all = go_gtk_builder_get_widget (state->gui, "sheet_select_all");
566 state->sheets.select_none = go_gtk_builder_get_widget (state->gui, "sheet_select_none");
567 state->sheets.up = go_gtk_builder_get_widget (state->gui, "sheet_up");
568 state->sheets.down = go_gtk_builder_get_widget (state->gui, "sheet_down");
569 state->sheets.top = go_gtk_builder_get_widget (state->gui, "sheet_top");
570 state->sheets.bottom = go_gtk_builder_get_widget (state->gui, "sheet_bottom");
571 gtk_button_set_alignment (GTK_BUTTON (state->sheets.up), 0., .5);
572 gtk_button_set_alignment (GTK_BUTTON (state->sheets.down), 0., .5);
573 gtk_button_set_alignment (GTK_BUTTON (state->sheets.top), 0., .5);
574 gtk_button_set_alignment (GTK_BUTTON (state->sheets.bottom), 0., .5);
576 state->sheets.model = gtk_list_store_new (STF_EXPORT_COL_MAX,
577 G_TYPE_BOOLEAN, G_TYPE_STRING, G_TYPE_OBJECT, G_TYPE_BOOLEAN);
578 state->sheets.view = GTK_TREE_VIEW (
579 go_gtk_builder_get_widget (state->gui, "sheet_list"));
580 gtk_tree_view_set_model (state->sheets.view, GTK_TREE_MODEL (state->sheets.model));
582 renderer = gtk_cell_renderer_toggle_new ();
583 g_signal_connect (G_OBJECT (renderer),
584 "toggled",
585 G_CALLBACK (cb_sheet_export_toggled), state);
586 gtk_tree_view_append_column (GTK_TREE_VIEW (state->sheets.view),
587 gtk_tree_view_column_new_with_attributes
588 (_("Export"),
589 renderer,
590 "active", STF_EXPORT_COL_EXPORTED,
591 "activatable", STF_EXPORT_COL_NON_EMPTY,
592 NULL));
593 gtk_tree_view_append_column (GTK_TREE_VIEW (state->sheets.view),
594 gtk_tree_view_column_new_with_attributes (_("Sheet"),
595 gtk_cell_renderer_text_new (),
596 "text", STF_EXPORT_COL_SHEET_NAME, NULL));
598 selection = gtk_tree_view_get_selection (state->sheets.view);
599 gtk_tree_selection_set_mode (selection, GTK_SELECTION_BROWSE);
601 state->sheets.num = workbook_sheet_count (state->wb);
602 state->sheets.num_selected = 0;
603 state->sheets.non_empty = 0;
605 sheet_list = gnm_stf_export_options_sheet_list_get (state->stfe);
607 for (i = 0 ; i < state->sheets.num ; i++) {
608 Sheet *sheet = workbook_sheet_by_index (state->wb, i);
609 GnmRange total_range = sheet_get_extent (sheet, TRUE, TRUE);
610 gboolean empty = sheet_is_region_empty (sheet, &total_range);
611 gboolean export =
612 !sheet_list || g_slist_find (sheet_list, sheet);
613 /* The above adds up to n^2 in number of sheets. Tough. */
615 gtk_list_store_append (state->sheets.model, &iter);
616 gtk_list_store_set (state->sheets.model, &iter,
617 STF_EXPORT_COL_EXPORTED, export && !empty,
618 STF_EXPORT_COL_SHEET_NAME, sheet->name_quoted,
619 STF_EXPORT_COL_SHEET, sheet,
620 STF_EXPORT_COL_NON_EMPTY, !empty,
621 -1);
622 if (!empty)
623 state->sheets.non_empty++;
625 if (export)
626 state->sheets.num_selected++;
628 set_sheet_selection_count (state, state->sheets.num_selected);
630 g_signal_connect_swapped (G_OBJECT (state->sheets.select_all),
631 "clicked",
632 G_CALLBACK (cb_sheet_select_all), state);
633 g_signal_connect_swapped (G_OBJECT (state->sheets.select_none),
634 "clicked",
635 G_CALLBACK (cb_sheet_select_none), state);
636 g_signal_connect_swapped (G_OBJECT (state->sheets.up),
637 "clicked",
638 G_CALLBACK (cb_sheet_up), state);
639 g_signal_connect_swapped (G_OBJECT (state->sheets.down),
640 "clicked",
641 G_CALLBACK (cb_sheet_down), state);
642 g_signal_connect_swapped (G_OBJECT (state->sheets.top),
643 "clicked",
644 G_CALLBACK (cb_sheet_top), state);
645 g_signal_connect_swapped (G_OBJECT (state->sheets.bottom),
646 "clicked",
647 G_CALLBACK (cb_sheet_bottom), state);
649 cb_selection_changed (NULL, state);
650 g_signal_connect (selection,
651 "changed",
652 G_CALLBACK (cb_selection_changed), state);
654 gtk_tree_view_set_reorderable (state->sheets.view, TRUE);
657 static void
658 stf_export_dialog_switch_page (TextExportState *state, TextExportPage new_page)
660 gtk_notebook_set_current_page (GTK_NOTEBOOK (state->notebook),
661 new_page);
662 if (new_page == PAGE_FORMAT) {
663 gtk_widget_hide (state->next_button);
664 gtk_widget_show (state->finish_button);
665 gtk_widget_grab_default (state->finish_button);
666 gtk_widget_grab_focus (state->finish_button);
667 } else {
668 gtk_widget_show (state->next_button);
669 gtk_widget_hide (state->finish_button);
670 gtk_widget_grab_default (state->next_button);
671 gtk_widget_grab_focus (state->next_button);
674 if (state->sheets.non_empty > 1) {
675 gtk_widget_show (state->back_button);
676 gtk_widget_set_sensitive (state->back_button, new_page > 0);
677 } else
678 gtk_widget_hide (state->back_button);
681 static void
682 cb_back_page (TextExportState *state)
684 int p = gtk_notebook_get_current_page (GTK_NOTEBOOK (state->notebook));
685 stf_export_dialog_switch_page (state, p - 1);
688 static void
689 cb_next_page (TextExportState *state)
691 int p = gtk_notebook_get_current_page (GTK_NOTEBOOK (state->notebook));
692 stf_export_dialog_switch_page (state, p + 1);
696 * stf_export_dialog:
697 * @wbcg: (nullable): #WBCGtk
698 * @stfe: An exporter to set up (and take defaults from)
699 * @wb: The #Workbook to export
701 * 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;