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"
56 #include "gl/intprops.h"
57 #include "gl/xalloc.h"
60 #define _(msgid) gettext (msgid)
61 #define N_(msgid) msgid
63 struct import_assistant;
66 static char *choose_file (GtkWindow *parent_window, gchar **encodingp);
71 /* Obtains the file to import from the user and initializes IA's
72 file substructure. PARENT_WINDOW must be the window to use
73 as the file chooser window's parent.
75 Returns true if successful, false if the file name could not
76 be obtained or the file could not be read. */
78 init_file (struct import_assistant *ia, GtkWindow *parent_window)
80 enum { MAX_LINE_LEN = 16384 }; /* Max length of an acceptable line. */
81 struct file *file = &ia->file;
84 file->file_name = choose_file (parent_window, &file->encoding);
85 if (file->file_name == NULL)
88 if (ia->spreadsheet == NULL)
89 ia->spreadsheet = gnumeric_probe (file->file_name, false);
91 if (ia->spreadsheet == NULL)
92 ia->spreadsheet = ods_probe (file->file_name, false);
94 if (ia->spreadsheet == NULL)
97 struct line_reader *reader = line_reader_for_file (file->encoding, file->file_name, O_RDONLY);
100 msg (ME, _("Could not open `%s': %s"),
101 file->file_name, strerror (errno));
105 ds_init_empty (&input);
106 file->lines = xnmalloc (MAX_PREVIEW_LINES, sizeof *file->lines);
107 for (; file->line_cnt < MAX_PREVIEW_LINES; file->line_cnt++)
110 if (!line_reader_read (reader, &input, MAX_LINE_LEN + 1)
111 || ds_length (&input) > MAX_LINE_LEN)
113 if (line_reader_eof (reader))
115 else if (line_reader_error (reader))
116 msg (ME, _("Error reading `%s': %s"),
117 file->file_name, strerror (line_reader_error (reader)));
119 msg (ME, _("Failed to read `%s', because it contains a line "
120 "over %d bytes long and therefore appears not to be "
122 file->file_name, MAX_LINE_LEN);
123 line_reader_close (reader);
129 ds_init_cstr (&file->lines[file->line_cnt],
130 recode_string ("UTF-8", line_reader_get_encoding (reader),
131 ds_cstr (&input), ds_length (&input)));
135 if (file->line_cnt == 0)
137 msg (ME, _("`%s' is empty."), file->file_name);
138 line_reader_close (reader);
143 /* Estimate the number of lines in the file. */
144 if (file->line_cnt < MAX_PREVIEW_LINES)
145 file->total_lines = file->line_cnt;
149 off_t position = line_reader_tell (reader);
150 if (fstat (line_reader_fileno (reader), &s) == 0 && position > 0)
151 file->total_lines = (double) file->line_cnt / position * s.st_size;
153 file->total_lines = 0;
156 line_reader_close (reader);
162 /* Frees IA's file substructure. */
164 destroy_file (struct import_assistant *ia)
166 struct file *f = &ia->file;
171 for (i = 0; i < f->line_cnt; i++)
172 ds_destroy (&f->lines[i]);
176 g_free (f->file_name);
177 g_free (f->encoding);
180 /* Obtains the file to read from the user. If successful, returns the name of
181 the file and stores the user's chosen encoding for the file into *ENCODINGP.
182 The caller must free each of these strings with g_free().
184 On failure, stores a null pointer and stores NULL in *ENCODINGP.
186 PARENT_WINDOW must be the window to use as the file chooser window's
189 choose_file (GtkWindow *parent_window, gchar **encodingp)
192 GtkFileFilter *filter = NULL;
194 GtkWidget *dialog = gtk_file_chooser_dialog_new (_("Import Delimited Text Data"),
196 GTK_FILE_CHOOSER_ACTION_OPEN,
197 GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
198 GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT,
201 g_object_set (dialog, "local-only", FALSE, NULL);
203 filter = gtk_file_filter_new ();
204 gtk_file_filter_set_name (filter, _("Text Files"));
205 gtk_file_filter_add_mime_type (filter, "text/*");
206 gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (dialog), filter);
208 filter = gtk_file_filter_new ();
209 gtk_file_filter_set_name (filter, _("Text (*.txt) Files"));
210 gtk_file_filter_add_pattern (filter, "*.txt");
211 gtk_file_filter_add_pattern (filter, "*.TXT");
212 gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (dialog), filter);
214 filter = gtk_file_filter_new ();
215 gtk_file_filter_set_name (filter, _("Plain Text (ASCII) Files"));
216 gtk_file_filter_add_mime_type (filter, "text/plain");
217 gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (dialog), filter);
219 filter = gtk_file_filter_new ();
220 gtk_file_filter_set_name (filter, _("Comma Separated Value Files"));
221 gtk_file_filter_add_mime_type (filter, "text/csv");
222 gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (dialog), filter);
224 /* I've never encountered one of these, but it's listed here:
225 http://www.iana.org/assignments/media-types/text/tab-separated-values */
226 filter = gtk_file_filter_new ();
227 gtk_file_filter_set_name (filter, _("Tab Separated Value Files"));
228 gtk_file_filter_add_mime_type (filter, "text/tab-separated-values");
229 gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (dialog), filter);
231 filter = gtk_file_filter_new ();
232 gtk_file_filter_set_name (filter, _("Gnumeric Spreadsheet Files"));
233 gtk_file_filter_add_mime_type (filter, "application/x-gnumeric");
234 gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (dialog), filter);
236 filter = gtk_file_filter_new ();
237 gtk_file_filter_set_name (filter, _("OpenDocument Spreadsheet Files"));
238 gtk_file_filter_add_mime_type (filter, "application/vnd.oasis.opendocument.spreadsheet");
239 gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (dialog), filter);
241 filter = gtk_file_filter_new ();
242 gtk_file_filter_set_name (filter, _("All Spreadsheet Files"));
243 gtk_file_filter_add_mime_type (filter, "application/x-gnumeric");
244 gtk_file_filter_add_mime_type (filter, "application/vnd.oasis.opendocument.spreadsheet");
245 gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (dialog), filter);
247 gtk_file_chooser_set_extra_widget (
248 GTK_FILE_CHOOSER (dialog), psppire_encoding_selector_new ("Auto", true));
250 filter = gtk_file_filter_new ();
251 gtk_file_filter_set_name (filter, _("All Files"));
252 gtk_file_filter_add_pattern (filter, "*");
253 gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (dialog), filter);
255 switch (gtk_dialog_run (GTK_DIALOG (dialog)))
257 case GTK_RESPONSE_ACCEPT:
258 file_name = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (dialog));
259 *encodingp = psppire_encoding_selector_get_encoding (
260 gtk_file_chooser_get_extra_widget (GTK_FILE_CHOOSER (dialog)));
267 gtk_widget_destroy (dialog);