1 /*
2 * dialog-stf.c : Controls the widget on the CSV (Comma Separated Value) page.
3 *
4 * Copyright 2001 Almer S. Tigelaar <almer@gnome.org>
5 * Copyright 2003 Morten Welinder <terra@gnome.org>
6 *
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.
11 *
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.
16 *
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/>.
19 */
20
21 #include <gnumeric-config.h>
22 #include <dialogs/dialog-stf.h>
23 #include <gnm-format.h>
24 #include <goffice/goffice.h>
25 #include <string.h>
26
27 /*************************************************************************************************
28 * SIGNAL HANDLERS
29 *************************************************************************************************/
30
31 /**
32 * csv_page_global_change
33 * @widget: the widget which emitted the signal
34 * @data: mother struct
35 *
36 * This will update the preview based on the state of
37 * the widgets on the csv page
38 **/
39 static void
csv_page_global_change(G_GNUC_UNUSED GtkWidget * widget,StfDialogData * pagedata)40 csv_page_global_change (G_GNUC_UNUSED GtkWidget *widget,
41 StfDialogData *pagedata)
42 {
43 StfParseOptions_t *parseoptions = pagedata->parseoptions;
44 RenderData_t *renderdata = pagedata->csv.renderdata;
45 GSList *sepstr;
46 GString *sepc = g_string_new (NULL);
47 GStringChunk *lines_chunk;
48 GPtrArray *lines;
49 StfTrimType_t trim;
50
51 sepstr = NULL;
52 if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (pagedata->csv.csv_custom))) {
53 char *csvcustomtext = gtk_editable_get_chars (GTK_EDITABLE (pagedata->csv.csv_customseparator), 0, -1);
54
55 if (strcmp (csvcustomtext, "") != 0)
56 sepstr = g_slist_append (sepstr, csvcustomtext);
57 else
58 g_free (csvcustomtext);
59 }
60
61 if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (pagedata->csv.csv_tab)))
62 g_string_append_c (sepc, '\t');
63 if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (pagedata->csv.csv_colon)))
64 g_string_append_c (sepc, ':');
65 if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (pagedata->csv.csv_comma)))
66 g_string_append_c (sepc, ',');
67 if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (pagedata->csv.csv_space)))
68 g_string_append_c (sepc, ' ');
69 if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (pagedata->csv.csv_semicolon)))
70 g_string_append_c (sepc, ';');
71 if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (pagedata->csv.csv_hyphen)))
72 g_string_append_c (sepc, '-');
73
74 stf_parse_options_csv_set_separators (parseoptions,
75 strcmp (sepc->str, "") == 0 ? NULL : sepc->str,
76 sepstr);
77 g_string_free (sepc, TRUE);
78 g_slist_free_full (sepstr, g_free);
79
80 stf_parse_options_csv_set_duplicates (parseoptions,
81 gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (pagedata->csv.csv_duplicates)));
82 stf_parse_options_csv_set_trim_seps (parseoptions,
83 gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (pagedata->csv.csv_trim_seps)));
84
85 lines_chunk = g_string_chunk_new (100 * 1024);
86
87 /* Don't trim on this page. */
88 trim = parseoptions->trim_spaces;
89 stf_parse_options_set_trim_spaces (parseoptions, TRIM_TYPE_NEVER);
90 lines = stf_parse_general (parseoptions, lines_chunk,
91 pagedata->cur, pagedata->cur_end);
92 stf_parse_options_set_trim_spaces (parseoptions, trim);
93
94 stf_preview_set_lines (renderdata, lines_chunk, lines);
95 }
96
97 /**
98 * csv_page_custom_toggled
99 * @button: the Checkbutton that emitted the signal
100 * @data: a mother struct
101 *
102 * This will nicely activate the @data->csv_info->csv_customseparator widget
103 * so the user can enter text into it.
104 * It will also gray out this widget if the @button is not selected.
105 **/
106 static void
csv_page_custom_toggled(GtkCheckButton * button,StfDialogData * data)107 csv_page_custom_toggled (GtkCheckButton *button, StfDialogData *data)
108 {
109 if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (button))) {
110 gtk_widget_set_sensitive (GTK_WIDGET (data->csv.csv_customseparator), TRUE);
111 gtk_widget_grab_focus (GTK_WIDGET (data->csv.csv_customseparator));
112 gtk_editable_select_region (GTK_EDITABLE (data->csv.csv_customseparator), 0, -1);
113
114 } else {
115 gtk_widget_set_sensitive (GTK_WIDGET (data->csv.csv_customseparator), FALSE);
116 gtk_editable_select_region (GTK_EDITABLE (data->csv.csv_customseparator), 0, 0); /* If we don't use this the selection will remain blue */
117 }
118
119 csv_page_global_change (NULL, data);
120 }
121
122
123 static void
csv_page_textindicator_change(G_GNUC_UNUSED GtkWidget * widget,StfDialogData * data)124 csv_page_textindicator_change (G_GNUC_UNUSED GtkWidget *widget,
125 StfDialogData *data)
126 {
127 char *textfieldtext = gtk_editable_get_chars (GTK_EDITABLE (data->csv.csv_textfield), 0, -1);
128 gunichar str_ind = g_utf8_get_char (textfieldtext);
129
130 stf_parse_options_csv_set_stringindicator (data->parseoptions, str_ind);
131 g_free (textfieldtext);
132
133 stf_parse_options_csv_set_indicator_2x_is_single (data->parseoptions,
134 gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (data->csv.csv_2x_indicator)));
135 csv_page_global_change (NULL, data);
136 }
137
138 static void
csv_page_parseoptions_to_gui(StfDialogData * pagedata)139 csv_page_parseoptions_to_gui (StfDialogData *pagedata)
140 {
141 StfParseOptions_t *po = pagedata->parseoptions;
142
143 {
144 const char *sep;
145 gboolean s_tab = FALSE;
146 gboolean s_colon = FALSE;
147 gboolean s_comma = FALSE;
148 gboolean s_space = FALSE;
149 gboolean s_semicolon = FALSE;
150 gboolean s_hyphen = FALSE;
151
152 if (po->sep.chr)
153 for (sep = po->sep.chr; *sep; sep++) {
154 switch (*sep) {
155 case '\t': s_tab = TRUE; break;
156 case ':': s_colon = TRUE; break;
157 case ',': s_comma = TRUE; break;
158 case ' ': s_space = TRUE; break;
159 case ';': s_semicolon = TRUE; break;
160 case '-': s_hyphen = TRUE; break;
161 default: break;
162 }
163 }
164 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (pagedata->csv.csv_tab), s_tab);
165 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (pagedata->csv.csv_colon), s_colon);
166 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (pagedata->csv.csv_comma), s_comma);
167 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (pagedata->csv.csv_space), s_space);
168 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (pagedata->csv.csv_semicolon), s_semicolon);
169 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (pagedata->csv.csv_hyphen), s_hyphen);
170 }
171
172 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (pagedata->csv.csv_duplicates),
173 po->sep.duplicates);
174 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (pagedata->csv.csv_trim_seps),
175 po->trim_seps);
176 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (pagedata->csv.csv_2x_indicator),
177 po->indicator_2x_is_single);
178
179 {
180 char buffer[7];
181 gint len;
182 len = g_unichar_to_utf8 (po->stringindicator, buffer);
183 buffer[len] = 0;
184 gtk_combo_box_set_active_id
185 (GTK_COMBO_BOX (pagedata->csv.csv_textindicator),
186 buffer);
187 }
188 }
189
190
191 /**
192 * stf_dialog_csv_page_prepare
193 * @pagedata: mother struct
194 *
195 * Will prepare the csv page
196 **/
197 void
stf_dialog_csv_page_prepare(StfDialogData * pagedata)198 stf_dialog_csv_page_prepare (StfDialogData *pagedata)
199 {
200 csv_page_parseoptions_to_gui (pagedata);
201
202 /* Calling this routine will also automatically call global change which updates the preview too */
203 csv_page_custom_toggled (pagedata->csv.csv_custom, pagedata);
204 }
205
206 /*************************************************************************************************
207 * CSV EXPORTED FUNCTIONS
208 *************************************************************************************************/
209
210 /**
211 * stf_dialog_csv_page_cleanup
212 * @pagedata: mother struct
213 *
214 * Will cleanup csv page run-time data
215 **/
216 void
stf_dialog_csv_page_cleanup(StfDialogData * pagedata)217 stf_dialog_csv_page_cleanup (StfDialogData *pagedata)
218 {
219 stf_preview_free (pagedata->csv.renderdata);
220 pagedata->csv.renderdata = NULL;
221 }
222
223 void
stf_dialog_csv_page_init(GtkBuilder * gui,StfDialogData * pagedata)224 stf_dialog_csv_page_init (GtkBuilder *gui, StfDialogData *pagedata)
225 {
226 g_return_if_fail (gui != NULL);
227 g_return_if_fail (pagedata != NULL);
228
229 /* Create/get object and fill information struct */
230 pagedata->csv.csv_tab = GTK_CHECK_BUTTON (go_gtk_builder_get_widget (gui, "csv_tab"));
231 pagedata->csv.csv_colon = GTK_CHECK_BUTTON (go_gtk_builder_get_widget (gui, "csv_colon"));
232 pagedata->csv.csv_comma = GTK_CHECK_BUTTON (go_gtk_builder_get_widget (gui, "csv_comma"));
233 pagedata->csv.csv_space = GTK_CHECK_BUTTON (go_gtk_builder_get_widget (gui, "csv_space"));
234 pagedata->csv.csv_semicolon = GTK_CHECK_BUTTON (go_gtk_builder_get_widget (gui, "csv_semicolon"));
235 pagedata->csv.csv_hyphen = GTK_CHECK_BUTTON (go_gtk_builder_get_widget (gui, "csv_hyphen"));
236 pagedata->csv.csv_custom = GTK_CHECK_BUTTON (go_gtk_builder_get_widget (gui, "csv_custom"));
237 pagedata->csv.csv_customseparator = GTK_ENTRY (go_gtk_builder_get_widget (gui, "csv_customseparator"));
238 pagedata->csv.csv_2x_indicator = GTK_CHECK_BUTTON (go_gtk_builder_get_widget (gui, "csv_2x_indicator"));
239
240 pagedata->csv.csv_textindicator = go_gtk_builder_get_widget (gui, "csv-textindicator");
241 pagedata->csv.csv_textfield = GTK_ENTRY (gtk_bin_get_child (GTK_BIN (pagedata->csv.csv_textindicator)));
242
243 pagedata->csv.csv_duplicates = GTK_CHECK_BUTTON (go_gtk_builder_get_widget (gui, "csv_duplicates"));
244 pagedata->csv.csv_trim_seps = GTK_CHECK_BUTTON (go_gtk_builder_get_widget (gui, "csv_trim_seps"));
245 pagedata->csv.csv_data_container = go_gtk_builder_get_widget (gui, "csv_data_container");
246
247 /* Set properties */
248 pagedata->csv.renderdata =
249 stf_preview_new (pagedata->csv.csv_data_container,
250 NULL);
251 csv_page_parseoptions_to_gui (pagedata);
252
253 /* Connect signals */
254 g_signal_connect (G_OBJECT (pagedata->csv.csv_tab),
255 "toggled",
256 G_CALLBACK (csv_page_global_change), pagedata);
257 g_signal_connect (G_OBJECT (pagedata->csv.csv_colon),
258 "toggled",
259 G_CALLBACK (csv_page_global_change), pagedata);
260 g_signal_connect (G_OBJECT (pagedata->csv.csv_comma),
261 "toggled",
262 G_CALLBACK (csv_page_global_change), pagedata);
263 g_signal_connect (G_OBJECT (pagedata->csv.csv_space),
264 "toggled",
265 G_CALLBACK (csv_page_global_change), pagedata);
266 g_signal_connect (G_OBJECT (pagedata->csv.csv_semicolon),
267 "toggled",
268 G_CALLBACK (csv_page_global_change), pagedata);
269 g_signal_connect (G_OBJECT (pagedata->csv.csv_hyphen),
270 "toggled",
271 G_CALLBACK (csv_page_global_change), pagedata);
272 g_signal_connect (G_OBJECT (pagedata->csv.csv_custom),
273 "toggled",
274 G_CALLBACK (csv_page_custom_toggled), pagedata);
275 g_signal_connect (G_OBJECT (pagedata->csv.csv_customseparator),
276 "changed",
277 G_CALLBACK (csv_page_global_change), pagedata);
278 g_signal_connect (G_OBJECT (pagedata->csv.csv_duplicates),
279 "toggled",
280 G_CALLBACK (csv_page_global_change), pagedata);
281 g_signal_connect (G_OBJECT (pagedata->csv.csv_trim_seps),
282 "toggled",
283 G_CALLBACK (csv_page_global_change), pagedata);
284 g_signal_connect (G_OBJECT (pagedata->csv.csv_2x_indicator),
285 "toggled",
286 G_CALLBACK (csv_page_textindicator_change), pagedata);
287 g_signal_connect (G_OBJECT (pagedata->csv.csv_textfield),
288 "changed",
289 G_CALLBACK (csv_page_textindicator_change), pagedata);
290 }
291