1 /* PSPPIRE - a graphical user interface for PSPP.
2 Copyright (C) 2008, 2009, 2010, 2011, 2012, 2013 Free Software Foundation
4 This program is free software: you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation, either version 3 of the License, or
7 (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
14 You should have received a copy of the GNU General Public License
15 along with this program. If not, see <http://www.gnu.org/licenses/>. */
19 #include "ui/gui/text-data-import-dialog.h"
28 #include "data/data-in.h"
29 #include "data/data-out.h"
30 #include "data/format-guesser.h"
31 #include "data/value-labels.h"
32 #include "language/data-io/data-parser.h"
33 #include "language/lexer/lexer.h"
34 #include "libpspp/assertion.h"
35 #include "libpspp/i18n.h"
36 #include "libpspp/line-reader.h"
37 #include "libpspp/message.h"
38 #include "ui/gui/checkbox-treeview.h"
39 #include "ui/gui/dialog-common.h"
40 #include "ui/gui/executor.h"
41 #include "ui/gui/helper.h"
42 #include "ui/gui/builder-wrapper.h"
43 #include "ui/gui/psppire-data-window.h"
44 #include "ui/gui/psppire-dialog.h"
45 #include "ui/gui/psppire-encoding-selector.h"
46 #include "ui/gui/psppire-empty-list-store.h"
47 #include "ui/gui/psppire-var-sheet.h"
48 #include "ui/gui/psppire-scanf.h"
51 #include "gl/intprops.h"
52 #include "gl/xalloc.h"
55 #define _(msgid) gettext (msgid)
56 #define N_(msgid) msgid
58 /* Page where the user verifies and adjusts input formats. */
62 PsppSheetView *data_tree_view;
63 PsppireDict *psppire_dict;
64 struct variable **modified_vars;
65 size_t modified_var_cnt;
68 /* The "formats" page of the assistant. */
70 static void on_variable_change (PsppireDict *dict, int idx,
72 const struct variable *oldvar,
73 struct import_assistant *);
75 static void clear_modified_vars (struct import_assistant *);
77 /* Initializes IA's formats substructure. */
80 formats_page_create (struct import_assistant *ia)
82 GtkBuilder *builder = ia->asst.builder;
83 struct formats_page *p = xzalloc (sizeof *p);
85 p->page = add_page_to_assistant (ia, get_widget_assert (builder, "Formats"),
86 GTK_ASSISTANT_PAGE_CONFIRM);
88 p->data_tree_view = PSPP_SHEET_VIEW (get_widget_assert (builder, "data"));
89 p->modified_vars = NULL;
90 p->modified_var_cnt = 0;
95 /* Frees IA's formats substructure. */
97 destroy_formats_page (struct import_assistant *ia)
99 struct formats_page *p = ia->formats;
101 if (p->psppire_dict != NULL)
103 dict_destroy (p->psppire_dict->dict);
104 g_object_unref (p->psppire_dict);
106 clear_modified_vars (ia);
109 /* Called just before the formats page of the assistant is
112 prepare_formats_page (struct import_assistant *ia)
114 struct dictionary *dict;
115 PsppireDict *psppire_dict;
116 GtkBin *vars_scroller;
117 GtkWidget *old_var_sheet;
118 PsppireVarSheet *var_sheet;
119 struct formats_page *p = ia->formats;
120 struct fmt_guesser *fg;
121 unsigned long int number = 0;
124 push_watch_cursor (ia);
126 dict = dict_create (get_default_encoding ());
127 fg = fmt_guesser_create ();
128 for (column_idx = 0; column_idx < ia->column_cnt; column_idx++)
130 struct variable *modified_var =
131 (column_idx < p->modified_var_cnt ? p->modified_vars[column_idx] : NULL);
132 if (modified_var == NULL)
134 struct column *column = &ia->columns[column_idx];
135 struct variable *var;
136 struct fmt_spec format;
140 /* Choose variable name. */
141 name = dict_make_unique_var_name (dict, column->name, &number);
143 /* Choose variable format. */
144 fmt_guesser_clear (fg);
145 for (row = ia->skip_lines; row < ia->file.line_cnt; row++)
146 fmt_guesser_add (fg, column->contents[row]);
147 fmt_guesser_guess (fg, &format);
148 fmt_fix_input (&format);
150 /* Create variable. */
151 var = dict_create_var_assert (dict, name, fmt_var_width (&format));
152 var_set_both_formats (var, &format);
160 name = dict_make_unique_var_name (dict, var_get_name (modified_var),
162 dict_clone_var_as_assert (dict, modified_var, name);
166 fmt_guesser_destroy (fg);
168 psppire_dict = psppire_dict_new_from_dict (dict);
169 g_signal_connect (psppire_dict, "variable-changed",
170 G_CALLBACK (on_variable_change), ia);
172 ia->formats->psppire_dict = psppire_dict;
174 /* XXX: PsppireVarStore doesn't hold a reference to
175 psppire_dict for now, but it should. After it does, we
176 should g_object_ref the psppire_dict here, since we also
177 hold a reference via ia->formats->dict. */
178 var_sheet = PSPPIRE_VAR_SHEET (psppire_var_sheet_new ());
179 g_object_set (var_sheet,
180 "dictionary", psppire_dict,
181 "may-create-vars", FALSE,
182 "may-delete-vars", FALSE,
183 "format-use", FMT_FOR_INPUT,
184 "enable-grid-lines", PSPP_SHEET_VIEW_GRID_LINES_BOTH,
187 vars_scroller = GTK_BIN (get_widget_assert (ia->asst.builder, "vars-scroller"));
188 old_var_sheet = gtk_bin_get_child (vars_scroller);
189 if (old_var_sheet != NULL)
190 gtk_widget_destroy (old_var_sheet);
191 gtk_container_add (GTK_CONTAINER (vars_scroller), GTK_WIDGET (var_sheet));
192 gtk_widget_show (GTK_WIDGET (var_sheet));
194 gtk_widget_destroy (GTK_WIDGET (ia->formats->data_tree_view));
195 ia->formats->data_tree_view = create_data_tree_view (
197 GTK_CONTAINER (get_widget_assert (ia->asst.builder, "data-scroller")),
200 gtk_widget_show (ia->asst.paste_button);
202 pop_watch_cursor (ia);
205 /* Clears the set of user-modified variables from IA's formats
206 substructure. This discards user modifications to variable
207 formats, thereby causing formats to revert to their
210 clear_modified_vars (struct import_assistant *ia)
212 struct formats_page *p = ia->formats;
215 for (i = 0; i < p->modified_var_cnt; i++)
216 var_destroy (p->modified_vars[i]);
217 free (p->modified_vars);
218 p->modified_vars = NULL;
219 p->modified_var_cnt = 0;
222 /* Resets the formats page to its defaults, discarding user
225 reset_formats_page (struct import_assistant *ia)
227 clear_modified_vars (ia);
228 prepare_formats_page (ia);
233 /* Called when the user changes one of the variables in the
236 on_variable_change (PsppireDict *dict, int dict_idx,
237 unsigned int what, const struct variable *oldvar,
238 struct import_assistant *ia)
240 struct formats_page *p = ia->formats;
241 PsppSheetView *tv = ia->formats->data_tree_view;
242 gint column_idx = dict_idx + 1;
244 push_watch_cursor (ia);
246 /* Remove previous column and replace with new column. */
247 pspp_sheet_view_remove_column (tv, pspp_sheet_view_get_column (tv, column_idx));
248 pspp_sheet_view_insert_column (tv, make_data_column (ia, tv, false, dict_idx),
251 /* Save a copy of the modified variable in modified_vars, so
252 that its attributes will be preserved if we back up to the
253 previous page with the Prev button and then come back
255 if (dict_idx >= p->modified_var_cnt)
258 p->modified_vars = xnrealloc (p->modified_vars, dict_idx + 1,
259 sizeof *p->modified_vars);
260 for (i = 0; i <= dict_idx; i++)
261 p->modified_vars[i] = NULL;
262 p->modified_var_cnt = dict_idx + 1;
264 if (p->modified_vars[dict_idx])
265 var_destroy (p->modified_vars[dict_idx]);
266 p->modified_vars[dict_idx]
267 = var_clone (psppire_dict_get_variable (dict, dict_idx));
269 pop_watch_cursor (ia);
276 formats_append_syntax (const struct import_assistant *ia, struct string *s)
280 ds_put_cstr (s, " /VARIABLES=\n");
282 var_cnt = dict_get_var_cnt (ia->dict);
283 for (i = 0; i < var_cnt; i++)
285 struct variable *var = dict_get_var (ia->dict, i);
286 char format_string[FMT_STRING_LEN_MAX + 1];
287 fmt_to_string (var_get_print_format (var), format_string);
288 ds_put_format (s, " %s %s%s\n",
289 var_get_name (var), format_string,
290 i == var_cnt - 1 ? "." : "");