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"
23 #include <gtk-contrib/psppire-sheet.h>
29 #include "data/data-in.h"
30 #include "data/data-out.h"
31 #include "data/format-guesser.h"
32 #include "data/casereader.h"
33 #include "data/gnumeric-reader.h"
34 #include "data/ods-reader.h"
35 #include "data/spreadsheet-reader.h"
36 #include "data/value-labels.h"
37 #include "language/data-io/data-parser.h"
38 #include "language/lexer/lexer.h"
39 #include "libpspp/assertion.h"
40 #include "libpspp/i18n.h"
41 #include "libpspp/line-reader.h"
42 #include "libpspp/message.h"
43 #include "ui/gui/checkbox-treeview.h"
44 #include "ui/gui/dialog-common.h"
45 #include "ui/gui/executor.h"
46 #include "ui/gui/helper.h"
47 #include "ui/gui/builder-wrapper.h"
48 #include "ui/gui/psppire-data-window.h"
49 #include "ui/gui/psppire-dialog.h"
50 #include "ui/gui/psppire-encoding-selector.h"
51 #include "ui/gui/psppire-empty-list-store.h"
52 #include "ui/gui/psppire-var-sheet.h"
53 #include "ui/gui/psppire-var-store.h"
54 #include "ui/gui/psppire-scanf.h"
55 #include "ui/syntax-gen.h"
58 #include "gl/intprops.h"
59 #include "gl/xalloc.h"
62 #define _(msgid) gettext (msgid)
63 #define N_(msgid) msgid
65 struct import_assistant;
68 static char *choose_file (GtkWindow *parent_window, gchar **encodingp);
73 /* Obtains the file to import from the user and initializes IA's
74 file substructure. PARENT_WINDOW must be the window to use
75 as the file chooser window's parent.
77 Returns true if successful, false if the file name could not
78 be obtained or the file could not be read. */
80 init_file (struct import_assistant *ia, GtkWindow *parent_window)
82 enum { MAX_LINE_LEN = 16384 }; /* Max length of an acceptable line. */
83 struct file *file = &ia->file;
84 struct spreadsheet_read_options opts;
87 file->file_name = choose_file (parent_window, &file->encoding);
88 if (file->file_name == NULL)
91 opts.sheet_name = NULL;
92 opts.cell_range = NULL;
95 opts.read_names = true;
99 if (ia->spreadsheet == NULL)
100 ia->spreadsheet = gnumeric_probe (file->file_name, false);
102 if (ia->spreadsheet == NULL)
103 ia->spreadsheet = ods_probe (file->file_name, false);
105 if (ia->spreadsheet == NULL)
108 struct line_reader *reader = line_reader_for_file (file->encoding, file->file_name, O_RDONLY);
111 msg (ME, _("Could not open `%s': %s"),
112 file->file_name, strerror (errno));
116 ds_init_empty (&input);
117 file->lines = xnmalloc (MAX_PREVIEW_LINES, sizeof *file->lines);
118 for (; file->line_cnt < MAX_PREVIEW_LINES; file->line_cnt++)
121 if (!line_reader_read (reader, &input, MAX_LINE_LEN + 1)
122 || ds_length (&input) > MAX_LINE_LEN)
124 if (line_reader_eof (reader))
126 else if (line_reader_error (reader))
127 msg (ME, _("Error reading `%s': %s"),
128 file->file_name, strerror (line_reader_error (reader)));
130 msg (ME, _("Failed to read `%s', because it contains a line "
131 "over %d bytes long and therefore appears not to be "
133 file->file_name, MAX_LINE_LEN);
134 line_reader_close (reader);
140 ds_init_cstr (&file->lines[file->line_cnt],
141 recode_string ("UTF-8", line_reader_get_encoding (reader),
142 ds_cstr (&input), ds_length (&input)));
146 if (file->line_cnt == 0)
148 msg (ME, _("`%s' is empty."), file->file_name);
149 line_reader_close (reader);
154 /* Estimate the number of lines in the file. */
155 if (file->line_cnt < MAX_PREVIEW_LINES)
156 file->total_lines = file->line_cnt;
160 off_t position = line_reader_tell (reader);
161 if (fstat (line_reader_fileno (reader), &s) == 0 && position > 0)
162 file->total_lines = (double) file->line_cnt / position * s.st_size;
164 file->total_lines = 0;
167 line_reader_close (reader);
173 /* Frees IA's file substructure. */
175 destroy_file (struct import_assistant *ia)
177 struct file *f = &ia->file;
182 for (i = 0; i < f->line_cnt; i++)
183 ds_destroy (&f->lines[i]);
187 g_free (f->file_name);
188 g_free (f->encoding);
191 /* Obtains the file to read from the user. If successful, returns the name of
192 the file and stores the user's chosen encoding for the file into *ENCODINGP.
193 The caller must free each of these strings with g_free().
195 On failure, stores a null pointer and stores NULL in *ENCODINGP.
197 PARENT_WINDOW must be the window to use as the file chooser window's
200 choose_file (GtkWindow *parent_window, gchar **encodingp)
203 GtkFileFilter *filter = NULL;
205 GtkWidget *dialog = gtk_file_chooser_dialog_new (_("Import Delimited Text Data"),
207 GTK_FILE_CHOOSER_ACTION_OPEN,
208 GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
209 GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT,
212 g_object_set (dialog, "local-only", FALSE, NULL);
214 filter = gtk_file_filter_new ();
215 gtk_file_filter_set_name (filter, _("Text files"));
216 gtk_file_filter_add_mime_type (filter, "text/*");
217 gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (dialog), filter);
219 filter = gtk_file_filter_new ();
220 gtk_file_filter_set_name (filter, _("Text (*.txt) Files"));
221 gtk_file_filter_add_pattern (filter, "*.txt");
222 gtk_file_filter_add_pattern (filter, "*.TXT");
223 gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (dialog), filter);
225 filter = gtk_file_filter_new ();
226 gtk_file_filter_set_name (filter, _("Plain Text (ASCII) Files"));
227 gtk_file_filter_add_mime_type (filter, "text/plain");
228 gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (dialog), filter);
230 filter = gtk_file_filter_new ();
231 gtk_file_filter_set_name (filter, _("Comma Separated Value Files"));
232 gtk_file_filter_add_mime_type (filter, "text/csv");
233 gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (dialog), filter);
235 /* I've never encountered one of these, but it's listed here:
236 http://www.iana.org/assignments/media-types/text/tab-separated-values */
237 filter = gtk_file_filter_new ();
238 gtk_file_filter_set_name (filter, _("Tab Separated Value Files"));
239 gtk_file_filter_add_mime_type (filter, "text/tab-separated-values");
240 gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (dialog), filter);
243 gtk_file_chooser_set_extra_widget (
244 GTK_FILE_CHOOSER (dialog), psppire_encoding_selector_new ("Auto", true));
246 filter = gtk_file_filter_new ();
247 gtk_file_filter_set_name (filter, _("All Files"));
248 gtk_file_filter_add_pattern (filter, "*");
249 gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (dialog), filter);
251 switch (gtk_dialog_run (GTK_DIALOG (dialog)))
253 case GTK_RESPONSE_ACCEPT:
254 file_name = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (dialog));
255 *encodingp = psppire_encoding_selector_get_encoding (
256 gtk_file_chooser_get_extra_widget (GTK_FILE_CHOOSER (dialog)));
263 gtk_widget_destroy (dialog);