Reference count struct dictionary.
[pspp] / src / ui / gui / psppire-import-assistant.c
index f4f41efa64dee7b611f14a3d0aa3c3c5cd8ee99f..e376bacc7e667cf3ae9076d071c193fa940936ea 100644 (file)
@@ -1,5 +1,5 @@
 /* PSPPIRE - a graphical user interface for PSPP.
-   Copyright (C) 2015, 2016, 2017  Free Software Foundation
+   Copyright (C) 2015, 2016, 2017, 2018  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
@@ -127,6 +127,8 @@ psppire_import_assistant_finalize (GObject *object)
 
   ds_destroy (&ia->quotes);
 
+  dict_unref (ia->dict);
+
   g_object_unref (ia->builder);
 
   ia->response = -1;
@@ -189,16 +191,17 @@ struct separator
 /* All the separators in the dialog box. */
 static const struct separator separators[] =
   {
-    {"space", ' '},
-    {"tab", '\t'},
-    {"bang", '!'},
-    {"colon", ':'},
-    {"comma", ','},
-    {"hyphen", '-'},
-    {"pipe", '|'},
+    {"space",     ' '},
+    {"tab",       '\t'},
+    {"bang",      '!'},
+    {"colon",     ':'},
+    {"comma",     ','},
+    {"hyphen",    '-'},
+    {"pipe",      '|'},
     {"semicolon", ';'},
-    {"slash", '/'},
+    {"slash",     '/'},
   };
+
 #define SEPARATOR_CNT (sizeof separators / sizeof *separators)
 
 struct separator_count_node
@@ -310,7 +313,8 @@ repopulate_delimiter_columns (PsppireImportAssistant *ia)
       gtk_tree_view_remove_column (GTK_TREE_VIEW (ia->fields_tree_view), tvc);
     }
 
-  gint n_fields = gtk_tree_model_get_n_columns (ia->delimiters_model);
+  gint n_fields =
+    gtk_tree_model_get_n_columns (GTK_TREE_MODEL (ia->delimiters_model));
 
   /* ... and put them back again. */
   gint f;
@@ -370,9 +374,10 @@ reset_tree_view_model (PsppireImportAssistant *ia)
 static void
 prepare_separators_page (PsppireImportAssistant *ia, GtkWidget *page)
 {
-  gtk_tree_view_set_model (GTK_TREE_VIEW (ia->fields_tree_view), ia->delimiters_model);
+  gtk_tree_view_set_model (GTK_TREE_VIEW (ia->fields_tree_view),
+                          GTK_TREE_MODEL (ia->delimiters_model));
 
-  g_signal_connect_swapped (ia->delimiters_model, "notify::delimiters",
+  g_signal_connect_swapped (GTK_TREE_MODEL (ia->delimiters_model), "notify::delimiters",
                        G_CALLBACK (reset_tree_view_model), ia);
 
 
@@ -820,7 +825,6 @@ render_text_preview_line (GtkTreeViewColumn *tree_column,
      Set the text  to a "insensitive" state if the row
      is greater than what the user declared to be the maximum.
   */
-  PsppireImportAssistant *ia = PSPPIRE_IMPORT_ASSISTANT (data);
   GtkTreePath *path = gtk_tree_model_get_path (tree_model, iter);
   gint *ii = gtk_tree_path_get_indices (path);
   gint max_lines;
@@ -845,6 +849,7 @@ first_line_page_create (PsppireImportAssistant *ia)
   if (ia->first_line_tree_view == NULL)
     {
       ia->first_line_tree_view = gtk_tree_view_new ();
+      g_object_set (ia->first_line_tree_view, "enable-search", FALSE, NULL);
 
       gtk_tree_view_set_headers_visible (GTK_TREE_VIEW (ia->first_line_tree_view), TRUE);
 
@@ -1045,8 +1050,6 @@ set_quote_list (GtkComboBox *cb)
   gtk_combo_box_set_entry_text_column (cb, 0);
 }
 
-
-
 /* Chooses a name for each column on the separators page */
 static void
 choose_column_names (PsppireImportAssistant *ia)
@@ -1055,7 +1058,9 @@ choose_column_names (PsppireImportAssistant *ia)
   unsigned long int generated_name_count = 0;
   dict_clear (ia->dict);
 
-  for (i = 0; i < gtk_tree_model_get_n_columns (ia->delimiters_model) - 1; ++i)
+  for (i = 0;
+       i < gtk_tree_model_get_n_columns (GTK_TREE_MODEL (ia->delimiters_model)) - 1;
+       ++i)
     {
       const gchar *candidate_name = NULL;
 
@@ -1073,8 +1078,6 @@ choose_column_names (PsppireImportAssistant *ia)
     }
 }
 
-
-
 /* Called when the user toggles one of the separators
    checkboxes. */
 static void
@@ -1165,6 +1168,7 @@ separators_page_create (PsppireImportAssistant *ia)
     {
       GtkWidget *scroller = get_widget_assert (ia->builder, "fields-scroller");
       ia->fields_tree_view = gtk_tree_view_new ();
+      g_object_set (ia->fields_tree_view, "enable-search", FALSE, NULL);
       gtk_container_add (GTK_CONTAINER (scroller), GTK_WIDGET (ia->fields_tree_view));
       gtk_widget_show_all (scroller);
     }
@@ -1214,16 +1218,18 @@ my_read (struct casereader *reader, void *aux, casenumber idx)
          const struct variable *var = dict_get_var (ia->dict, i);
 
          const gchar *ss = g_value_get_string (&value);
-
-         union value *v = case_data_rw (c, var);
-         char *xx = data_in (ss_cstr (ss),
-                             "UTF-8",
-                             var_get_write_format (var)->type,
-                             v, var_get_width (var), "UTF-8");
-
-         /* if (xx) */
-         /*   g_print ("%s:%d Err %s\n", __FILE__, __LINE__, xx); */
-         free (xx);
+         if (ss)
+           {
+             union value *v = case_data_rw (c, var);
+             char *xx = data_in (ss_cstr (ss),
+                                 "UTF-8",
+                                 var_get_write_format (var)->type,
+                                 v, var_get_width (var), "UTF-8");
+
+             /* if (xx) */
+             /*   g_print ("%s:%d Err %s\n", __FILE__, __LINE__, xx); */
+             free (xx);
+           }
          g_value_unset (&value);
        }
     }
@@ -1245,103 +1251,98 @@ my_advance (struct casereader *reader, void *aux, casenumber cnt)
   g_print ("%s:%d\n", __FILE__, __LINE__);
 }
 
-static void
-foo (struct dictionary *dict, void *aux)
-{
-  PsppireImportAssistant *ia = PSPPIRE_IMPORT_ASSISTANT (aux);
-  g_print ("%s:%d\n", __FILE__, __LINE__);
-
-  struct caseproto *proto = caseproto_create ();
-
-  int i;
-  for (i = 0 ; i < dict_get_var_cnt (ia->dict); ++i)
-    {
-      const struct variable *var = dict_get_var (ia->dict, i);
-      proto = caseproto_add_width (proto, var_get_width (var));
-    }
-
-
-  gint n_rows = gtk_tree_model_iter_n_children (ia->delimiters_model, NULL);
-
-  struct casereader *reader =
-    casereader_create_random (proto, n_rows, &my_casereader_class,  ia);
-
-
-  PsppireDataStore *store = NULL;
-
-  g_object_get (ia->data_sheet, "data-model", &store, NULL);
-
-  psppire_data_store_set_reader (store, reader);
-}
-
 /* Called just before the formats page of the assistant is
    displayed. */
 static void
 prepare_formats_page (PsppireImportAssistant *ia)
 {
-  PsppireDict *dict = psppire_dict_new_from_dict (ia->dict);
-  g_object_set (ia->var_sheet, "data-model", dict, NULL);
-
   my_casereader_class.read = my_read;
   my_casereader_class.destroy = my_destroy;
   my_casereader_class.advance = my_advance;
 
-  struct caseproto *proto = caseproto_create ();
-  int i;
-
-  struct fmt_guesser **fg = xcalloc (sizeof *fg, dict_get_var_cnt (ia->dict));
-  for (i = 0 ; i < dict_get_var_cnt (ia->dict); ++i)
+  if (ia->spreadsheet)
     {
-      fg[i] = fmt_guesser_create ();
+      GtkBuilder *builder = ia->builder;
+      GtkWidget *range_entry = get_widget_assert (builder, "cell-range-entry");
+      GtkWidget *rnc = get_widget_assert (builder, "readnames-checkbox");
+      GtkWidget *combo_box = get_widget_assert (builder, "sheet-entry");
+
+      struct spreadsheet_read_options opts;
+      opts.sheet_name = NULL;
+      opts.sheet_index = gtk_combo_box_get_active (GTK_COMBO_BOX (combo_box)) + 1;
+      opts.read_names = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (rnc));
+      opts.cell_range = g_strdup (gtk_entry_get_text (GTK_ENTRY (range_entry)));
+      opts.asw = 8;
+
+      struct casereader *reader = spreadsheet_make_reader (ia->spreadsheet, &opts);
+
+      PsppireDict *dict = psppire_dict_new_from_dict (ia->spreadsheet->dict);
+      PsppireDataStore *store = psppire_data_store_new (dict);
+      psppire_data_store_set_reader (store, reader);
+      g_object_set (ia->data_sheet, "data-model", store, NULL);
+      g_object_set (ia->var_sheet, "data-model", dict, NULL);
     }
+  else
+    {
+      PsppireDict *dict = psppire_dict_new_from_dict (ia->dict);
+      g_object_set (ia->var_sheet, "data-model", dict, NULL);
 
-  gint n_rows = gtk_tree_model_iter_n_children (ia->delimiters_model, NULL);
+      int i;
 
-  GtkTreeIter iter;
-  gboolean ok;
-  for (ok = gtk_tree_model_get_iter_first (ia->delimiters_model, &iter);
-       ok;
-       ok = gtk_tree_model_iter_next (ia->delimiters_model, &iter))
-    {
+      struct fmt_guesser **fg = xcalloc (sizeof *fg, dict_get_var_cnt (ia->dict));
       for (i = 0 ; i < dict_get_var_cnt (ia->dict); ++i)
        {
-         gchar *s = NULL;
-         gtk_tree_model_get (ia->delimiters_model, &iter, i+1, &s, -1);
-         fmt_guesser_add (fg[i], ss_cstr (s));
-         free (s);
+         fg[i] = fmt_guesser_create ();
        }
-    }
 
-  for (i = 0 ; i < dict_get_var_cnt (ia->dict); ++i)
-    {
-      struct fmt_spec fs;
-      fmt_guesser_guess (fg[i], &fs);
+      gint n_rows = gtk_tree_model_iter_n_children (GTK_TREE_MODEL (ia->delimiters_model), NULL);
 
-      fmt_fix (&fs, FMT_FOR_INPUT);
+      GtkTreeIter iter;
+      gboolean ok;
+      for (ok = gtk_tree_model_get_iter_first (GTK_TREE_MODEL (ia->delimiters_model), &iter);
+          ok;
+          ok = gtk_tree_model_iter_next (GTK_TREE_MODEL (ia->delimiters_model), &iter))
+       {
+         for (i = 0 ; i < dict_get_var_cnt (ia->dict); ++i)
+           {
+             gchar *s = NULL;
+             gtk_tree_model_get (GTK_TREE_MODEL (ia->delimiters_model), &iter, i+1, &s, -1);
+             if (s)
+               fmt_guesser_add (fg[i], ss_cstr (s));
+             free (s);
+           }
+       }
 
-      struct variable *var = dict_get_var (ia->dict, i);
+      struct caseproto *proto = caseproto_create ();
+      for (i = 0 ; i < dict_get_var_cnt (ia->dict); ++i)
+       {
+         struct fmt_spec fs;
+         fmt_guesser_guess (fg[i], &fs);
 
-      int width = fmt_var_width (&fs);
+         fmt_fix (&fs, FMT_FOR_INPUT);
 
-      var_set_width_and_formats (var, width,
-                                &fs, &fs);
+         struct variable *var = dict_get_var (ia->dict, i);
 
-      proto = caseproto_add_width (proto, width);
-      fmt_guesser_destroy (fg[i]);
-    }
+         int width = fmt_var_width (&fs);
 
-  free (fg);
+         var_set_width_and_formats (var, width,
+                                    &fs, &fs);
 
-  //  dict_set_change_callback (ia->dict, foo, ia);
+         proto = caseproto_add_width (proto, width);
+         fmt_guesser_destroy (fg[i]);
+       }
 
-  struct casereader *reader =
-    casereader_create_random (proto, n_rows, &my_casereader_class,  ia);
+      free (fg);
 
-  PsppireDataStore *store = psppire_data_store_new (dict);
-  psppire_data_store_set_reader (store, reader);
+      struct casereader *reader =
+       casereader_create_random (proto, n_rows, &my_casereader_class,  ia);
 
-  g_object_set (ia->data_sheet, "data-model", store, NULL);
+      PsppireDataStore *store = psppire_data_store_new (dict);
+      psppire_data_store_set_reader (store, reader);
 
+      g_object_set (ia->data_sheet, "data-model", store, NULL);
+      caseproto_unref (proto);
+    }
 
   gint pmax;
   g_object_get (get_widget_assert (ia->builder, "vpaned1"),
@@ -1378,6 +1379,7 @@ formats_page_create (PsppireImportAssistant *ia)
   if (ia->data_sheet == NULL)
     {
       ia->data_sheet = psppire_data_sheet_new ();
+      g_object_set (ia->data_sheet, "editable", FALSE, NULL);
 
       gtk_container_add (GTK_CONTAINER (data_scroller), ia->data_sheet);
 
@@ -1452,9 +1454,12 @@ first_line_append_syntax (const PsppireImportAssistant *ia, struct string *s)
 static void
 intro_append_syntax (const PsppireImportAssistant *ia, struct string *s)
 {
+  gint first_line = 0;
+  g_object_get (ia->delimiters_model, "first-line", &first_line, NULL);
+
   if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (ia->n_cases_button)))
-    ds_put_format (s, "N OF CASES %d.\n",
-                  gtk_spin_button_get_value_as_int (GTK_SPIN_BUTTON (ia->n_cases_spin)));
+    ds_put_format (s, "SELECT IF ($CASENUM <= %d).\n",
+                  gtk_spin_button_get_value_as_int (GTK_SPIN_BUTTON (ia->n_cases_spin)) - first_line);
   else if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (ia->percent_button)))
     ds_put_format (s, "SAMPLE %.4g.\n",
                   gtk_spin_button_get_value (GTK_SPIN_BUTTON (ia->percent_spin)) / 100.0);
@@ -1543,8 +1548,8 @@ apply_dict (const struct dictionary *dict, struct string *s)
 
 
 
-static char *
-sheet_spec_gen_syntax (PsppireImportAssistant *ia)
+static void
+sheet_spec_gen_syntax (PsppireImportAssistant *ia, struct string *s)
 {
   GtkBuilder *builder = ia->builder;
   GtkWidget *range_entry = get_widget_assert (builder, "cell-range-entry");
@@ -1554,11 +1559,13 @@ sheet_spec_gen_syntax (PsppireImportAssistant *ia)
   int sheet_index = 1 + gtk_combo_box_get_active (GTK_COMBO_BOX (sheet_entry));
   gboolean read_names = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (rnc));
 
-  struct string s = DS_EMPTY_INITIALIZER;
 
   char *filename;
-  g_object_get (ia->text_file, "file-name", &filename, NULL);
-  syntax_gen_pspp (&s,
+  if (ia->spreadsheet)
+    filename = ia->spreadsheet->file_name;
+  else
+    g_object_get (ia->text_file, "file-name", &filename, NULL);
+  syntax_gen_pspp (s,
                   "GET DATA"
                   "\n  /TYPE=%ss"
                   "\n  /FILE=%sq"
@@ -1571,20 +1578,17 @@ sheet_spec_gen_syntax (PsppireImportAssistant *ia)
 
   if (range && 0 != strcmp ("", range))
     {
-      syntax_gen_pspp (&s,
+      syntax_gen_pspp (s,
                       "\n  /CELLRANGE=RANGE %sq", range);
     }
   else
     {
-      syntax_gen_pspp (&s,
+      syntax_gen_pspp (s,
                       "\n  /CELLRANGE=FULL");
     }
 
 
-  syntax_gen_pspp (&s, ".");
-
-
-  return ds_cstr (&s);
+  syntax_gen_pspp (s, ".\n");
 }
 
 
@@ -1626,7 +1630,7 @@ psppire_import_assistant_generate_syntax (PsppireImportAssistant *ia)
     }
   else
     {
-      return sheet_spec_gen_syntax (ia);
+      sheet_spec_gen_syntax (ia, &s);
     }
 
   return ds_cstr (&s);