X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=src%2Fui%2Fgui%2Ftext-data-import-dialog.c;h=f8fa9c3a4623e1d43d688517991e098407675926;hb=deea66e1be0c3e783b159e1605a697d9e75861aa;hp=547105fe455497269c928309f5f5b4971bb257bd;hpb=02c89b93ff0b5942e66fdfbb7562641a0ff29d2c;p=pspp diff --git a/src/ui/gui/text-data-import-dialog.c b/src/ui/gui/text-data-import-dialog.c index 547105fe45..f8fa9c3a46 100644 --- a/src/ui/gui/text-data-import-dialog.c +++ b/src/ui/gui/text-data-import-dialog.c @@ -19,6 +19,7 @@ #include "ui/gui/text-data-import-dialog.h" #include +#include #include #include #include @@ -33,6 +34,7 @@ #include "language/lexer/lexer.h" #include "libpspp/assertion.h" #include "libpspp/i18n.h" +#include "libpspp/line-reader.h" #include "libpspp/message.h" #include "ui/gui/checkbox-treeview.h" #include "ui/gui/dialog-common.h" @@ -41,39 +43,28 @@ #include "ui/gui/builder-wrapper.h" #include "ui/gui/psppire-data-window.h" #include "ui/gui/psppire-dialog.h" +#include "ui/gui/psppire-encoding-selector.h" +#include "ui/gui/psppire-empty-list-store.h" #include "ui/gui/psppire-var-sheet.h" #include "ui/gui/psppire-var-store.h" #include "ui/gui/psppire-scanf.h" #include "ui/syntax-gen.h" #include "gl/error.h" +#include "gl/intprops.h" #include "gl/xalloc.h" #include "gettext.h" #define _(msgid) gettext (msgid) #define N_(msgid) msgid - -/* TextImportModel, a GtkTreeModel used by the text data import - dialog. */ -enum - { - TEXT_IMPORT_MODEL_COLUMN_LINE_NUMBER, /* 1-based line number in file */ - TEXT_IMPORT_MODEL_COLUMN_LINE, /* The line from the file. */ - }; -typedef struct TextImportModel TextImportModel; -typedef struct TextImportModelClass TextImportModelClass; - -TextImportModel *text_import_model_new (struct string *lines, size_t line_cnt, - size_t first_line); -gint text_import_model_iter_to_row (const GtkTreeIter *); - struct import_assistant; /* The file to be imported. */ struct file { char *file_name; /* File name. */ + gchar *encoding; /* Encoding. */ unsigned long int total_lines; /* Number of lines in file. */ bool total_is_exact; /* Is total_lines exact (or an estimate)? */ @@ -226,7 +217,6 @@ static GtkTreeViewColumn *make_data_column (struct import_assistant *, gint column_idx); static GtkTreeView *create_data_tree_view (bool input, GtkContainer *parent, struct import_assistant *); -static char *escape_underscores (const char *in); static void push_watch_cursor (struct import_assistant *); static void pop_watch_cursor (struct import_assistant *); @@ -372,6 +362,8 @@ generate_syntax (const struct import_assistant *ia) " /TYPE=TXT\n" " /FILE=%sq\n", ia->file.file_name); + if (ia->file.encoding && strcmp (ia->file.encoding, "Auto")) + syntax_gen_pspp (&s, " /ENCODING=%sq\n", ia->file.encoding); if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON ( ia->intro.n_cases_button))) ds_put_format (&s, " /IMPORTCASES=FIRST %d\n", @@ -427,7 +419,7 @@ generate_syntax (const struct import_assistant *ia) /* Choosing a file and reading it. */ -static char *choose_file (GtkWindow *parent_window); +static char *choose_file (GtkWindow *parent_window, gchar **encodingp); /* Obtains the file to import from the user and initializes IA's file substructure. PARENT_WINDOW must be the window to use @@ -441,50 +433,55 @@ init_file (struct import_assistant *ia, GtkWindow *parent_window) struct file *file = &ia->file; enum { MAX_PREVIEW_LINES = 1000 }; /* Max number of lines to read. */ enum { MAX_LINE_LEN = 16384 }; /* Max length of an acceptable line. */ - FILE *stream; + struct line_reader *reader; + struct string input; - file->file_name = choose_file (parent_window); + file->file_name = choose_file (parent_window, &file->encoding); if (file->file_name == NULL) return false; - stream = fopen (file->file_name, "r"); - if (stream == NULL) + reader = line_reader_for_file (file->encoding, file->file_name, O_RDONLY); + if (reader == NULL) { msg (ME, _("Could not open `%s': %s"), file->file_name, strerror (errno)); return false; } + ds_init_empty (&input); file->lines = xnmalloc (MAX_PREVIEW_LINES, sizeof *file->lines); for (; file->line_cnt < MAX_PREVIEW_LINES; file->line_cnt++) { - struct string *line = &file->lines[file->line_cnt]; - - ds_init_empty (line); - if (!ds_read_line (line, stream, MAX_LINE_LEN)) + ds_clear (&input); + if (!line_reader_read (reader, &input, MAX_LINE_LEN + 1) + || ds_length (&input) > MAX_LINE_LEN) { - if (feof (stream)) + if (line_reader_eof (reader)) break; - else if (ferror (stream)) + else if (line_reader_error (reader)) msg (ME, _("Error reading `%s': %s"), - file->file_name, strerror (errno)); + file->file_name, strerror (line_reader_error (reader))); else msg (ME, _("Failed to read `%s', because it contains a line " "over %d bytes long and therefore appears not to be " "a text file."), file->file_name, MAX_LINE_LEN); - fclose (stream); + line_reader_close (reader); destroy_file (ia); + ds_destroy (&input); return false; } - ds_chomp_byte (line, '\n'); - ds_chomp_byte (line, '\r'); + + ds_init_cstr (&file->lines[file->line_cnt], + recode_string ("UTF-8", line_reader_get_encoding (reader), + ds_cstr (&input), ds_length (&input))); } + ds_destroy (&input); if (file->line_cnt == 0) { msg (ME, _("`%s' is empty."), file->file_name); - fclose (stream); + line_reader_close (reader); destroy_file (ia); return false; } @@ -495,13 +492,15 @@ init_file (struct import_assistant *ia, GtkWindow *parent_window) else { struct stat s; - off_t position = ftello (stream); - if (fstat (fileno (stream), &s) == 0 && position > 0) + off_t position = line_reader_tell (reader); + if (fstat (line_reader_fileno (reader), &s) == 0 && position > 0) file->total_lines = (double) file->line_cnt / position * s.st_size; else file->total_lines = 0; } + line_reader_close (reader); + return true; } @@ -516,16 +515,22 @@ destroy_file (struct import_assistant *ia) ds_destroy (&f->lines[i]); free (f->lines); g_free (f->file_name); + g_free (f->encoding); } -/* Obtains the file to read from the user and returns the name of - the file as a string that must be freed with g_free if - successful, otherwise a null pointer. PARENT_WINDOW must be - the window to use as the file chooser window's parent. */ +/* Obtains the file to read from the user. If successful, returns the name of + the file and stores the user's chosen encoding for the file into *ENCODINGP. + The caller must free each of these strings with g_free(). + + On failure, stores a null pointer and stores NULL in *ENCODINGP. + + PARENT_WINDOW must be the window to use as the file chooser window's + parent. */ static char * -choose_file (GtkWindow *parent_window) +choose_file (GtkWindow *parent_window, gchar **encodingp) { char *file_name; + GtkFileFilter *filter = NULL; GtkWidget *dialog = gtk_file_chooser_dialog_new (_("Import Delimited Text Data"), parent_window, @@ -536,13 +541,52 @@ choose_file (GtkWindow *parent_window) g_object_set (dialog, "local-only", FALSE, NULL); + filter = gtk_file_filter_new (); + gtk_file_filter_set_name (filter, _("Text files")); + gtk_file_filter_add_mime_type (filter, "text/*"); + gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (dialog), filter); + + filter = gtk_file_filter_new (); + gtk_file_filter_set_name (filter, _("Text (*.txt) Files")); + gtk_file_filter_add_pattern (filter, "*.txt"); + gtk_file_filter_add_pattern (filter, "*.TXT"); + gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (dialog), filter); + + filter = gtk_file_filter_new (); + gtk_file_filter_set_name (filter, _("Plain Text (ASCII) Files")); + gtk_file_filter_add_mime_type (filter, "text/plain"); + gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (dialog), filter); + + filter = gtk_file_filter_new (); + gtk_file_filter_set_name (filter, _("Comma Separated Value Files")); + gtk_file_filter_add_mime_type (filter, "text/csv"); + gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (dialog), filter); + + /* I've never encountered one of these, but it's listed here: + http://www.iana.org/assignments/media-types/text/tab-separated-values */ + filter = gtk_file_filter_new (); + gtk_file_filter_set_name (filter, _("Tab Separated Value Files")); + gtk_file_filter_add_mime_type (filter, "text/tab-separated-values"); + gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (dialog), filter); + + gtk_file_chooser_set_extra_widget ( + GTK_FILE_CHOOSER (dialog), psppire_encoding_selector_new ("Auto", true)); + + filter = gtk_file_filter_new (); + gtk_file_filter_set_name (filter, _("All Files")); + gtk_file_filter_add_pattern (filter, "*"); + gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (dialog), filter); + switch (gtk_dialog_run (GTK_DIALOG (dialog))) { case GTK_RESPONSE_ACCEPT: file_name = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (dialog)); + *encodingp = psppire_encoding_selector_get_encoding ( + gtk_file_chooser_get_extra_widget (GTK_FILE_CHOOSER (dialog))); break; default: file_name = NULL; + *encodingp = NULL; break; } gtk_widget_destroy (dialog); @@ -864,6 +908,23 @@ reset_first_line_page (struct import_assistant *ia) set_first_line (ia); } +static void +render_line (GtkTreeViewColumn *tree_column, + GtkCellRenderer *cell, + GtkTreeModel *tree_model, + GtkTreeIter *iter, + gpointer data) +{ + gint row = empty_list_store_iter_to_row (iter); + struct string *lines; + + lines = g_object_get_data (G_OBJECT (tree_model), "lines"); + g_return_if_fail (lines != NULL); + + g_object_set (cell, "text", ds_cstr (&lines[row]), NULL); +} + + /* Creates and returns a tree view that contains each of the lines in IA's file as a row. */ static GtkTreeView * @@ -878,12 +939,10 @@ create_lines_tree_view (GtkContainer *parent, struct import_assistant *ia) make_tree_view (ia, 0, &tree_view); - column = gtk_tree_view_column_new_with_attributes - ( - title, ia->asst.fixed_renderer, - "text", TEXT_IMPORT_MODEL_COLUMN_LINE, - (void *) NULL - ); + column = gtk_tree_view_column_new_with_attributes ( + title, ia->asst.fixed_renderer, (void *) NULL); + gtk_tree_view_column_set_cell_data_func (column, ia->asst.fixed_renderer, + render_line, NULL, NULL); gtk_tree_view_column_set_sizing (column, GTK_TREE_VIEW_COLUMN_FIXED); max_line_length = 0; @@ -1009,15 +1068,15 @@ struct separator /* All the separators in the dialog box. */ static const struct separator separators[] = { - {N_("space"), ' '}, - {N_("tab"), '\t'}, - {N_("bang"), '!'}, - {N_("colon"), ':'}, - {N_("comma"), ','}, - {N_("hyphen"), '-'}, - {N_("pipe"), '|'}, - {N_("semicolon"), ';'}, - {N_("slash"), '/'}, + {"space", ' '}, + {"tab", '\t'}, + {"bang", '!'}, + {"colon", ':'}, + {"comma", ','}, + {"hyphen", '-'}, + {"pipe", '|'}, + {"semicolon", ';'}, + {"slash", '/'}, }; #define SEPARATOR_CNT (sizeof separators / sizeof *separators) @@ -1042,6 +1101,7 @@ set_quote_list (GtkComboBoxEntry *cb) } gtk_combo_box_set_model (GTK_COMBO_BOX (cb), GTK_TREE_MODEL (list)); + g_object_unref (list); gtk_combo_box_entry_set_text_column (cb, 0); } @@ -1077,7 +1137,7 @@ init_separators_page (struct import_assistant *ia) g_signal_connect (p->custom_cb, "toggled", G_CALLBACK (on_separators_custom_cb_toggle), ia); for (i = 0; i < SEPARATOR_CNT; i++) - g_signal_connect (get_widget_assert (builder, gettext(separators[i].name)), + g_signal_connect (get_widget_assert (builder, separators[i].name), "toggled", G_CALLBACK (on_separator_toggle), ia); g_signal_connect (p->escape_cb, "toggled", G_CALLBACK (on_separator_toggle), ia); @@ -1503,7 +1563,7 @@ render_input_cell (GtkTreeViewColumn *tree_column, GtkCellRenderer *cell, column = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (tree_column), "column-number")); - row = text_import_model_iter_to_row (iter) + ia->first_line.skip_lines; + row = empty_list_store_iter_to_row (iter) + ia->first_line.skip_lines; field = ia->separators.columns[column].contents[row]; if (field.string != NULL) { @@ -1572,7 +1632,7 @@ destroy_formats_page (struct import_assistant *ia) if (p->psppire_dict != NULL) { - /* This destroys p->dict also. */ + dict_destroy (p->psppire_dict->dict); g_object_unref (p->psppire_dict); } clear_modified_vars (ia); @@ -1771,7 +1831,7 @@ parse_field (struct import_assistant *ia, { char *error; - error = data_in (field, C_ENCODING, in->type, &val, var_get_width (var), + error = data_in (field, "UTF-8", in->type, &val, var_get_width (var), dict_get_encoding (ia->formats.dict)); if (error != NULL) { @@ -1817,7 +1877,7 @@ render_output_cell (GtkTreeViewColumn *tree_column, bool ok; ok = parse_field (ia, - (text_import_model_iter_to_row (iter) + (empty_list_store_iter_to_row (iter) + ia->first_line.skip_lines), GPOINTER_TO_INT (g_object_get_data (G_OBJECT (tree_column), "column-number")), @@ -1901,7 +1961,7 @@ get_tooltip_location (GtkWidget *widget, gint wx, gint wy, if (!ok) return FALSE; - *row = text_import_model_iter_to_row (&iter) + ia->first_line.skip_lines; + *row = empty_list_store_iter_to_row (&iter) + ia->first_line.skip_lines; return TRUE; } @@ -1913,14 +1973,34 @@ make_tree_view (const struct import_assistant *ia, GtkTreeModel *model; *tree_view = GTK_TREE_VIEW (gtk_tree_view_new ()); - model = GTK_TREE_MODEL (text_import_model_new ( - ia->file.lines + first_line, - ia->file.line_cnt - first_line, first_line)); + model = GTK_TREE_MODEL (psppire_empty_list_store_new ( + ia->file.line_cnt - first_line)); + g_object_set_data (G_OBJECT (model), "lines", ia->file.lines + first_line); + g_object_set_data (G_OBJECT (model), "first-line", + GINT_TO_POINTER (first_line)); gtk_tree_view_set_model (*tree_view, model); + g_object_unref (model); add_line_number_column (ia, *tree_view); } +static void +render_line_number (GtkTreeViewColumn *tree_column, + GtkCellRenderer *cell, + GtkTreeModel *tree_model, + GtkTreeIter *iter, + gpointer data) +{ + gint row = empty_list_store_iter_to_row (iter); + char s[INT_BUFSIZE_BOUND (int)]; + int first_line; + + first_line = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (tree_model), + "first-line")); + sprintf (s, "%d", first_line + row); + g_object_set (cell, "text", s, NULL); +} + static void add_line_number_column (const struct import_assistant *ia, GtkTreeView *treeview) @@ -1928,12 +2008,13 @@ add_line_number_column (const struct import_assistant *ia, GtkTreeViewColumn *column; column = gtk_tree_view_column_new_with_attributes ( - _("Line"), ia->asst.prop_renderer, - "text", TEXT_IMPORT_MODEL_COLUMN_LINE_NUMBER, - (void *) NULL); + _("Line"), ia->asst.prop_renderer, (void *) NULL); gtk_tree_view_column_set_sizing (column, GTK_TREE_VIEW_COLUMN_FIXED); gtk_tree_view_column_set_fixed_width ( column, get_monospace_width (treeview, ia->asst.prop_renderer, 5)); + gtk_tree_view_column_set_resizable (column, TRUE); + gtk_tree_view_column_set_cell_data_func (column, ia->asst.prop_renderer, + render_line_number, NULL, NULL); gtk_tree_view_append_column (treeview, column); } @@ -2032,290 +2113,6 @@ create_data_tree_view (bool input, GtkContainer *parent, return tree_view; } -static char * -escape_underscores (const char *in) -{ - char *out = xmalloc (2 * strlen (in) + 1); - char *p; - - p = out; - for (; *in != '\0'; in++) - { - if (*in == '_') - *p++ = '_'; - *p++ = *in; - } - *p = '\0'; - - return out; -} - -/* TextImportModel, a GtkTreeModel implementation used by some - pages of the assistant. */ - -#define G_TYPE_TEXT_IMPORT_MODEL (text_import_model_get_type ()) -#define TEXT_IMPORT_MODEL(object) (G_TYPE_CHECK_INSTANCE_CAST ((object), G_TYPE_TEXT_IMPORT_MODEL, TextImportModel)) -#define TEXT_IMPORT_MODEL_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), G_TYPE_TEXT_IMPORT_MODEL, TextImportModelClass)) -#define IS_TEXT_IMPORT_MODEL(object) (G_TYPE_CHECK_INSTANCE_TYPE ((object), G_TYPE_TEXT_IMPORT_MODEL)) -#define IS_TEXT_IMPORT_MODEL_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), G_TYPE_TEXT_IMPORT_MODEL)) -#define TEXT_IMPORT_MODEL_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), G_TYPE_TEXT_IMPORT_MODEL, TextImportModelClass)) - -/* Random number used in 'stamp' member of GtkTreeIter. */ -#define TREE_MODEL_STAMP 0x7efd67d3 - -struct TextImportModel -{ - GObject parent; - struct string *lines; - size_t line_cnt; - size_t first_line; -}; - -struct TextImportModelClass -{ - GObjectClass parent_class; -}; - -GType text_import_model_get_type (void); -static void text_import_model_tree_model_init (gpointer iface, gpointer data); - -GType -text_import_model_get_type (void) -{ - static GType object_type = 0; - - if (!object_type) - { - static const GTypeInfo object_info = { - sizeof (TextImportModelClass), - (GBaseInitFunc) NULL, - (GBaseFinalizeFunc) NULL, - NULL, /* class_init */ - NULL, /* class_finalize */ - NULL, /* class_data */ - sizeof (TextImportModel), - 0, /* n_preallocs */ - NULL, /* instance_init */ - }; - - static const GInterfaceInfo tree_model_info = { - text_import_model_tree_model_init, - NULL, - NULL - }; - - object_type = g_type_register_static (G_TYPE_OBJECT, - "TextImportModel", - &object_info, 0); - - g_type_add_interface_static (object_type, GTK_TYPE_TREE_MODEL, - &tree_model_info); - - - } - - return object_type; -} - - -/* Creates and returns a new TextImportModel that contains the - LINE_CNT lines in LINES. The lines before FIRST_LINE in LINES - are not part of the model, but they are included in the line - numbers in the TEXT_IMPORT_MODEL_COLUMN_LINE_NUMBER column. - - The caller retains responsibility for freeing LINES and must - ensure that its lifetime and that of the strings that it - contains exceeds that of the TextImportModel. */ -TextImportModel * -text_import_model_new (struct string *lines, size_t line_cnt, - size_t first_line) -{ - TextImportModel *new_text_import_model - = g_object_new (G_TYPE_TEXT_IMPORT_MODEL, NULL); - new_text_import_model->lines = lines; - new_text_import_model->line_cnt = line_cnt; - new_text_import_model->first_line = first_line; - return new_text_import_model; -} - - -static gboolean -tree_model_iter_has_child (GtkTreeModel *tree_model, - GtkTreeIter *iter) -{ - return FALSE; -} - -static gboolean -tree_model_iter_parent (GtkTreeModel *tree_model, - GtkTreeIter *iter, - GtkTreeIter *child) -{ - return TRUE; -} - -static GtkTreeModelFlags -tree_model_get_flags (GtkTreeModel *model) -{ - g_return_val_if_fail (IS_TEXT_IMPORT_MODEL (model), (GtkTreeModelFlags) 0); - - return GTK_TREE_MODEL_LIST_ONLY | GTK_TREE_MODEL_ITERS_PERSIST; -} - - -static gint -tree_model_n_columns (GtkTreeModel *model) -{ - return 2; -} - -static GType -tree_model_column_type (GtkTreeModel *model, gint index) -{ - return (index == TEXT_IMPORT_MODEL_COLUMN_LINE_NUMBER ? G_TYPE_INT - : index == TEXT_IMPORT_MODEL_COLUMN_LINE ? G_TYPE_STRING - : -1); -} - -static gboolean -init_iter (TextImportModel *list, gint idx, GtkTreeIter *iter) -{ - if (idx < 0 || idx >= list->line_cnt) - { - iter->stamp = 0; - iter->user_data = GINT_TO_POINTER (-1); - return FALSE; - } - else - { - iter->stamp = TREE_MODEL_STAMP; - iter->user_data = GINT_TO_POINTER (idx); - return TRUE; - } -} - -static gboolean -tree_model_get_iter (GtkTreeModel *model, GtkTreeIter *iter, GtkTreePath *path) -{ - gint *indices, depth; - - TextImportModel *list = TEXT_IMPORT_MODEL (model); - - g_return_val_if_fail (path, FALSE); - - indices = gtk_tree_path_get_indices (path); - depth = gtk_tree_path_get_depth (path); - - g_return_val_if_fail (depth == 1, FALSE); - - return init_iter (list, indices[0], iter); -} - - -static gboolean -tree_model_iter_next (GtkTreeModel *model, GtkTreeIter *iter) -{ - TextImportModel *list = TEXT_IMPORT_MODEL (model); - gint idx; - - assert (iter->stamp == TREE_MODEL_STAMP); - - idx = GPOINTER_TO_INT (iter->user_data); - return init_iter (list, idx == -1 ? -1 : idx + 1, iter); -} - -static GtkTreePath * -tree_model_get_path (GtkTreeModel *model, GtkTreeIter *iter) -{ - GtkTreePath *path; - - g_return_val_if_fail (iter->stamp == TREE_MODEL_STAMP, FALSE); - - path = gtk_tree_path_new (); - gtk_tree_path_append_index (path, GPOINTER_TO_INT (iter->user_data)); - - return path; -} - -static void -tree_model_get_value (GtkTreeModel *model, GtkTreeIter *iter, - gint column, GValue *value) -{ - TextImportModel *list = TEXT_IMPORT_MODEL (model); - gint idx; - - g_return_if_fail (iter->stamp == TREE_MODEL_STAMP); - - idx = GPOINTER_TO_INT (iter->user_data); - assert (idx >= 0 && idx < list->line_cnt); - - if (column == 0) - { - g_value_init (value, G_TYPE_INT); - g_value_set_int (value, idx + list->first_line + 1); - } - else - { - g_value_init (value, G_TYPE_STRING); - g_value_set_static_string (value, ds_cstr (&list->lines[idx])); - } -} - -static gboolean -tree_model_iter_children (GtkTreeModel *tree_model, - GtkTreeIter *iter, - GtkTreeIter *parent) -{ - return FALSE; -} - -static gint -tree_model_n_children (GtkTreeModel *model, GtkTreeIter *iter) -{ - TextImportModel *list = TEXT_IMPORT_MODEL (model); - - return iter == NULL ? list->line_cnt : 0; -} - -static gboolean -tree_model_nth_child (GtkTreeModel *model, GtkTreeIter *iter, - GtkTreeIter *parent, gint n) -{ - TextImportModel *list = TEXT_IMPORT_MODEL (model); - g_return_val_if_fail (IS_TEXT_IMPORT_MODEL (model), FALSE); - - if (parent) - return FALSE; - return init_iter (list, n, iter); -} - -static void -text_import_model_tree_model_init (gpointer iface_, gpointer data UNUSED) -{ - GtkTreeModelIface *iface = (GtkTreeModelIface *) iface_; - - iface->get_flags = tree_model_get_flags; - iface->get_n_columns = tree_model_n_columns; - iface->get_column_type = tree_model_column_type; - iface->get_iter = tree_model_get_iter; - iface->iter_next = tree_model_iter_next; - iface->get_path = tree_model_get_path; - iface->get_value = tree_model_get_value; - - iface->iter_children = tree_model_iter_children; - iface->iter_has_child = tree_model_iter_has_child; - iface->iter_n_children = tree_model_n_children; - iface->iter_nth_child = tree_model_nth_child; - iface->iter_parent = tree_model_iter_parent; -} - -gint -text_import_model_iter_to_row (const GtkTreeIter *iter) -{ - assert (iter->stamp == TREE_MODEL_STAMP); - return GPOINTER_TO_INT (iter->user_data); -} - /* Increments the "watch cursor" level, setting the cursor for the assistant window to a watch face to indicate to the user that the ongoing operation may take some time. */