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/casereader.h"
32 #include "data/gnumeric-reader.h"
33 #include "data/ods-reader.h"
34 #include "data/spreadsheet-reader.h"
35 #include "data/value-labels.h"
36 #include "language/data-io/data-parser.h"
37 #include "language/lexer/lexer.h"
38 #include "libpspp/assertion.h"
39 #include "libpspp/i18n.h"
40 #include "libpspp/line-reader.h"
41 #include "libpspp/message.h"
42 #include "ui/gui/checkbox-treeview.h"
43 #include "ui/gui/dialog-common.h"
44 #include "ui/gui/executor.h"
45 #include "ui/gui/helper.h"
46 #include "ui/gui/builder-wrapper.h"
47 #include "ui/gui/psppire-data-window.h"
48 #include "ui/gui/psppire-dialog.h"
49 #include "ui/gui/psppire-encoding-selector.h"
50 #include "ui/gui/psppire-empty-list-store.h"
51 #include "ui/gui/psppire-var-sheet.h"
52 #include "ui/gui/psppire-scanf.h"
53 #include "ui/syntax-gen.h"
55 #include "gl/intprops.h"
56 #include "gl/xalloc.h"
59 #define _(msgid) gettext (msgid)
60 #define N_(msgid) msgid
62 struct import_assistant;
65 static char *choose_file (GtkWindow *parent_window, gchar **encodingp);
70 /* Obtains the file to import from the user and initializes IA's
71 file substructure. PARENT_WINDOW must be the window to use
72 as the file chooser window's parent.
74 Returns true if successful, false if the file name could not
75 be obtained or the file could not be read. */
77 init_file (struct import_assistant *ia, GtkWindow *parent_window)
79 enum { MAX_LINE_LEN = 16384 }; /* Max length of an acceptable line. */
80 struct file *file = &ia->file;
83 file->file_name = choose_file (parent_window, &file->encoding);
84 if (file->file_name == NULL)
87 if (ia->spreadsheet == NULL)
88 ia->spreadsheet = gnumeric_probe (file->file_name, false);
90 if (ia->spreadsheet == NULL)
91 ia->spreadsheet = ods_probe (file->file_name, false);
93 if (ia->spreadsheet == NULL)
96 struct line_reader *reader = line_reader_for_file (file->encoding, file->file_name, O_RDONLY);
99 msg_error (errno, _("Could not open `%s'"),
104 ds_init_empty (&input);
105 file->lines = xnmalloc (MAX_PREVIEW_LINES, sizeof *file->lines);
106 for (; file->line_cnt < MAX_PREVIEW_LINES; file->line_cnt++)
109 if (!line_reader_read (reader, &input, MAX_LINE_LEN + 1)
110 || ds_length (&input) > MAX_LINE_LEN)
112 if (line_reader_eof (reader))
114 else if (line_reader_error (reader))
115 msg (ME, _("Error reading `%s': %s"),
116 file->file_name, strerror (line_reader_error (reader)));
118 msg (ME, _("Failed to read `%s', because it contains a line "
119 "over %d bytes long and therefore appears not to be "
121 file->file_name, MAX_LINE_LEN);
122 line_reader_close (reader);
128 ds_init_cstr (&file->lines[file->line_cnt],
129 recode_string ("UTF-8", line_reader_get_encoding (reader),
130 ds_cstr (&input), ds_length (&input)));
134 if (file->line_cnt == 0)
136 msg (ME, _("`%s' is empty."), file->file_name);
137 line_reader_close (reader);
142 /* Estimate the number of lines in the file. */
143 if (file->line_cnt < MAX_PREVIEW_LINES)
144 file->total_lines = file->line_cnt;
148 off_t position = line_reader_tell (reader);
149 if (fstat (line_reader_fileno (reader), &s) == 0 && position > 0)
150 file->total_lines = (double) file->line_cnt / position * s.st_size;
152 file->total_lines = 0;
155 line_reader_close (reader);
161 /* Frees IA's file substructure. */
163 destroy_file (struct import_assistant *ia)
165 struct file *f = &ia->file;
170 for (i = 0; i < f->line_cnt; i++)
171 ds_destroy (&f->lines[i]);
175 g_free (f->file_name);
176 g_free (f->encoding);
179 /* Obtains the file to read from the user. If successful, returns the name of
180 the file and stores the user's chosen encoding for the file into *ENCODINGP.
181 The caller must free each of these strings with g_free().
183 On failure, stores a null pointer and stores NULL in *ENCODINGP.
185 PARENT_WINDOW must be the window to use as the file chooser window's
188 choose_file (GtkWindow *parent_window, gchar **encodingp)
191 GtkFileFilter *filter = NULL;
193 GtkWidget *dialog = gtk_file_chooser_dialog_new (_("Import Delimited Text Data"),
195 GTK_FILE_CHOOSER_ACTION_OPEN,
196 GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
197 GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT,
200 g_object_set (dialog, "local-only", FALSE, NULL);
202 filter = gtk_file_filter_new ();
203 gtk_file_filter_set_name (filter, _("Text Files"));
204 gtk_file_filter_add_mime_type (filter, "text/*");
205 gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (dialog), filter);
207 filter = gtk_file_filter_new ();
208 gtk_file_filter_set_name (filter, _("Text (*.txt) Files"));
209 gtk_file_filter_add_pattern (filter, "*.txt");
210 gtk_file_filter_add_pattern (filter, "*.TXT");
211 gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (dialog), filter);
213 filter = gtk_file_filter_new ();
214 gtk_file_filter_set_name (filter, _("Plain Text (ASCII) Files"));
215 gtk_file_filter_add_mime_type (filter, "text/plain");
216 gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (dialog), filter);
218 filter = gtk_file_filter_new ();
219 gtk_file_filter_set_name (filter, _("Comma Separated Value Files"));
220 gtk_file_filter_add_mime_type (filter, "text/csv");
221 gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (dialog), filter);
223 /* I've never encountered one of these, but it's listed here:
224 http://www.iana.org/assignments/media-types/text/tab-separated-values */
225 filter = gtk_file_filter_new ();
226 gtk_file_filter_set_name (filter, _("Tab Separated Value Files"));
227 gtk_file_filter_add_mime_type (filter, "text/tab-separated-values");
228 gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (dialog), filter);
230 filter = gtk_file_filter_new ();
231 gtk_file_filter_set_name (filter, _("Gnumeric Spreadsheet Files"));
232 gtk_file_filter_add_mime_type (filter, "application/x-gnumeric");
233 gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (dialog), filter);
235 filter = gtk_file_filter_new ();
236 gtk_file_filter_set_name (filter, _("OpenDocument Spreadsheet Files"));
237 gtk_file_filter_add_mime_type (filter, "application/vnd.oasis.opendocument.spreadsheet");
238 gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (dialog), filter);
240 filter = gtk_file_filter_new ();
241 gtk_file_filter_set_name (filter, _("All Spreadsheet Files"));
242 gtk_file_filter_add_mime_type (filter, "application/x-gnumeric");
243 gtk_file_filter_add_mime_type (filter, "application/vnd.oasis.opendocument.spreadsheet");
244 gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (dialog), filter);
246 gtk_file_chooser_set_extra_widget (
247 GTK_FILE_CHOOSER (dialog), psppire_encoding_selector_new ("Auto", true));
249 filter = gtk_file_filter_new ();
250 gtk_file_filter_set_name (filter, _("All Files"));
251 gtk_file_filter_add_pattern (filter, "*");
252 gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (dialog), filter);
254 switch (gtk_dialog_run (GTK_DIALOG (dialog)))
256 case GTK_RESPONSE_ACCEPT:
257 file_name = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (dialog));
258 *encodingp = psppire_encoding_selector_get_encoding (
259 gtk_file_chooser_get_extra_widget (GTK_FILE_CHOOSER (dialog)));
266 gtk_widget_destroy (dialog);