Merge "master" into "psppsheet" to obtain bug fixes from "master". 20120709001830/pspp 20120710001843/pspp
authorBen Pfaff <blp@cs.stanford.edu>
Mon, 9 Jul 2012 05:18:20 +0000 (22:18 -0700)
committerBen Pfaff <blp@cs.stanford.edu>
Mon, 9 Jul 2012 05:18:20 +0000 (22:18 -0700)
1  2 
src/ui/gui/psppire-data-window.c
src/ui/gui/text-data-import-dialog.c

index 3db9b28b8446ec4c21331a8332f611baf916b733,c22f7bb293acb05ec957931a8f2a693db728b86e..204c8f1c849d68abed8cd4e6dee7d0c89fd4d278
@@@ -35,7 -35,9 +35,7 @@@
  #include "ui/gui/crosstabs-dialog.h"
  #include "ui/gui/entry-dialog.h"
  #include "ui/gui/executor.h"
 -#include "ui/gui/find-dialog.h"
  #include "ui/gui/frequencies-dialog.h"
 -#include "ui/gui/goto-case-dialog.h"
  #include "ui/gui/help-menu.h"
  #include "ui/gui/helper.h"
  #include "ui/gui/helper.h"
@@@ -43,7 -45,6 +43,7 @@@
  #include "ui/gui/npar-two-sample-related.h"
  #include "ui/gui/oneway-anova-dialog.h"
  #include "ui/gui/psppire-data-window.h"
 +#include "ui/gui/psppire-dialog-action.h"
  #include "ui/gui/psppire-syntax-window.h"
  #include "ui/gui/psppire-window.h"
  #include "ui/gui/psppire.h"
@@@ -87,10 -88,6 +87,10 @@@ static void psppire_data_window_get_pro
                                                GValue          *value,
                                                GParamSpec      *pspec);
  
 +static guint psppire_data_window_add_ui (PsppireDataWindow *, GtkUIManager *);
 +static void psppire_data_window_remove_ui (PsppireDataWindow *,
 +                                           GtkUIManager *, guint);
 +
  GType
  psppire_data_window_get_type (void)
  {
@@@ -155,6 -152,24 +155,6 @@@ psppire_data_window_class_init (Psppire
                            G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE));
  }
  \f
 -static void
 -set_paste_menuitem_sensitivity (PsppireDataWindow *de, gboolean x)
 -{
 -  GtkAction *edit_paste = get_action_assert (de->builder, "edit_paste");
 -
 -  gtk_action_set_sensitive (edit_paste, x);
 -}
 -
 -static void
 -set_cut_copy_menuitem_sensitivity (PsppireDataWindow *de, gboolean x)
 -{
 -  GtkAction *edit_copy = get_action_assert (de->builder, "edit_copy");
 -  GtkAction *edit_cut = get_action_assert (de->builder, "edit_cut");
 -
 -  gtk_action_set_sensitive (edit_copy, x);
 -  gtk_action_set_sensitive (edit_cut, x);
 -}
 -
  /* Run the EXECUTE command. */
  static void
  execute (PsppireDataWindow *dw)
@@@ -201,11 -216,13 +201,11 @@@ on_filter_change (GObject *o, gint filt
      }
    else
      {
 -      PsppireVarStore *vs = NULL;
        PsppireDict *dict = NULL;
        struct variable *var ;
        gchar *text ;
  
 -      g_object_get (de->data_editor, "var-store", &vs, NULL);
 -      g_object_get (vs, "dictionary", &dict, NULL);
 +      g_object_get (de->data_editor, "dictionary", &dict, NULL);
  
        var = psppire_dict_get_variable (dict, filter_index);
  
@@@ -272,10 -289,12 +272,10 @@@ on_weight_change (GObject *o, gint weig
    else
      {
        struct variable *var ;
 -      PsppireVarStore *vs = NULL;
        PsppireDict *dict = NULL;
        gchar *text;
  
 -      g_object_get (de->data_editor, "var-store", &vs, NULL);
 -      g_object_get (vs, "dictionary", &dict, NULL);
 +      g_object_get (de->data_editor, "dictionary", &dict, NULL);
  
        var = psppire_dict_get_variable (dict, weight_index);
  
@@@ -411,6 -430,19 +411,6 @@@ save_file (PsppireWindow *w
  }
  
  
 -static void
 -insert_case (PsppireDataWindow *dw)
 -{
 -  psppire_data_editor_insert_case (dw->data_editor);
 -}
 -
 -static void
 -on_insert_variable (PsppireDataWindow *dw)
 -{
 -  psppire_data_editor_insert_variable (dw->data_editor);
 -}
 -
 -
  static void
  display_dict (PsppireDataWindow *de)
  {
@@@ -595,6 -627,27 +595,6 @@@ on_rename_dataset (PsppireDataWindow *d
    free (new_name);
  }
  
 -static void
 -on_edit_paste (PsppireDataWindow  *de)
 -{
 -  psppire_data_editor_clip_paste (de->data_editor);
 -}
 -
 -static void
 -on_edit_copy (PsppireDataWindow  *de)
 -{
 -  psppire_data_editor_clip_copy (de->data_editor);
 -}
 -
 -
 -
 -static void
 -on_edit_cut (PsppireDataWindow  *de)
 -{
 -  psppire_data_editor_clip_cut (de->data_editor);
 -}
 -
 -
  static void
  status_bar_activate (PsppireDataWindow  *de, GtkToggleAction *action)
  {
@@@ -689,6 -742,7 +689,6 @@@ file_quit (PsppireDataWindow *de
    psppire_quit ();
  }
  
 -
  static void
  on_recent_data_select (GtkMenuShell *menushell,
                       PsppireWindow *window)
@@@ -773,52 -827,75 +773,52 @@@ on_recent_files_select (GtkMenuShell *m
    g_free (file);
  }
  
 -
 -
  static void
 -enable_delete_cases (GtkWidget *w, gint case_num, gpointer data)
 +set_unsaved (gpointer w)
  {
 -  PsppireDataWindow *de = PSPPIRE_DATA_WINDOW (data);
 -
 -  gtk_action_set_visible (de->delete_cases, case_num != -1);
 +  psppire_window_set_unsaved (PSPPIRE_WINDOW (w));
  }
  
 -
  static void
 -enable_delete_variables (GtkWidget *w, gint var, gpointer data)
 +on_switch_page (PsppireDataEditor *de, GtkNotebookPage *p,
 +              gint pagenum, PsppireDataWindow *dw)
  {
 -  PsppireDataWindow *de = PSPPIRE_DATA_WINDOW (data);
 -
 -  gtk_action_set_visible (de->delete_variables, var != -1);
 +  GtkWidget *page_menu_item;
 +  gboolean is_ds;
 +  const char *path;
 +
 +  is_ds = pagenum == PSPPIRE_DATA_EDITOR_DATA_VIEW;
 +  path = (is_ds
 +          ? "/ui/menubar/view/view_data"
 +          : "/ui/menubar/view/view_variables");
 +  page_menu_item = gtk_ui_manager_get_widget (dw->ui_manager, path);
 +  gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (page_menu_item), TRUE);
  }
  
 -/* Callback for when the datasheet/varsheet is selected */
  static void
 -on_switch_sheet (GtkNotebook *notebook,
 -               GtkNotebookPage *page,
 -               guint page_num,
 -               gpointer user_data)
 +on_ui_manager_changed (PsppireDataEditor *de,
 +                       GParamSpec *pspec UNUSED,
 +                       PsppireDataWindow *dw)
  {
 -  PsppireDataWindow *de = PSPPIRE_DATA_WINDOW (user_data);
 -
 -  GtkUIManager *uim = GTK_UI_MANAGER (get_object_assert (de->builder, "uimanager1", GTK_TYPE_UI_MANAGER));
 -
 -  GtkWidget *view_data =
 -    gtk_ui_manager_get_widget (uim,"/ui/menubar/view/view_data");
 -
 -  GtkWidget *view_variables =
 -    gtk_ui_manager_get_widget (uim,"/ui/menubar/view/view_variables");
 +  GtkUIManager *uim = psppire_data_editor_get_ui_manager (de);
 +  if (uim == dw->uim)
 +    return;
  
 -  switch (page_num)
 +  if (dw->uim)
      {
 -    case PSPPIRE_DATA_EDITOR_VARIABLE_VIEW:
 -      gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (view_variables),
 -                                      TRUE);
 -      gtk_action_set_sensitive (de->insert_variable, TRUE);
 -      gtk_action_set_sensitive (de->insert_case, FALSE);
 -      gtk_action_set_sensitive (de->invoke_goto_dialog, FALSE);
 -      break;
 -    case PSPPIRE_DATA_EDITOR_DATA_VIEW:
 -      gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (view_data), TRUE);
 -      gtk_action_set_sensitive (de->invoke_goto_dialog, TRUE);
 -      gtk_action_set_sensitive (de->insert_case, TRUE);
 -      break;
 -    default:
 -      g_assert_not_reached ();
 -      break;
 +      psppire_data_window_remove_ui (dw, dw->uim, dw->merge_id);
 +      g_object_unref (dw->uim);
 +      dw->uim = NULL;
      }
  
 -#if 0
 -  update_paste_menuitem (de, page_num);
 -#endif
 -}
 -
 -
 -
 -static void
 -set_unsaved (gpointer w)
 -{
 -  psppire_window_set_unsaved (PSPPIRE_WINDOW (w));
 +  dw->uim = uim;
 +  if (dw->uim)
 +    {
 +      g_object_ref (dw->uim);
 +      dw->merge_id = psppire_data_window_add_ui (dw, dw->uim);
 +    }
  }
  
 -
  /* Connects the action called ACTION_NAME to HANDLER passing DW as the auxilliary data.
     Returns a pointer to the action
  */
@@@ -843,15 -920,14 +843,15 @@@ connect_action (PsppireDataWindow *dw, 
  static void
  psppire_data_window_init (PsppireDataWindow *de)
  {
 -  GtkUIManager *uim;
 -
    de->builder = builder_new ("data-editor.ui");
  
 -  uim = GTK_UI_MANAGER (get_object_assert (de->builder, "uimanager1", GTK_TYPE_UI_MANAGER));
 +  de->ui_manager = GTK_UI_MANAGER (get_object_assert (de->builder, "uimanager1", GTK_TYPE_UI_MANAGER));
  
    PSPPIRE_WINDOW (de)->menu =
 -    GTK_MENU_SHELL (gtk_ui_manager_get_widget (uim,"/ui/menubar/windows/windows_minimise_all")->parent);
 +    GTK_MENU_SHELL (gtk_ui_manager_get_widget (de->ui_manager, "/ui/menubar/windows/windows_minimise_all")->parent);
 +
 +  de->uim = NULL;
 +  de->merge_id = 0;
  }
  
  static void
@@@ -864,6 -940,8 +864,6 @@@ psppire_data_window_finish_init (Psppir
        transformation_change_callback, /* transformations_changed */
      };
  
 -  PsppireDict *dict;
 -
    GtkWidget *menubar;
    GtkWidget *hb ;
    GtkWidget *sb ;
    GtkWidget *box = gtk_vbox_new (FALSE, 0);
  
    de->dataset = ds;
 -  dict = psppire_dict_new_from_dict (dataset_dict (ds));
 -  de->var_store = psppire_var_store_new (dict);
 -  de->data_store = psppire_data_store_new (dict);
 +  de->dict = psppire_dict_new_from_dict (dataset_dict (ds));
 +  de->data_store = psppire_data_store_new (de->dict);
    psppire_data_store_set_reader (de->data_store, NULL);
  
    menubar = get_widget_assert (de->builder, "menubar");
    hb = get_widget_assert (de->builder, "handlebox1");
    sb = get_widget_assert (de->builder, "status-bar");
  
 +  de->uim = NULL;
 +  de->merge_id = 0;
 +
    de->data_editor =
 -    PSPPIRE_DATA_EDITOR (psppire_data_editor_new (de, de->var_store,
 -                                                  de->data_store));
 +    PSPPIRE_DATA_EDITOR (psppire_data_editor_new (de->dict, de->data_store));
 +  g_signal_connect (de->data_editor, "switch-page",
 +                    G_CALLBACK (on_switch_page), de);
  
    g_signal_connect_swapped (de->data_store, "case-changed",
                            G_CALLBACK (set_unsaved), de);
  
    gtk_container_add (GTK_CONTAINER (de), box);
  
 -  set_cut_copy_menuitem_sensitivity (de, FALSE);
 -
 -  g_signal_connect_swapped (de->data_editor, "data-selection-changed",
 -                          G_CALLBACK (set_cut_copy_menuitem_sensitivity), de);
 -
 -
 -  set_paste_menuitem_sensitivity (de, FALSE);
 -
 -  g_signal_connect_swapped (de->data_editor, "data-available-changed",
 -                          G_CALLBACK (set_paste_menuitem_sensitivity), de);
 -
 -  g_signal_connect (dict, "weight-changed",
 +  g_signal_connect (de->dict, "weight-changed",
                    G_CALLBACK (on_weight_change),
                    de);
  
 -  g_signal_connect (dict, "filter-changed",
 +  g_signal_connect (de->dict, "filter-changed",
                    G_CALLBACK (on_filter_change),
                    de);
  
 -  g_signal_connect (dict, "split-changed",
 +  g_signal_connect (de->dict, "split-changed",
                    G_CALLBACK (on_split_change),
                    de);
  
  
 -  connect_action (de, "edit_copy", G_CALLBACK (on_edit_copy));
 -
 -  connect_action (de, "edit_cut", G_CALLBACK (on_edit_cut));
 -
    connect_action (de, "file_new_data", G_CALLBACK (create_data_window));
  
    connect_action (de, "file_import-text", G_CALLBACK (text_data_import_assistant));
  
    connect_action (de, "file_information_external-file", G_CALLBACK (sysfile_info));
  
 -  connect_action (de, "edit_paste", G_CALLBACK (on_edit_paste));
 -
 -  de->insert_case = connect_action (de, "edit_insert-case", G_CALLBACK (insert_case));
 -
 -  de->insert_variable = connect_action (de, "action_insert-variable", G_CALLBACK (on_insert_variable));
 -
 -  de->invoke_goto_dialog = connect_action (de, "edit_goto-case", G_CALLBACK (goto_case_dialog));
 -
    g_signal_connect_swapped (get_action_assert (de->builder, "view_value-labels"), "toggled", G_CALLBACK (toggle_value_labels), de);
  
 -  {
 -    de->delete_cases = get_action_assert (de->builder, "edit_clear-cases");
 -
 -    g_signal_connect_swapped (de->delete_cases, "activate", G_CALLBACK (psppire_data_editor_delete_cases), de->data_editor);
 -
 -    gtk_action_set_visible (de->delete_cases, FALSE);
 -  }
 -
 -
 -  {
 -    de->delete_variables = get_action_assert (de->builder, "edit_clear-variables");
 -
 -    g_signal_connect_swapped (de->delete_variables, "activate", G_CALLBACK (psppire_data_editor_delete_variables), de->data_editor);
 -
 -    gtk_action_set_visible (de->delete_variables, FALSE);
 -  }
 -
 -
    connect_action (de, "data_transpose", G_CALLBACK (transpose_dialog));
    connect_action (de, "data_select-cases", G_CALLBACK (select_cases_dialog));
    connect_action (de, "data_aggregate", G_CALLBACK (aggregate_dialog));
    connect_action (de, "transform_compute", G_CALLBACK (compute_dialog));
    connect_action (de, "transform_autorecode", G_CALLBACK (autorecode_dialog));
 -  connect_action (de, "edit_find", G_CALLBACK (find_dialog));
    connect_action (de, "data_split-file", G_CALLBACK (split_file_dialog));
    connect_action (de, "data_weight-cases", G_CALLBACK (weight_cases_dialog));
    connect_action (de, "oneway-anova", G_CALLBACK (oneway_anova_dialog));
    connect_action (de, "two-related-samples", G_CALLBACK (two_related_dialog));
  
    {
 -    GtkUIManager *uim = GTK_UI_MANAGER (get_object_assert (de->builder, "uimanager1", GTK_TYPE_UI_MANAGER));
 -
      GtkWidget *recent_data =
 -      gtk_ui_manager_get_widget (uim,"/ui/menubar/file/file_recent-data");
 +      gtk_ui_manager_get_widget (de->ui_manager, "/ui/menubar/file/file_recent-data");
  
      GtkWidget *recent_files =
 -      gtk_ui_manager_get_widget (uim,"/ui/menubar/file/file_recent-files");
 +      gtk_ui_manager_get_widget (de->ui_manager, "/ui/menubar/file/file_recent-files");
  
  
      GtkWidget *menu_data = gtk_recent_chooser_menu_new_for_manager (
    connect_action (de, "file_new_syntax", G_CALLBACK (create_syntax_window));
  
  
 -  g_signal_connect (de->data_editor,
 -                  "cases-selected",
 -                  G_CALLBACK (enable_delete_cases),
 -                  de);
 -
 -  g_signal_connect (de->data_editor,
 -                  "variables-selected",
 -                  G_CALLBACK (enable_delete_variables),
 -                  de);
 -
 -
 -  g_signal_connect (de->data_editor,
 -                  "switch-page",
 -                  G_CALLBACK (on_switch_sheet), de);
 -
    gtk_notebook_set_current_page (GTK_NOTEBOOK (de->data_editor), PSPPIRE_DATA_EDITOR_VARIABLE_VIEW);
    gtk_notebook_set_current_page (GTK_NOTEBOOK (de->data_editor), PSPPIRE_DATA_EDITOR_DATA_VIEW);
  
  
    g_signal_connect_swapped (get_action_assert (de->builder, "windows_split"), "toggled", G_CALLBACK (toggle_split_window), de);
  
 -  {
 -    GtkUIManager *uim = GTK_UI_MANAGER (get_object_assert (de->builder, "uimanager1", GTK_TYPE_UI_MANAGER));
 -
 -    merge_help_menu (uim);
 -  }
 -
 -  {
 -    GtkWidget *data_sheet_cases_popup_menu = get_widget_assert (de->builder,
 -                                                              "datasheet-cases-popup");
 +  merge_help_menu (de->ui_manager);
  
 -    GtkWidget *var_sheet_variable_popup_menu = get_widget_assert (de->builder,
 -                                                                "varsheet-variable-popup");
 -
 -    GtkWidget *data_sheet_variable_popup_menu = get_widget_assert (de->builder,
 -                                                                 "datasheet-variable-popup");
 -
 -    g_signal_connect_swapped (get_action_assert (de->builder, "sort-up"), "activate",
 -                            G_CALLBACK (psppire_data_editor_sort_ascending),
 -                            de->data_editor);
 -
 -    g_signal_connect_swapped (get_action_assert (de->builder, "sort-down"), "activate",
 -                            G_CALLBACK (psppire_data_editor_sort_descending),
 -                            de->data_editor);
 -
 -    g_object_set (de->data_editor,
 -                "datasheet-column-menu", data_sheet_variable_popup_menu,
 -                "datasheet-row-menu", data_sheet_cases_popup_menu,
 -                "varsheet-row-menu", var_sheet_variable_popup_menu,
 -                NULL);
 -  }
 +  g_signal_connect (de->data_editor, "notify::ui-manager",
 +                    G_CALLBACK (on_ui_manager_changed), de);
 +  on_ui_manager_changed (de->data_editor, NULL, de);
  
    gtk_widget_show (GTK_WIDGET (de->data_editor));
    gtk_widget_show (box);
@@@ -1053,23 -1212,16 +1053,23 @@@ psppire_data_window_dispose (GObject *o
  {
    PsppireDataWindow *dw = PSPPIRE_DATA_WINDOW (object);
  
 +  if (dw->uim)
 +    {
 +      psppire_data_window_remove_ui (dw, dw->uim, dw->merge_id);
 +      g_object_unref (dw->uim);
 +      dw->uim = NULL;
 +    }
 +
    if (dw->builder != NULL)
      {
        g_object_unref (dw->builder);
        dw->builder = NULL;
      }
  
 -  if (dw->var_store)
 +  if (dw->dict)
      {
 -      g_object_unref (dw->var_store);
 -      dw->var_store = NULL;
 +      g_object_unref (dw->dict);
 +      dw->dict = NULL;
      }
  
    if (dw->data_store)
@@@ -1126,65 -1278,6 +1126,65 @@@ psppire_data_window_get_property (GObje
      };
  }
  
 +static guint
 +psppire_data_window_add_ui (PsppireDataWindow *pdw, GtkUIManager *uim)
 +{
 +  gchar *ui_string;
 +  guint merge_id;
 +  GList *list;
 +
 +  ui_string = gtk_ui_manager_get_ui (uim);
 +  merge_id = gtk_ui_manager_add_ui_from_string (pdw->ui_manager, ui_string,
 +                                                -1, NULL);
 +  g_free (ui_string);
 +
 +  g_return_val_if_fail (merge_id != 0, 0);
 +
 +  list = gtk_ui_manager_get_action_groups (uim);
 +  for (; list != NULL; list = list->next)
 +    {
 +      GtkActionGroup *action_group = list->data;
 +      GList *actions = gtk_action_group_list_actions (action_group);
 +      GList *action;
 +
 +      for (action = actions; action != NULL; action = action->next)
 +        {
 +          GtkAction *a = action->data;
 +
 +          if (PSPPIRE_IS_DIALOG_ACTION (a))
 +            g_object_set (a, "manager", pdw->ui_manager, NULL);
 +        }
 +
 +      gtk_ui_manager_insert_action_group (pdw->ui_manager, action_group, 0);
 +    }
 +
 +  gtk_window_add_accel_group (GTK_WINDOW (pdw),
 +                              gtk_ui_manager_get_accel_group (uim));
 +
 +  return merge_id;
 +}
 +
 +static void
 +psppire_data_window_remove_ui (PsppireDataWindow *pdw,
 +                               GtkUIManager *uim, guint merge_id)
 +{
 +  GList *list;
 +
 +  g_return_if_fail (merge_id != 0);
 +
 +  gtk_ui_manager_remove_ui (pdw->ui_manager, merge_id);
 +
 +  list = gtk_ui_manager_get_action_groups (uim);
 +  for (; list != NULL; list = list->next)
 +    {
 +      GtkActionGroup *action_group = list->data;
 +      gtk_ui_manager_remove_action_group (pdw->ui_manager, action_group);
 +    }
 +
 +  gtk_window_remove_accel_group (GTK_WINDOW (pdw),
 +                                 gtk_ui_manager_get_accel_group (uim));
 +}
 +
  GtkWidget*
  psppire_data_window_new (struct dataset *ds)
  {
  
    if (ds == NULL)
      {
-       static int n_datasets;
-       char *dataset_name;
-       dataset_name = xasprintf ("DataSet%d", ++n_datasets);
+       char *dataset_name = session_generate_dataset_name (the_session);
        ds = dataset_create (the_session, dataset_name);
        free (dataset_name);
      }
  bool
  psppire_data_window_is_empty (PsppireDataWindow *dw)
  {
 -  return psppire_var_store_get_var_cnt (dw->var_store) == 0;
 +  return psppire_dict_get_var_cnt (dw->dict) == 0;
  }
  
  static void
@@@ -1265,18 -1355,6 +1262,18 @@@ psppire_data_window_for_dataset (struc
    return NULL;
  }
  
 +PsppireDataWindow *
 +psppire_data_window_for_data_store (PsppireDataStore *data_store)
 +{
 +  PsppireDataWindow *pdw;
 +
 +  ll_for_each (pdw, PsppireDataWindow, ll, &all_data_windows)
 +    if (pdw->data_store == data_store)
 +      return pdw;
 +
 +  return NULL;
 +}
 +
  void
  create_data_window (void)
  {
@@@ -1290,14 -1368,10 +1287,14 @@@ open_data_window (PsppireWindow *victim
  
    if (PSPPIRE_IS_DATA_WINDOW (victim)
        && psppire_data_window_is_empty (PSPPIRE_DATA_WINDOW (victim)))
 -    window = GTK_WIDGET (victim);
 +    {
 +      window = GTK_WIDGET (victim);
 +      gtk_widget_hide (GTK_WIDGET (PSPPIRE_DATA_WINDOW (window)->data_editor));
 +    }
    else
      window = psppire_data_window_new (NULL);
  
    psppire_window_load (PSPPIRE_WINDOW (window), file_name);
 -  gtk_widget_show (window);
 +  gtk_widget_show_all (window);
  }
 +
index b5a50cbaba1f961f911e558402e32bd3e6af5885,907dd7ab4cb683ebe4f61a3fcc842ec35ec64e48..0abeb56f6884c75b013925e8876ddfd02124e9cc
@@@ -20,6 -20,7 +20,6 @@@
  
  #include <errno.h>
  #include <fcntl.h>
 -#include <gtk-contrib/psppire-sheet.h>
  #include <gtk/gtk.h>
  #include <limits.h>
  #include <stdlib.h>
  #include "libpspp/i18n.h"
  #include "libpspp/line-reader.h"
  #include "libpspp/message.h"
 +#include "ui/gui/builder-wrapper.h"
  #include "ui/gui/checkbox-treeview.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/pspp-sheet-selection.h"
 +#include "ui/gui/pspp-sheet-view.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/gui/psppire-var-sheet.h"
  #include "ui/syntax-gen.h"
  
  #include "gl/error.h"
@@@ -115,7 -115,7 +115,7 @@@ struct first_line_pag
      bool variable_names; /* Variable names above first line of data? */
  
      GtkWidget *page;
 -    GtkTreeView *tree_view;
 +    PsppSheetView *tree_view;
      GtkWidget *variable_names_cb;
    };
  static void init_first_line_page (struct import_assistant *);
@@@ -140,7 -140,7 +140,7 @@@ struct separators_pag
      GtkWidget *quote_combo;
      GtkEntry *quote_entry;
      GtkWidget *escape_cb;
 -    GtkTreeView *fields_tree_view;
 +    PsppSheetView *fields_tree_view;
    };
  /* The columns that the separators divide the data into. */
  struct column
@@@ -177,7 -177,7 +177,7 @@@ struct formats_pag
      struct dictionary *dict;
  
      GtkWidget *page;
 -    GtkTreeView *data_tree_view;
 +    PsppSheetView *data_tree_view;
      PsppireDict *psppire_dict;
      struct variable **modified_vars;
      size_t modified_var_cnt;
@@@ -205,17 -205,17 +205,17 @@@ static gboolean get_tooltip_location (G
                                        size_t *row, size_t *column);
  static void make_tree_view (const struct import_assistant *ia,
                              size_t first_line,
 -                            GtkTreeView **tree_view);
 +                            PsppSheetView **tree_view);
  static void add_line_number_column (const struct import_assistant *,
 -                                    GtkTreeView *);
 -static gint get_monospace_width (GtkTreeView *, GtkCellRenderer *,
 +                                    PsppSheetView *);
 +static gint get_monospace_width (PsppSheetView *, GtkCellRenderer *,
                                   size_t char_cnt);
 -static gint get_string_width (GtkTreeView *, GtkCellRenderer *,
 +static gint get_string_width (PsppSheetView *, GtkCellRenderer *,
                                const char *string);
 -static GtkTreeViewColumn *make_data_column (struct import_assistant *,
 -                                            GtkTreeView *, bool input,
 +static PsppSheetViewColumn *make_data_column (struct import_assistant *,
 +                                            PsppSheetView *, bool input,
                                              gint column_idx);
 -static GtkTreeView *create_data_tree_view (bool input, GtkContainer *parent,
 +static PsppSheetView *create_data_tree_view (bool input, GtkContainer *parent,
                                             struct import_assistant *);
  static void push_watch_cursor (struct import_assistant *);
  static void pop_watch_cursor (struct import_assistant *);
@@@ -861,9 -861,9 +861,9 @@@ on_intro_amount_changed (struct import_
  \f
  /* The "first line" page of the assistant. */
  
 -static GtkTreeView *create_lines_tree_view (GtkContainer *parent_window,
 +static PsppSheetView *create_lines_tree_view (GtkContainer *parent_window,
                                              struct import_assistant *);
 -static void on_first_line_change (GtkTreeSelection *,
 +static void on_first_line_change (PsppSheetSelection *,
                                    struct import_assistant *);
  static void on_variable_names_cb_toggle (GtkToggleButton *,
                                           struct import_assistant *);
@@@ -883,12 -883,11 +883,12 @@@ init_first_line_page (struct import_ass
    p->tree_view = create_lines_tree_view (
      GTK_CONTAINER (get_widget_assert (builder, "first-line-scroller")), ia);
    p->variable_names_cb = get_widget_assert (builder, "variable-names");
 -  gtk_tree_selection_set_mode (
 -    gtk_tree_view_get_selection (GTK_TREE_VIEW (p->tree_view)),
 -    GTK_SELECTION_BROWSE);
 +  pspp_sheet_selection_set_mode (
 +    pspp_sheet_view_get_selection (PSPP_SHEET_VIEW (p->tree_view)),
 +    PSPP_SHEET_SELECTION_BROWSE);
 +  pspp_sheet_view_set_rubber_banding (PSPP_SHEET_VIEW (p->tree_view), TRUE);
    set_first_line (ia);
 -  g_signal_connect (gtk_tree_view_get_selection (GTK_TREE_VIEW (p->tree_view)),
 +  g_signal_connect (pspp_sheet_view_get_selection (PSPP_SHEET_VIEW (p->tree_view)),
                      "changed", G_CALLBACK (on_first_line_change), ia);
    g_signal_connect (p->variable_names_cb, "toggled",
                      G_CALLBACK (on_variable_names_cb_toggle), ia);
@@@ -904,7 -903,7 +904,7 @@@ reset_first_line_page (struct import_as
  }
  
  static void
 -render_line (GtkTreeViewColumn *tree_column,
 +render_line (PsppSheetViewColumn *tree_column,
               GtkCellRenderer *cell,
               GtkTreeModel *tree_model,
               GtkTreeIter *iter,
  
  /* Creates and returns a tree view that contains each of the
     lines in IA's file as a row. */
 -static GtkTreeView *
 +static PsppSheetView *
  create_lines_tree_view (GtkContainer *parent, struct import_assistant *ia)
  {
 -  GtkTreeView *tree_view;
 -  GtkTreeViewColumn *column;
 +  PsppSheetView *tree_view;
 +  PsppSheetViewColumn *column;
    size_t max_line_length;
    gint content_width, header_width;
    size_t i;
  
    make_tree_view (ia, 0, &tree_view);
  
 -  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,
 +  column = pspp_sheet_view_column_new_with_attributes (
 +    title, ia->asst.fixed_renderer, (void *) NULL);
 +  pspp_sheet_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);
 +  pspp_sheet_view_column_set_resizable (column, TRUE);
  
    max_line_length = 0;
    for (i = 0; i < ia->file.line_cnt; i++)
    content_width = get_monospace_width (tree_view, ia->asst.fixed_renderer,
                                         max_line_length);
    header_width = get_string_width (tree_view, ia->asst.prop_renderer, title);
 -  gtk_tree_view_column_set_fixed_width (column, MAX (content_width,
 +  pspp_sheet_view_column_set_fixed_width (column, MAX (content_width,
                                                       header_width));
 -  gtk_tree_view_append_column (tree_view, column);
 -
 -  gtk_tree_view_set_fixed_height_mode (tree_view, true);
 +  pspp_sheet_view_append_column (tree_view, column);
  
    gtk_container_add (parent, GTK_WIDGET (tree_view));
    gtk_widget_show (GTK_WIDGET (tree_view));
  /* Called when the line selected in the first_line tree view
     changes. */
  static void
 -on_first_line_change (GtkTreeSelection *selection UNUSED,
 +on_first_line_change (PsppSheetSelection *selection UNUSED,
                        struct import_assistant *ia)
  {
    get_first_line (ia);
@@@ -985,7 -986,7 +985,7 @@@ set_first_line (struct import_assistan
    GtkTreePath *path;
  
    path = gtk_tree_path_new_from_indices (ia->first_line.skip_lines, -1);
 -  gtk_tree_view_set_cursor (GTK_TREE_VIEW (ia->first_line.tree_view),
 +  pspp_sheet_view_set_cursor (PSPP_SHEET_VIEW (ia->first_line.tree_view),
                              path, NULL, false);
    gtk_tree_path_free (path);
  
  static void
  get_first_line (struct import_assistant *ia)
  {
 -  GtkTreeSelection *selection;
 +  PsppSheetSelection *selection;
    GtkTreeIter iter;
    GtkTreeModel *model;
  
 -  selection = gtk_tree_view_get_selection (ia->first_line.tree_view);
 -  if (gtk_tree_selection_get_selected (selection, &model, &iter))
 +  selection = pspp_sheet_view_get_selection (ia->first_line.tree_view);
 +  if (pspp_sheet_selection_get_selected (selection, &model, &iter))
      {
        GtkTreePath *path = gtk_tree_model_get_path (model, &iter);
        int row = gtk_tree_path_get_indices (path)[0];
@@@ -1042,7 -1043,7 +1042,7 @@@ static void on_quote_combo_change (GtkC
  static void on_quote_cb_toggle (GtkToggleButton *quote_cb,
                                  struct import_assistant *);
  static void on_separator_toggle (GtkToggleButton *, struct import_assistant *);
 -static void render_input_cell (GtkTreeViewColumn *tree_column,
 +static void render_input_cell (PsppSheetViewColumn *tree_column,
                                 GtkCellRenderer *cell,
                                 GtkTreeModel *model, GtkTreeIter *iter,
                                 gpointer ia);
@@@ -1120,7 -1121,7 +1120,7 @@@ init_separators_page (struct import_ass
  
    set_separators (ia);
    set_quote_list (GTK_COMBO_BOX_ENTRY (p->quote_combo));
 -  p->fields_tree_view = GTK_TREE_VIEW (get_widget_assert (builder, "fields"));
 +  p->fields_tree_view = PSPP_SHEET_VIEW (get_widget_assert (builder, "fields"));
    g_signal_connect (p->quote_combo, "changed",
                      G_CALLBACK (on_quote_combo_change), ia);
    g_signal_connect (p->quote_cb, "toggled",
@@@ -1545,7 -1546,7 +1545,7 @@@ on_separator_toggle (GtkToggleButton *t
  /* Called to render one of the cells in the fields preview tree
     view. */
  static void
 -render_input_cell (GtkTreeViewColumn *tree_column, GtkCellRenderer *cell,
 +render_input_cell (PsppSheetViewColumn *tree_column, GtkCellRenderer *cell,
                     GtkTreeModel *model, GtkTreeIter *iter,
                     gpointer ia_)
  {
@@@ -1611,7 -1612,7 +1611,7 @@@ init_formats_page (struct import_assist
  
    p->page = add_page_to_assistant (ia, get_widget_assert (builder, "Formats"),
                                     GTK_ASSISTANT_PAGE_CONFIRM);
 -  p->data_tree_view = GTK_TREE_VIEW (get_widget_assert (builder, "data"));
 +  p->data_tree_view = PSPP_SHEET_VIEW (get_widget_assert (builder, "data"));
    p->modified_vars = NULL;
    p->modified_var_cnt = 0;
    p->dict = NULL;
@@@ -1625,7 -1626,7 +1625,7 @@@ destroy_formats_page (struct import_ass
  
    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);
@@@ -1638,6 -1639,7 +1638,6 @@@ prepare_formats_page (struct import_ass
  {
    struct dictionary *dict;
    PsppireDict *psppire_dict;
 -  PsppireVarStore *var_store;
    GtkBin *vars_scroller;
    GtkWidget *old_var_sheet;
    PsppireVarSheet *var_sheet;
       psppire_dict for now, but it should.  After it does, we
       should g_object_ref the psppire_dict here, since we also
       hold a reference via ia->formats.dict. */
 -  var_store = psppire_var_store_new (psppire_dict);
 -  g_object_set (var_store,
 -                "format-type", PSPPIRE_VAR_STORE_INPUT_FORMATS,
 -                (void *) NULL);
    var_sheet = PSPPIRE_VAR_SHEET (psppire_var_sheet_new ());
    g_object_set (var_sheet,
 -                "model", var_store,
 +                "dictionary", psppire_dict,
                  "may-create-vars", FALSE,
 +                "may-delete-vars", FALSE,
 +                "format-use", FMT_FOR_INPUT,
 +                "enable-grid-lines", PSPP_SHEET_VIEW_GRID_LINES_BOTH,
                  (void *) NULL);
  
    vars_scroller = GTK_BIN (get_widget_assert (ia->asst.builder, "vars-scroller"));
@@@ -1761,14 -1764,14 +1761,14 @@@ on_variable_change (PsppireDict *dict, 
                      struct import_assistant *ia)
  {
    struct formats_page *p = &ia->formats;
 -  GtkTreeView *tv = ia->formats.data_tree_view;
 +  PsppSheetView *tv = ia->formats.data_tree_view;
    gint column_idx = dict_idx + 1;
  
    push_watch_cursor (ia);
  
    /* Remove previous column and replace with new column. */
 -  gtk_tree_view_remove_column (tv, gtk_tree_view_get_column (tv, column_idx));
 -  gtk_tree_view_insert_column (tv, make_data_column (ia, tv, false, dict_idx),
 +  pspp_sheet_view_remove_column (tv, pspp_sheet_view_get_column (tv, column_idx));
 +  pspp_sheet_view_insert_column (tv, make_data_column (ia, tv, false, dict_idx),
                                 column_idx);
  
    /* Save a copy of the modified variable in modified_vars, so
@@@ -1856,7 -1859,7 +1856,7 @@@ parse_field (struct import_assistant *i
  /* Called to render one of the cells in the data preview tree
     view. */
  static void
 -render_output_cell (GtkTreeViewColumn *tree_column,
 +render_output_cell (PsppSheetViewColumn *tree_column,
                      GtkCellRenderer *cell,
                      GtkTreeModel *model,
                      GtkTreeIter *iter,
@@@ -1916,11 -1919,11 +1916,11 @@@ get_tooltip_location (GtkWidget *widget
                        const struct import_assistant *ia,
                        size_t *row, size_t *column)
  {
 -  GtkTreeView *tree_view = GTK_TREE_VIEW (widget);
 +  PsppSheetView *tree_view = PSPP_SHEET_VIEW (widget);
    gint bx, by;
    GtkTreePath *path;
    GtkTreeIter iter;
 -  GtkTreeViewColumn *tree_column;
 +  PsppSheetViewColumn *tree_column;
    GtkTreeModel *tree_model;
    bool ok;
  
    if (!gtk_widget_get_mapped (widget))
      return FALSE;
  
 -  gtk_tree_view_convert_widget_to_bin_window_coords (tree_view,
 +  pspp_sheet_view_convert_widget_to_bin_window_coords (tree_view,
                                                       wx, wy, &bx, &by);
 -  if (!gtk_tree_view_get_path_at_pos (tree_view, bx, by,
 +  if (!pspp_sheet_view_get_path_at_pos (tree_view, bx, by,
                                        &path, &tree_column, NULL, NULL))
      return FALSE;
  
    *column = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (tree_column),
                                                  "column-number"));
  
 -  tree_model = gtk_tree_view_get_model (tree_view);
 +  tree_model = pspp_sheet_view_get_model (tree_view);
    ok = gtk_tree_model_get_iter (tree_model, &iter, path);
    gtk_tree_path_free (path);
    if (!ok)
  static void
  make_tree_view (const struct import_assistant *ia,
                  size_t first_line,
 -                GtkTreeView **tree_view)
 +                PsppSheetView **tree_view)
  {
    GtkTreeModel *model;
  
 -  *tree_view = GTK_TREE_VIEW (gtk_tree_view_new ());
 +  *tree_view = PSPP_SHEET_VIEW (pspp_sheet_view_new ());
 +  pspp_sheet_view_set_grid_lines (*tree_view, PSPP_SHEET_VIEW_GRID_LINES_BOTH);
    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);
 +  pspp_sheet_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,
 +render_line_number (PsppSheetViewColumn *tree_column,
                      GtkCellRenderer *cell,
                      GtkTreeModel *tree_model,
                      GtkTreeIter *iter,
  
  static void
  add_line_number_column (const struct import_assistant *ia,
 -                        GtkTreeView *treeview)
 +                        PsppSheetView *treeview)
  {
 -  GtkTreeViewColumn *column;
 +  PsppSheetViewColumn *column;
  
 -  column = gtk_tree_view_column_new_with_attributes (
 +  column = pspp_sheet_view_column_new_with_attributes (
      _("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 (
 +  pspp_sheet_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);
 +  pspp_sheet_view_column_set_resizable (column, TRUE);
 +  pspp_sheet_view_column_set_cell_data_func (column, ia->asst.prop_renderer,
 +                                             render_line_number, NULL, NULL);
 +  pspp_sheet_view_append_column (treeview, column);
  }
  
  static gint
 -get_monospace_width (GtkTreeView *treeview, GtkCellRenderer *renderer,
 +get_monospace_width (PsppSheetView *treeview, GtkCellRenderer *renderer,
                       size_t char_cnt)
  {
    struct string s;
  }
  
  static gint
 -get_string_width (GtkTreeView *treeview, GtkCellRenderer *renderer,
 +get_string_width (PsppSheetView *treeview, GtkCellRenderer *renderer,
                    const char *string)
  {
    gint width;
    return width;
  }
  
 -static GtkTreeViewColumn *
 -make_data_column (struct import_assistant *ia, GtkTreeView *tree_view,
 +static PsppSheetViewColumn *
 +make_data_column (struct import_assistant *ia, PsppSheetView *tree_view,
                    bool input, gint dict_idx)
  {
    struct variable *var = NULL;
    struct column *column = NULL;
    size_t char_cnt;
    gint content_width, header_width;
 -  GtkTreeViewColumn *tree_column;
 +  PsppSheetViewColumn *tree_column;
    char *name;
  
    if (input)
    header_width = get_string_width (tree_view, ia->asst.prop_renderer,
                                     name);
  
 -  tree_column = gtk_tree_view_column_new ();
 +  tree_column = pspp_sheet_view_column_new ();
    g_object_set_data (G_OBJECT (tree_column), "column-number",
                       GINT_TO_POINTER (dict_idx));
 -  gtk_tree_view_column_set_title (tree_column, name);
 -  gtk_tree_view_column_pack_start (tree_column, ia->asst.fixed_renderer,
 +  pspp_sheet_view_column_set_title (tree_column, name);
 +  pspp_sheet_view_column_pack_start (tree_column, ia->asst.fixed_renderer,
                                     FALSE);
 -  gtk_tree_view_column_set_cell_data_func (
 +  pspp_sheet_view_column_set_cell_data_func (
      tree_column, ia->asst.fixed_renderer,
      input ? render_input_cell : render_output_cell, ia, NULL);
 -  gtk_tree_view_column_set_sizing (tree_column, GTK_TREE_VIEW_COLUMN_FIXED);
 -  gtk_tree_view_column_set_fixed_width (tree_column, MAX (content_width,
 +  pspp_sheet_view_column_set_fixed_width (tree_column, MAX (content_width,
                                                            header_width));
 +  pspp_sheet_view_column_set_resizable (tree_column, TRUE);
  
    free (name);
  
    return tree_column;
  }
  
 -static GtkTreeView *
 +static PsppSheetView *
  create_data_tree_view (bool input, GtkContainer *parent,
                         struct import_assistant *ia)
  {
 -  GtkTreeView *tree_view;
 +  PsppSheetView *tree_view;
    gint i;
  
    make_tree_view (ia, ia->first_line.skip_lines, &tree_view);
 -  gtk_tree_selection_set_mode (gtk_tree_view_get_selection (tree_view),
 -                               GTK_SELECTION_NONE);
 +  pspp_sheet_selection_set_mode (pspp_sheet_view_get_selection (tree_view),
 +                               PSPP_SHEET_SELECTION_NONE);
  
    for (i = 0; i < ia->separators.column_cnt; i++)
 -    gtk_tree_view_append_column (tree_view,
 +    pspp_sheet_view_append_column (tree_view,
                                   make_data_column (ia, tree_view, input, i));
  
    g_object_set (G_OBJECT (tree_view), "has-tooltip", TRUE, (void *) NULL);
    g_signal_connect (tree_view, "query-tooltip",
                      G_CALLBACK (input ? on_query_input_tooltip
                                  : on_query_output_tooltip), ia);
 -  gtk_tree_view_set_fixed_height_mode (tree_view, true);
  
    gtk_container_add (parent, GTK_WIDGET (tree_view));
    gtk_widget_show (GTK_WIDGET (tree_view));