helper: Move escape_underscores() here.
[pspp] / src / ui / gui / text-data-import-dialog.c
index 8eb4f3c7972d714f42e96d6991c91aa378277be7..c4abeaa48b2e8f5b9969972ef5bd9ea7a7201933 100644 (file)
@@ -1,5 +1,5 @@
 /* PSPPIRE - a graphical user interface for PSPP.
-   Copyright (C) 2008, 2009, 2010  Free Software Foundation
+   Copyright (C) 2008, 2009, 2010, 2011, 2012  Free Software Foundation
 
    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
 #include "language/data-io/data-parser.h"
 #include "language/lexer/lexer.h"
 #include "libpspp/assertion.h"
+#include "libpspp/i18n.h"
 #include "libpspp/message.h"
 #include "ui/gui/checkbox-treeview.h"
-#include "ui/gui/descriptives-dialog.h"
 #include "ui/gui/dialog-common.h"
 #include "ui/gui/executor.h"
 #include "ui/gui/helper.h"
+#include "ui/gui/builder-wrapper.h"
 #include "ui/gui/psppire-data-window.h"
 #include "ui/gui/psppire-dialog.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/widget-io.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. */
@@ -225,14 +213,14 @@ 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 void escape_underscores (const char *in, char *out);
 static void push_watch_cursor (struct import_assistant *);
 static void pop_watch_cursor (struct import_assistant *);
 
 /* Pops up the Text Data Import assistant. */
 void
-text_data_import_assistant (GtkWindow *parent_window)
+text_data_import_assistant (PsppireDataWindow *dw)
 {
+  GtkWindow *parent_window = GTK_WINDOW (dw);
   struct import_assistant *ia;
 
   ia = xzalloc (sizeof *ia);
@@ -257,7 +245,7 @@ text_data_import_assistant (GtkWindow *parent_window)
   switch (ia->asst.response)
     {
     case GTK_RESPONSE_APPLY:
-      free (execute_syntax_string (generate_syntax (ia)));
+      free (execute_syntax_string (dw, generate_syntax (ia)));
       break;
     case PSPPIRE_RESPONSE_PASTE:
       free (paste_syntax_to_window (generate_syntax (ia)));
@@ -329,7 +317,7 @@ apply_dict (const struct dictionary *dict, struct string *s)
               ds_put_cstr (s, "\n  ");
               syntax_gen_value (s, &vl->value, width, format);
               ds_put_byte (s, ' ');
-              syntax_gen_string (s, ss_cstr (val_lab_get_label (vl)));
+              syntax_gen_string (s, ss_cstr (val_lab_get_escaped_label (vl)));
             }
           free (labels);
           ds_put_cstr (s, ".\n");
@@ -475,8 +463,8 @@ init_file (struct import_assistant *ia, GtkWindow *parent_window)
           destroy_file (ia);
           return false;
         }
-      ds_chomp (line, '\n');
-      ds_chomp (line, '\r');
+      ds_chomp_byte (line, '\n');
+      ds_chomp_byte (line, '\r');
     }
 
   if (file->line_cnt == 0)
@@ -523,16 +511,51 @@ destroy_file (struct import_assistant *ia)
 static char *
 choose_file (GtkWindow *parent_window)
 {
-  GtkWidget *dialog;
   char *file_name;
+  GtkFileFilter *filter = NULL;
 
-  dialog = gtk_file_chooser_dialog_new (_("Import Delimited Text Data"),
+  GtkWidget *dialog = gtk_file_chooser_dialog_new (_("Import Delimited Text Data"),
                                         parent_window,
                                         GTK_FILE_CHOOSER_ACTION_OPEN,
                                         GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
                                         GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT,
                                         NULL);
 
+  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);
+
+  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:
@@ -579,7 +602,7 @@ init_assistant (struct import_assistant *ia, GtkWindow *parent_window)
   gtk_window_set_title (GTK_WINDOW (a->assistant),
                         _("Importing Delimited Text Data"));
   gtk_window_set_transient_for (GTK_WINDOW (a->assistant), parent_window);
-  gtk_window_set_icon_name (GTK_WINDOW (a->assistant), "psppicon");
+  gtk_window_set_icon_name (GTK_WINDOW (a->assistant), "pspp");
 
   a->prop_renderer = gtk_cell_renderer_text_new ();
   g_object_ref_sink (a->prop_renderer);
@@ -726,7 +749,7 @@ init_intro_page (struct import_assistant *ia)
 
   p->n_cases_spin = gtk_spin_button_new_with_range (0, INT_MAX, 100);
 
-  hbox_n_cases = widget_scanf (_("Only the first %4d cases"), &p->n_cases_spin);
+  hbox_n_cases = psppire_scanf_new (_("Only the first %4d cases"), &p->n_cases_spin);
 
   table  = get_widget_assert (builder, "button-table");
 
@@ -736,7 +759,7 @@ init_intro_page (struct import_assistant *ia)
 
   p->percent_spin = gtk_spin_button_new_with_range (0, 100, 10);
 
-  hbox_percent = widget_scanf (_("Only the first %3d %% of file (approximately)"), &p->percent_spin);
+  hbox_percent = psppire_scanf_new (_("Only the first %3d %% of file (approximately)"), &p->percent_spin);
 
   gtk_table_attach_defaults (GTK_TABLE (table), hbox_percent,
                             1, 2,
@@ -861,6 +884,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 *
@@ -871,16 +911,14 @@ create_lines_tree_view (GtkContainer *parent, struct import_assistant *ia)
   size_t max_line_length;
   gint content_width, header_width;
   size_t i;
-  gchar *title = _("Text");
+  const gchar *title = _("Text");
 
   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;
@@ -1251,19 +1289,17 @@ choose_column_names (struct import_assistant *ia)
   struct column *col;
   size_t name_row;
 
-  dict = dict_create ();
+  dict = dict_create (get_default_encoding ());
   name_row = f->variable_names && f->skip_lines ? f->skip_lines : 0;
   for (col = s->columns; col < &s->columns[s->column_cnt]; col++)
     {
-      char name[VAR_NAME_LEN + 1];
-      char *hint;
+      char *hint, *name;
 
       hint = name_row ? ss_xstrdup (col->contents[name_row - 1]) : NULL;
-      if (!dict_make_unique_var_name (dict, hint, &generated_name_count, name))
-        NOT_REACHED ();
+      name = dict_make_unique_var_name (dict, hint, &generated_name_count);
       free (hint);
 
-      col->name = xstrdup (name);
+      col->name = name;
       dict_create_var_assert (dict, name, 0);
     }
   dict_destroy (dict);
@@ -1502,7 +1538,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)
     {
@@ -1596,12 +1632,11 @@ prepare_formats_page (struct import_assistant *ia)
 
   push_watch_cursor (ia);
 
-  dict = dict_create ();
+  dict = dict_create (get_default_encoding ());
   fg = fmt_guesser_create ();
   for (column_idx = 0; column_idx < s->column_cnt; column_idx++)
     {
       struct variable *modified_var;
-      char name[VAR_NAME_LEN + 1];
 
       modified_var = (column_idx < p->modified_var_cnt
                       ? p->modified_vars[column_idx] : NULL);
@@ -1610,11 +1645,11 @@ prepare_formats_page (struct import_assistant *ia)
           struct column *column = &s->columns[column_idx];
           struct variable *var;
           struct fmt_spec format;
+          char *name;
           size_t row;
 
           /* Choose variable name. */
-          if (!dict_make_unique_var_name (dict, column->name, &number, name))
-            NOT_REACHED ();
+          name = dict_make_unique_var_name (dict, column->name, &number);
 
           /* Choose variable format. */
           fmt_guesser_clear (fg);
@@ -1626,13 +1661,17 @@ prepare_formats_page (struct import_assistant *ia)
           /* Create variable. */
           var = dict_create_var_assert (dict, name, fmt_var_width (&format));
           var_set_both_formats (var, &format);
+
+          free (name);
         }
       else
         {
-          if (!dict_make_unique_var_name (dict, var_get_name (modified_var),
-                                          &number, name))
-            NOT_REACHED ();
+          char *name;
+
+          name = dict_make_unique_var_name (dict, var_get_name (modified_var),
+                                            &number);
           dict_clone_var_as_assert (dict, modified_var, name);
+          free (name);
         }
     }
   fmt_guesser_destroy (fg);
@@ -1767,8 +1806,7 @@ parse_field (struct import_assistant *ia,
     {
       char *error;
 
-      error = data_in (field, LEGACY_NATIVE, in->type, &val,
-                       var_get_width (var),
+      error = data_in (field, C_ENCODING, in->type, &val, var_get_width (var),
                        dict_get_encoding (ia->formats.dict));
       if (error != NULL)
         {
@@ -1814,7 +1852,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")),
@@ -1880,7 +1918,7 @@ get_tooltip_location (GtkWidget *widget, gint wx, gint wy,
      to make the data related to the tool tips part of a GObject
      that only gets destroyed when all references are released,
      but this solution appears to be effective too. */
-  if (!GTK_WIDGET_MAPPED (widget))
+  if (!gtk_widget_get_mapped (widget))
     return FALSE;
 
   gtk_tree_view_convert_widget_to_bin_window_coords (tree_view,
@@ -1898,7 +1936,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;
 }
 
@@ -1910,14 +1948,33 @@ 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);
 
   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)
@@ -1925,12 +1982,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);
 }
 
@@ -1967,17 +2025,17 @@ make_data_column (struct import_assistant *ia, GtkTreeView *tree_view,
 {
   struct variable *var = NULL;
   struct column *column = NULL;
-  char name[(VAR_NAME_LEN * 2) + 1];
   size_t char_cnt;
   gint content_width, header_width;
   GtkTreeViewColumn *tree_column;
+  char *name;
 
   if (input)
     column = &ia->separators.columns[dict_idx];
   else
     var = dict_get_var (ia->formats.dict, dict_idx);
 
-  escape_underscores (input ? column->name : var_get_name (var), name);
+  name = escape_underscores (input ? column->name : var_get_name (var));
   char_cnt = input ? column->width : var_get_print_format (var)->w;
   content_width = get_monospace_width (tree_view, ia->asst.fixed_renderer,
                                        char_cnt);
@@ -1997,6 +2055,8 @@ make_data_column (struct import_assistant *ia, GtkTreeView *tree_view,
   gtk_tree_view_column_set_fixed_width (tree_column, MAX (content_width,
                                                           header_width));
 
+  free (name);
+
   return tree_column;
 }
 
@@ -2027,284 +2087,6 @@ create_data_tree_view (bool input, GtkContainer *parent,
   return tree_view;
 }
 
-static void
-escape_underscores (const char *in, char *out)
-{
-  for (; *in != '\0'; in++)
-    {
-      if (*in == '_')
-        *out++ = '_';
-      *out++ = *in;
-    }
-  *out = '\0';
-}
-\f
-/* 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. */