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_info sri;
85 struct spreadsheet_read_options opts;
88 file->file_name = choose_file (parent_window, &file->encoding);
89 if (file->file_name == NULL)
92 opts.sheet_name = NULL;
93 opts.cell_range = NULL;
96 sri.read_names = true;
99 printf ("%s:%d %p\n", __FILE__, __LINE__, ia->spreadsheet);
101 if (ia->spreadsheet == NULL)
102 ia->spreadsheet = gnumeric_probe (file->file_name, false);
104 printf ("%s:%d %p\n", __FILE__, __LINE__, ia->spreadsheet);
106 if (ia->spreadsheet == NULL)
107 ia->spreadsheet = ods_probe (file->file_name, false);
109 printf ("%s:%d %p\n", __FILE__, __LINE__, ia->spreadsheet);
111 if (ia->spreadsheet == NULL)
114 struct line_reader *reader = line_reader_for_file (file->encoding, file->file_name, O_RDONLY);
117 msg (ME, _("Could not open `%s': %s"),
118 file->file_name, strerror (errno));
122 ds_init_empty (&input);
123 file->lines = xnmalloc (MAX_PREVIEW_LINES, sizeof *file->lines);
124 for (; file->line_cnt < MAX_PREVIEW_LINES; file->line_cnt++)
127 if (!line_reader_read (reader, &input, MAX_LINE_LEN + 1)
128 || ds_length (&input) > MAX_LINE_LEN)
130 if (line_reader_eof (reader))
132 else if (line_reader_error (reader))
133 msg (ME, _("Error reading `%s': %s"),
134 file->file_name, strerror (line_reader_error (reader)));
136 msg (ME, _("Failed to read `%s', because it contains a line "
137 "over %d bytes long and therefore appears not to be "
139 file->file_name, MAX_LINE_LEN);
140 line_reader_close (reader);
146 ds_init_cstr (&file->lines[file->line_cnt],
147 recode_string ("UTF-8", line_reader_get_encoding (reader),
148 ds_cstr (&input), ds_length (&input)));
152 if (file->line_cnt == 0)
154 msg (ME, _("`%s' is empty."), file->file_name);
155 line_reader_close (reader);
160 /* Estimate the number of lines in the file. */
161 if (file->line_cnt < MAX_PREVIEW_LINES)
162 file->total_lines = file->line_cnt;
166 off_t position = line_reader_tell (reader);
167 if (fstat (line_reader_fileno (reader), &s) == 0 && position > 0)
168 file->total_lines = (double) file->line_cnt / position * s.st_size;
170 file->total_lines = 0;
173 line_reader_close (reader);
179 /* Frees IA's file substructure. */
181 destroy_file (struct import_assistant *ia)
183 struct file *f = &ia->file;
188 for (i = 0; i < f->line_cnt; i++)
189 ds_destroy (&f->lines[i]);
193 g_free (f->file_name);
194 g_free (f->encoding);
197 /* Obtains the file to read from the user. If successful, returns the name of
198 the file and stores the user's chosen encoding for the file into *ENCODINGP.
199 The caller must free each of these strings with g_free().
201 On failure, stores a null pointer and stores NULL in *ENCODINGP.
203 PARENT_WINDOW must be the window to use as the file chooser window's
206 choose_file (GtkWindow *parent_window, gchar **encodingp)
209 GtkFileFilter *filter = NULL;
211 GtkWidget *dialog = gtk_file_chooser_dialog_new (_("Import Delimited Text Data"),
213 GTK_FILE_CHOOSER_ACTION_OPEN,
214 GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
215 GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT,
218 g_object_set (dialog, "local-only", FALSE, NULL);
220 filter = gtk_file_filter_new ();
221 gtk_file_filter_set_name (filter, _("Text files"));
222 gtk_file_filter_add_mime_type (filter, "text/*");
223 gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (dialog), filter);
225 filter = gtk_file_filter_new ();
226 gtk_file_filter_set_name (filter, _("Text (*.txt) Files"));
227 gtk_file_filter_add_pattern (filter, "*.txt");
228 gtk_file_filter_add_pattern (filter, "*.TXT");
229 gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (dialog), filter);
231 filter = gtk_file_filter_new ();
232 gtk_file_filter_set_name (filter, _("Plain Text (ASCII) Files"));
233 gtk_file_filter_add_mime_type (filter, "text/plain");
234 gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (dialog), filter);
236 filter = gtk_file_filter_new ();
237 gtk_file_filter_set_name (filter, _("Comma Separated Value Files"));
238 gtk_file_filter_add_mime_type (filter, "text/csv");
239 gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (dialog), filter);
241 /* I've never encountered one of these, but it's listed here:
242 http://www.iana.org/assignments/media-types/text/tab-separated-values */
243 filter = gtk_file_filter_new ();
244 gtk_file_filter_set_name (filter, _("Tab Separated Value Files"));
245 gtk_file_filter_add_mime_type (filter, "text/tab-separated-values");
246 gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (dialog), filter);
248 filter = gtk_file_filter_new ();
249 gtk_file_filter_set_name (filter, _("Gnumeric Spreadsheet Files"));
250 gtk_file_filter_add_mime_type (filter, "application/x-gnumeric");
251 gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (dialog), filter);
253 filter = gtk_file_filter_new ();
254 gtk_file_filter_set_name (filter, _("OpenOffice.Org Spreadsheet Files"));
255 gtk_file_filter_add_mime_type (filter, "application/vnd.oasis.opendocument.spreadsheet");
256 gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (dialog), filter);
258 filter = gtk_file_filter_new ();
259 gtk_file_filter_set_name (filter, _("All Spreadsheet Files"));
260 gtk_file_filter_add_mime_type (filter, "application/x-gnumeric");
261 gtk_file_filter_add_mime_type (filter, "application/vnd.oasis.opendocument.spreadsheet");
262 gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (dialog), filter);
265 gtk_file_chooser_set_extra_widget (
266 GTK_FILE_CHOOSER (dialog), psppire_encoding_selector_new ("Auto", true));
268 filter = gtk_file_filter_new ();
269 gtk_file_filter_set_name (filter, _("All Files"));
270 gtk_file_filter_add_pattern (filter, "*");
271 gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (dialog), filter);
273 switch (gtk_dialog_run (GTK_DIALOG (dialog)))
275 case GTK_RESPONSE_ACCEPT:
276 file_name = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (dialog));
277 *encodingp = psppire_encoding_selector_get_encoding (
278 gtk_file_chooser_get_extra_widget (GTK_FILE_CHOOSER (dialog)));
285 gtk_widget_destroy (dialog);