1.12.42
[gnumeric.git] / src / dialogs / dialog-stf.c
blob9d379e470f4a0034291ea5a450231561ac9c64d3
1 /*
2 * dialog-stf.c: implementation of the STF import dialog
4 * Copyright 2001 Almer S. Tigelaar <almer@gnome.org>
5 * Copyright 2003 Morten Welinder <terra@gnome.org>
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 <glib/gi18n-lib.h>
23 #include <gnumeric.h>
24 #include <dialogs/dialog-stf.h>
26 #include <gnm-format.h>
27 #include <wbc-gtk.h>
28 #include <command-context.h>
29 #include <gui-util.h>
30 #include <sheet-style.h>
31 #include <mstyle.h>
32 #include <clipboard.h>
33 #include <string.h>
35 /**********************************************************************************************
36 * DIALOG CONTROLLING CODE
37 **********************************************************************************************/
39 /**
40 * stf_dialog_set_initial_keyboard_focus
41 * @pagedata: mother struct
43 * Sets keyboard focus to an appropriate widget on the page.
45 * returns: nothing
46 **/
47 static void
48 stf_dialog_set_initial_keyboard_focus (StfDialogData *pagedata)
50 GtkWidget *focus_widget = NULL;
51 GtkWidget *default_widget = pagedata->next_button;
53 switch (gtk_notebook_get_current_page (pagedata->notebook)) {
54 case DPG_MAIN:
55 focus_widget = GTK_WIDGET (pagedata->main.main_separated);
56 break;
57 case DPG_CSV:
58 focus_widget = GTK_WIDGET (pagedata->csv.csv_space);
59 break;
60 case DPG_FIXED:
61 focus_widget = GTK_WIDGET (pagedata->fixed.fixed_auto);
62 break;
63 case DPG_FORMAT:
64 focus_widget = pagedata->finish_button;
65 default_widget = pagedata->finish_button;
66 break;
67 default:
68 g_assert_not_reached ();
71 if (focus_widget)
72 gtk_widget_grab_focus (focus_widget);
74 if (default_widget)
75 gtk_widget_grab_default (default_widget);
79 static void
80 frob_buttons (StfDialogData *pagedata)
82 StfDialogPage pos =
83 gtk_notebook_get_current_page (pagedata->notebook);
85 gtk_widget_set_sensitive (pagedata->back_button, pos != DPG_MAIN);
86 gtk_widget_set_sensitive (pagedata->next_button, pos != DPG_FORMAT);
89 static void
90 prepare_page (StfDialogData *data)
92 switch (gtk_notebook_get_current_page (data->notebook)) {
93 case DPG_MAIN: stf_dialog_main_page_prepare (data); break;
94 case DPG_CSV: stf_dialog_csv_page_prepare (data); break;
95 case DPG_FIXED: stf_dialog_fixed_page_prepare (data); break;
96 case DPG_FORMAT: stf_dialog_format_page_prepare (data); break;
102 static void
103 next_clicked (G_GNUC_UNUSED GtkWidget *widget, StfDialogData *data)
105 StfDialogPage newpos;
107 switch (gtk_notebook_get_current_page (data->notebook)) {
108 case DPG_MAIN:
109 stf_preview_set_lines (data->main.renderdata, NULL, NULL);
110 if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (data->main.main_separated))) {
111 newpos = DPG_CSV;
112 } else {
113 newpos = DPG_FIXED;
115 break;
117 case DPG_CSV:
118 stf_preview_set_lines (data->csv.renderdata, NULL, NULL);
119 newpos = DPG_FORMAT;
120 break;
122 case DPG_FIXED:
123 stf_preview_set_lines (data->fixed.renderdata, NULL, NULL);
124 newpos = DPG_FORMAT;
125 break;
127 default:
128 g_assert_not_reached ();
129 return;
132 gtk_notebook_set_current_page (data->notebook, newpos);
133 prepare_page (data);
134 frob_buttons (data);
135 stf_dialog_set_initial_keyboard_focus (data);
138 static void
139 back_clicked (G_GNUC_UNUSED GtkWidget *widget, StfDialogData *data)
141 StfDialogPage newpos;
143 switch (gtk_notebook_get_current_page (data->notebook)) {
144 case DPG_FORMAT:
145 stf_preview_set_lines (data->format.renderdata, NULL, NULL);
146 if (data->parseoptions->parsetype == PARSE_TYPE_CSV)
147 newpos = DPG_CSV;
148 else
149 newpos = DPG_FIXED;
150 break;
152 case DPG_FIXED:
153 stf_preview_set_lines (data->fixed.renderdata, NULL, NULL);
154 newpos = DPG_MAIN;
155 break;
157 case DPG_CSV:
158 stf_preview_set_lines (data->csv.renderdata, NULL, NULL);
159 newpos = DPG_MAIN;
160 break;
162 default:
163 g_assert_not_reached ();
164 return;
167 gtk_notebook_set_current_page (data->notebook, newpos);
168 prepare_page (data);
169 frob_buttons (data);
170 stf_dialog_set_initial_keyboard_focus (data);
175 * stf_dialog_attach_page_signals
176 * @gui: the GtkBuilder gui of the dialog
177 * @pagedata: mother struct
179 * Connects all signals to all pages and fills the mother struct
180 * The page flow looks like:
182 * main_page /- csv_page -\ format_page
183 * \- fixed_page -/
185 * returns: nothing
187 static void
188 stf_dialog_attach_page_signals (GtkBuilder *gui, StfDialogData *pagedata)
190 frob_buttons (pagedata);
191 /* Signals for individual pages */
193 g_signal_connect (G_OBJECT (pagedata->next_button),
194 "clicked",
195 G_CALLBACK (next_clicked), pagedata);
197 g_signal_connect (G_OBJECT (pagedata->back_button),
198 "clicked",
199 G_CALLBACK (back_clicked), pagedata);
203 * stf_dialog_editables_enter
204 * @pagedata: mother struct
206 * Make <Ret> in text fields activate default.
208 * returns: nothing
210 static void
211 stf_dialog_editables_enter (StfDialogData *pagedata)
213 #if 0
214 gnm_editable_enters
215 (pagedata->window,
216 GTK_WIDGET (&pagedata->main.main_startrow->entry));
217 gnm_editable_enters
218 (pagedata->window,
219 GTK_WIDGET (&pagedata->main.main_stoprow->entry));
220 gnm_editable_enters
221 (pagedata->window,
222 GTK_WIDGET (pagedata->csv.csv_customseparator));
223 gnumeric_combo_enters
224 (pagedata->window,
225 pagedata->csv.csv_textindicator);
226 gnm_editable_enters
227 (pagedata->window,
228 GTK_WIDGET (&pagedata->fixed.fixed_colend->entry));
229 go_format_sel_editable_enters
230 (pagedata->format.format_selector,
231 pagedata->window);
232 #endif
236 * stf_dialog: (skip)
237 * @wbcg: (nullable):
238 * @source: name of the file we are importing (or data) in UTF-8
239 * @data: the data itself
241 * This will start the import.
242 * (NOTE: you have to free the DialogStfResult_t that this function returns yourself)
244 * returns: A DialogStfResult_t struct on success, NULL otherwise.
246 DialogStfResult_t*
247 stf_dialog (WBCGtk *wbcg,
248 const char *opt_encoding,
249 gboolean fixed_encoding,
250 const char *opt_locale,
251 gboolean fixed_locale,
252 const char *source,
253 const char *data,
254 int data_len)
256 GtkBuilder *gui;
257 DialogStfResult_t *dialogresult;
258 StfDialogData pagedata;
259 GtkResponseType resp;
261 g_return_val_if_fail (opt_encoding != NULL || !fixed_encoding, NULL);
262 g_return_val_if_fail (opt_locale != NULL || !fixed_locale, NULL);
263 g_return_val_if_fail (source != NULL, NULL);
264 g_return_val_if_fail (data != NULL, NULL);
266 gui = gnm_gtk_builder_load ("res:ui/dialog-stf.ui", NULL, GO_CMD_CONTEXT (wbcg));
267 if (gui == NULL)
268 return NULL;
270 pagedata.encoding = g_strdup (opt_encoding);
271 pagedata.fixed_encoding = fixed_encoding;
272 pagedata.locale = g_strdup (opt_locale);
273 pagedata.fixed_locale = fixed_locale;
274 pagedata.wbcg = wbcg;
275 pagedata.source = source;
276 pagedata.raw_data = data;
277 pagedata.raw_data_len = data_len < 0 ? (int)strlen (data) : data_len;
278 pagedata.utf8_data = NULL;
279 pagedata.cur = NULL;
281 pagedata.dialog = GTK_DIALOG (go_gtk_builder_get_widget (gui, "stf_dialog"));
282 pagedata.notebook = GTK_NOTEBOOK (go_gtk_builder_get_widget (gui, "stf_notebook"));
283 pagedata.next_button = go_gtk_builder_get_widget (gui, "forward_button");
284 pagedata.back_button = go_gtk_builder_get_widget (gui, "back_button");
285 pagedata.cancel_button = go_gtk_builder_get_widget (gui, "cancel_button");
286 pagedata.help_button = go_gtk_builder_get_widget (gui, "help_button");
287 pagedata.finish_button = go_gtk_builder_get_widget (gui, "finish_button");
288 pagedata.parseoptions = NULL;
290 gtk_widget_set_name (GTK_WIDGET (pagedata.dialog), "stf-import");
292 stf_dialog_main_page_init (gui, &pagedata);
293 stf_dialog_csv_page_init (gui, &pagedata);
294 stf_dialog_fixed_page_init (gui, &pagedata);
295 stf_dialog_format_page_init (gui, &pagedata);
297 stf_dialog_attach_page_signals (gui, &pagedata);
299 stf_dialog_editables_enter (&pagedata);
301 stf_dialog_set_initial_keyboard_focus (&pagedata);
303 prepare_page (&pagedata);
304 frob_buttons (&pagedata);
306 resp = go_gtk_dialog_run (pagedata.dialog, wbcg_toplevel (wbcg));
308 if (resp == GTK_RESPONSE_OK) {
309 dialogresult = g_new (DialogStfResult_t, 1);
311 dialogresult->text = pagedata.utf8_data;
312 *((char *)pagedata.cur_end) = 0;
313 if (dialogresult->text != pagedata.cur)
314 strcpy (dialogresult->text, pagedata.cur);
315 pagedata.cur = pagedata.utf8_data = NULL;
317 dialogresult->encoding = pagedata.encoding;
318 pagedata.encoding = NULL;
320 dialogresult->colcount = pagedata.format.col_import_count;
321 dialogresult->rowcount = pagedata.rowcount;
323 dialogresult->parseoptions = pagedata.parseoptions;
324 pagedata.parseoptions = NULL;
325 g_free (dialogresult->parseoptions->locale);
326 dialogresult->parseoptions->locale = pagedata.locale;
327 pagedata.locale = NULL;
329 if (pagedata.format.formats) {
330 g_ptr_array_free (dialogresult->parseoptions->formats, TRUE);
331 dialogresult->parseoptions->formats = pagedata.format.formats;
332 pagedata.format.formats = NULL;
333 } else
334 g_ptr_array_set_size (dialogresult->parseoptions->formats, 0);
335 dialogresult->parseoptions->col_import_array
336 = pagedata.format.col_import_array;
337 dialogresult->parseoptions->col_import_array_len
338 = pagedata.format.col_import_array_len;
339 pagedata.format.col_import_array = NULL;
340 dialogresult->parseoptions->col_autofit_array
341 = pagedata.format.col_autofit_array;
342 pagedata.format.col_autofit_array = NULL;
343 pagedata.format.col_import_count = 0;
344 pagedata.format.col_import_array_len = 0;
345 } else {
346 dialogresult = NULL;
349 stf_dialog_main_page_cleanup (&pagedata);
350 stf_dialog_csv_page_cleanup (&pagedata);
351 stf_dialog_fixed_page_cleanup (&pagedata);
352 stf_dialog_format_page_cleanup (&pagedata);
354 g_object_unref (gui);
355 g_free (pagedata.encoding);
356 g_free (pagedata.locale);
357 g_free (pagedata.utf8_data);
358 if (pagedata.parseoptions)
359 stf_parse_options_free (pagedata.parseoptions);
361 return dialogresult;
365 * stf_dialog_result_free
366 * @dialogresult: a dialogresult struct
368 * This routine will properly free the members of @dialogresult and
369 * @dialogresult itself
371 * returns: nothing
373 void
374 stf_dialog_result_free (DialogStfResult_t *dialogresult)
376 g_return_if_fail (dialogresult != NULL);
378 stf_parse_options_free (dialogresult->parseoptions);
380 g_free (dialogresult->text);
381 g_free (dialogresult->encoding);
383 g_free (dialogresult);
387 * stf_dialog_result_attach_formats_to_cr
388 * @dialogresult: a dialogresult struct
389 * @cr: a cell region
391 * Attach the formats of the dialogresult to the given cell region.
393 * returns: nothing
395 void
396 stf_dialog_result_attach_formats_to_cr (DialogStfResult_t *dialogresult,
397 GnmCellRegion *cr)
399 unsigned int col, targetcol;
401 g_return_if_fail (dialogresult != NULL);
402 g_return_if_fail (cr != NULL);
404 targetcol = 0;
405 for (col = 0; col < dialogresult->parseoptions->formats->len; col++) {
406 if (dialogresult->parseoptions->col_import_array[col]) {
407 GOFormat *sf = g_ptr_array_index
408 (dialogresult->parseoptions->formats, col);
409 GnmStyleRegion *sr = g_new (GnmStyleRegion, 1);
411 sr->range.start.col = targetcol;
412 sr->range.start.row = 0;
413 sr->range.end.col = targetcol;
414 sr->range.end.row = dialogresult->rowcount - 1;
415 sr->style = gnm_style_new_default ();
416 gnm_style_set_format (sr->style, sf);
417 targetcol++;
419 cr->styles = g_slist_prepend (cr->styles, sr);