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/dialog-common.h"
43 #include "ui/gui/executor.h"
44 #include "ui/gui/helper.h"
45 #include "ui/gui/builder-wrapper.h"
46 #include "ui/gui/psppire-data-window.h"
47 #include "ui/gui/psppire-dialog.h"
48 #include "ui/gui/psppire-encoding-selector.h"
49 #include "ui/gui/psppire-empty-list-store.h"
50 #include "ui/gui/psppire-var-sheet.h"
51 #include "ui/gui/psppire-scanf.h"
52 #include "ui/syntax-gen.h"
54 #include "gl/intprops.h"
55 #include "gl/xalloc.h"
58 #define _(msgid) gettext (msgid)
59 #define N_(msgid) msgid
61 struct import_assistant;
64 static char *choose_file (GtkWindow *parent_window, gchar **encodingp);
69 /* Obtains the file to import from the user and initializes IA's
70 file substructure. PARENT_WINDOW must be the window to use
71 as the file chooser window's parent.
73 Returns true if successful, false if the file name could not
74 be obtained or the file could not be read. */
76 init_file (struct import_assistant *ia, GtkWindow *parent_window)
78 enum { MAX_LINE_LEN = 16384 }; /* Max length of an acceptable line. */
79 struct file *file = &ia->file;
82 file->file_name = choose_file (parent_window, &file->encoding);
83 if (file->file_name == NULL)
86 if (ia->spreadsheet == NULL)
87 ia->spreadsheet = gnumeric_probe (file->file_name, false);
89 if (ia->spreadsheet == NULL)
90 ia->spreadsheet = ods_probe (file->file_name, false);
92 if (ia->spreadsheet == NULL)
95 struct line_reader *reader = line_reader_for_file (file->encoding, file->file_name, O_RDONLY);
98 msg_error (errno, _("Could not open `%s'"),
103 ds_init_empty (&input);
104 file->lines = xnmalloc (MAX_PREVIEW_LINES, sizeof *file->lines);
105 for (; file->line_cnt < MAX_PREVIEW_LINES; file->line_cnt++)
108 if (!line_reader_read (reader, &input, MAX_LINE_LEN + 1)
109 || ds_length (&input) > MAX_LINE_LEN)
111 if (line_reader_eof (reader))
113 else if (line_reader_error (reader))
114 msg (ME, _("Error reading `%s': %s"),
115 file->file_name, strerror (line_reader_error (reader)));
117 msg (ME, _("Failed to read `%s', because it contains a line "
118 "over %d bytes long and therefore appears not to be "
120 file->file_name, MAX_LINE_LEN);
121 line_reader_close (reader);
127 ds_init_cstr (&file->lines[file->line_cnt],
128 recode_string ("UTF-8", line_reader_get_encoding (reader),
129 ds_cstr (&input), ds_length (&input)));
133 if (file->line_cnt == 0)
135 msg (ME, _("`%s' is empty."), file->file_name);
136 line_reader_close (reader);
142 /* Estimate the number of lines in the file. */
143 if (file->line_cnt < MAX_PREVIEW_LINES)
145 file->total_lines = file->line_cnt;
146 file->total_is_exact = true;
151 off_t position = line_reader_tell (reader);
152 if (fstat (line_reader_fileno (reader), &s) == 0 && position > 0)
154 file->total_lines = (double) file->line_cnt / position * s.st_size;
155 file->total_is_exact = false;
159 file->total_lines = 0;
160 file->total_is_exact = true;
164 line_reader_close (reader);
170 /* Frees IA's file substructure. */
172 destroy_file (struct import_assistant *ia)
174 struct file *f = &ia->file;
179 for (i = 0; i < f->line_cnt; i++)
180 ds_destroy (&f->lines[i]);
184 g_free (f->file_name);
185 g_free (f->encoding);
188 /* Obtains the file to read from the user. If successful, returns the name of
189 the file and stores the user's chosen encoding for the file into *ENCODINGP.
190 The caller must free each of these strings with g_free().
192 On failure, stores a null pointer and stores NULL in *ENCODINGP.
194 PARENT_WINDOW must be the window to use as the file chooser window's
197 choose_file (GtkWindow *parent_window, gchar **encodingp)
200 GtkFileFilter *filter = NULL;
202 GtkWidget *dialog = gtk_file_chooser_dialog_new (_("Import Delimited Text Data"),
204 GTK_FILE_CHOOSER_ACTION_OPEN,
205 _("Cancel"), GTK_RESPONSE_CANCEL,
206 _("Open"), GTK_RESPONSE_ACCEPT,
209 g_object_set (dialog, "local-only", FALSE, NULL);
211 filter = gtk_file_filter_new ();
212 gtk_file_filter_set_name (filter, _("Text Files"));
213 gtk_file_filter_add_mime_type (filter, "text/*");
214 gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (dialog), filter);
216 filter = gtk_file_filter_new ();
217 gtk_file_filter_set_name (filter, _("Text (*.txt) Files"));
218 gtk_file_filter_add_pattern (filter, "*.txt");
219 gtk_file_filter_add_pattern (filter, "*.TXT");
220 gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (dialog), filter);
222 filter = gtk_file_filter_new ();
223 gtk_file_filter_set_name (filter, _("Plain Text (ASCII) Files"));
224 gtk_file_filter_add_mime_type (filter, "text/plain");
225 gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (dialog), filter);
227 filter = gtk_file_filter_new ();
228 gtk_file_filter_set_name (filter, _("Comma Separated Value Files"));
229 gtk_file_filter_add_mime_type (filter, "text/csv");
230 gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (dialog), filter);
232 /* I've never encountered one of these, but it's listed here:
233 http://www.iana.org/assignments/media-types/text/tab-separated-values */
234 filter = gtk_file_filter_new ();
235 gtk_file_filter_set_name (filter, _("Tab Separated Value Files"));
236 gtk_file_filter_add_mime_type (filter, "text/tab-separated-values");
237 gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (dialog), filter);
239 filter = gtk_file_filter_new ();
240 gtk_file_filter_set_name (filter, _("Gnumeric Spreadsheet Files"));
241 gtk_file_filter_add_mime_type (filter, "application/x-gnumeric");
242 gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (dialog), filter);
244 filter = gtk_file_filter_new ();
245 gtk_file_filter_set_name (filter, _("OpenDocument Spreadsheet Files"));
246 gtk_file_filter_add_mime_type (filter, "application/vnd.oasis.opendocument.spreadsheet");
247 gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (dialog), filter);
249 filter = gtk_file_filter_new ();
250 gtk_file_filter_set_name (filter, _("All Spreadsheet Files"));
251 gtk_file_filter_add_mime_type (filter, "application/x-gnumeric");
252 gtk_file_filter_add_mime_type (filter, "application/vnd.oasis.opendocument.spreadsheet");
253 gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (dialog), filter);
255 gtk_file_chooser_set_extra_widget (
256 GTK_FILE_CHOOSER (dialog), psppire_encoding_selector_new ("Auto", true));
258 filter = gtk_file_filter_new ();
259 gtk_file_filter_set_name (filter, _("All Files"));
260 gtk_file_filter_add_pattern (filter, "*");
261 gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (dialog), filter);
263 switch (gtk_dialog_run (GTK_DIALOG (dialog)))
265 case GTK_RESPONSE_ACCEPT:
266 file_name = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (dialog));
267 *encodingp = psppire_encoding_selector_get_encoding (
268 gtk_file_chooser_get_extra_widget (GTK_FILE_CHOOSER (dialog)));
275 gtk_widget_destroy (dialog);