psppire-var-view: Fix constness error.
[pspp] / src / ui / gui / psppire-var-view.c
index 2a9ebf2e33a7c7a9a65e4d54338e8afb98a1167a..13db8e60e4c0cd2c78866cc4ac2cc07e9c625b18 100644 (file)
@@ -1,5 +1,5 @@
 /* PSPPIRE - a graphical user interface for PSPP.
-   Copyright (C) 2009  Free Software Foundation
+   Copyright (C) 2009, 2010, 2011  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 <config.h>
 
-#include <gtk/gtktreeview.h>
-#include <gtk/gtkcellrenderertext.h>
+#include <gtk/gtk.h>
 #include "psppire-var-view.h"
 #include "psppire-var-ptr.h"
+#include "psppire-select-dest.h"
 
+#include <libpspp/cast.h>
+#include <libpspp/str.h>
 #include <data/variable.h>
 
 #include <gettext.h>
@@ -32,6 +34,35 @@ static void psppire_var_view_base_init     (PsppireVarViewClass *class);
 static void psppire_var_view_class_init    (PsppireVarViewClass *class);
 static void psppire_var_view_init          (PsppireVarView      *var_view);
 
+/* Returns TRUE iff VV contains the item V.
+   V must be an initialised value containing a
+   PSPPIRE_VAR_PTR_TYPE.
+*/
+static gboolean
+var_view_contains_var (PsppireSelectDestWidget *sdm, const GValue *v)
+{
+  gboolean ok;
+  GtkTreeIter iter;
+  PsppireVarView *vv = PSPPIRE_VAR_VIEW (sdm);
+  g_return_val_if_fail (G_VALUE_HOLDS (v, PSPPIRE_VAR_PTR_TYPE), FALSE);
+
+  for (ok = psppire_var_view_get_iter_first (vv, &iter);
+       ok;
+       ok = psppire_var_view_get_iter_next (vv, &iter))
+    {
+      const struct variable *var = psppire_var_view_get_variable (vv, 0, &iter);
+      if (var == g_value_get_boxed (v))
+       return TRUE;
+    }
+
+  return FALSE;
+}
+
+static void
+model_init (PsppireSelectDestWidgetIface *iface)
+{
+  iface->contains_var = var_view_contains_var;
+}
 
 GType
 psppire_var_view_get_type (void)
@@ -53,22 +84,43 @@ psppire_var_view_get_type (void)
        (GInstanceInitFunc) psppire_var_view_init,
       };
 
+      static const GInterfaceInfo var_view_model_info = {
+       (GInterfaceInitFunc) model_init, /* Fill this in */
+       NULL,
+       NULL
+      };
+
       psppire_var_view_type =
        g_type_register_static (GTK_TYPE_TREE_VIEW, "PsppireVarView",
                                &psppire_var_view_info, 0);
+
+      g_type_add_interface_static (psppire_var_view_type,
+                                  PSPPIRE_TYPE_SELECT_DEST_WIDGET,
+                                  &var_view_model_info);
     }
 
   return psppire_var_view_type;
 }
 
+void 
+psppire_var_view_clear (PsppireVarView *vv)
+{
+  GtkListStore *l = gtk_list_store_newv  (vv->n_cols, vv->cols);
+
+  gtk_tree_view_set_model (GTK_TREE_VIEW (vv), GTK_TREE_MODEL (l));
+}
+
 
 static void
 psppire_var_view_finalize (GObject *object)
 {
   PsppireVarView *var_view = PSPPIRE_VAR_VIEW (object);
   g_free (var_view->nums);
+  g_free (var_view->cols);
 }
 
+
+
 /* Properties */
 enum
 {
@@ -101,7 +153,7 @@ display_cell_var_name (GtkTreeViewColumn *tree_column,
 
   g_value_unset (&value);
 
-  g_object_set (cell, "text", var_get_name (var), NULL);
+  g_object_set (cell, "text", var ? var_get_name (var) : "", NULL);
 }
 
 
@@ -116,7 +168,7 @@ psppire_var_view_get_property (GObject         *object,
   switch (prop_id)
     {
     case PROP_N_COLS:
-      g_value_set_int (value,  gtk_tree_model_iter_n_children (GTK_TREE_MODEL (var_view->list), NULL));
+      g_value_set_int (value,  var_view->n_cols);
       break;
     default:
       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
@@ -124,6 +176,43 @@ psppire_var_view_get_property (GObject         *object,
     };
 }
 
+static void
+set_renderers (PsppireVarView *var_view)
+{
+  gint c;
+  var_view->nums = g_malloc (sizeof *var_view->nums * var_view->n_cols);
+  
+  for (c = 0 ; c < var_view->n_cols; ++c)
+    {
+      GtkCellRenderer *renderer = gtk_cell_renderer_text_new ();
+      GtkTreeViewColumn *col = gtk_tree_view_column_new ();
+      
+      gchar *label = g_strdup_printf (_("Var%d"), c + 1);
+      
+      gtk_tree_view_column_set_min_width (col, 100);
+      gtk_tree_view_column_set_sizing (col, GTK_TREE_VIEW_COLUMN_FIXED);
+      gtk_tree_view_column_set_resizable (col, TRUE);
+      gtk_tree_view_column_set_title (col, label);
+      
+      g_free (label);
+      
+      var_view->nums[c] = c;
+      
+      gtk_tree_view_column_pack_start (col, renderer, TRUE);
+      gtk_tree_view_column_set_cell_data_func (col, renderer,
+                                              display_cell_var_name,
+                                              &var_view->nums[c], 0);
+      
+      gtk_tree_view_append_column (GTK_TREE_VIEW (var_view), col);
+    }
+}
+
+
+GtkTreeModel *
+psppire_var_view_get_current_model (PsppireVarView *vv)
+{
+  return gtk_tree_view_get_model (GTK_TREE_VIEW (vv));
+}
 
 static void
 psppire_var_view_set_property (GObject         *object,
@@ -137,42 +226,17 @@ psppire_var_view_set_property (GObject         *object,
     {
     case PROP_N_COLS:
       {
-       gint n_cols = g_value_get_int (value);
        gint c;
+       var_view->n_cols = g_value_get_int (value);
 
+       var_view->cols = xrealloc (var_view->cols, sizeof (GType) *  var_view->n_cols);
 
-       GType *array = g_alloca (sizeof (GType) *  n_cols);
-
-       var_view->nums = g_malloc (sizeof *var_view->nums * n_cols);
-
-       for (c = 0 ; c < n_cols; ++c)
-       {
-         GtkCellRenderer *renderer = gtk_cell_renderer_text_new ();
-         GtkTreeViewColumn *col = gtk_tree_view_column_new ();
+       for (c = 0 ; c < var_view->n_cols; ++c)
+         var_view->cols[c] = PSPPIRE_VAR_PTR_TYPE;
 
-         gchar *label = g_strdup_printf (_("Var%d"), c + 1);
-
-         gtk_tree_view_column_set_min_width (col, 100);
-         gtk_tree_view_column_set_sizing (col, GTK_TREE_VIEW_COLUMN_FIXED);
-         gtk_tree_view_column_set_resizable (col, TRUE);
-         gtk_tree_view_column_set_title (col, label);
-
-         g_free (label);
-
-         var_view->nums[c] = c;
-
-         gtk_tree_view_column_pack_start (col, renderer, TRUE);
-         gtk_tree_view_column_set_cell_data_func (col, renderer,
-                                                  display_cell_var_name,
-                                                  &var_view->nums[c], 0);
-
-         gtk_tree_view_append_column (GTK_TREE_VIEW (var_view), col);
-         array[c] = PSPPIRE_VAR_PTR_TYPE;
-       }
+       set_renderers (var_view);
 
-       /* Set a model, which is an GtkListStore of gpointers which point to a variable */
-       var_view->list = gtk_list_store_newv  (n_cols, array);
-       gtk_tree_view_set_model (GTK_TREE_VIEW (var_view), GTK_TREE_MODEL (var_view->list));
+       psppire_var_view_clear (var_view);
       }
       break;
     default:
@@ -207,6 +271,7 @@ psppire_var_view_class_init (PsppireVarViewClass *class)
 static void
 psppire_var_view_base_init (PsppireVarViewClass *class)
 {
+
   GObjectClass *object_class = G_OBJECT_CLASS (class);
 
   object_class->finalize = psppire_var_view_finalize;
@@ -223,8 +288,12 @@ psppire_var_view_base_finalize (PsppireVarViewClass *class,
 
 
 static void
-psppire_var_view_init (PsppireVarView *var_view)
+psppire_var_view_init (PsppireVarView *vv)
 {
+  GtkTreeSelection* selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (vv));
+  vv->cols = 0;
+
+  gtk_tree_selection_set_mode (selection, GTK_SELECTION_MULTIPLE);
 }
 
 
@@ -238,26 +307,29 @@ psppire_var_view_new (void)
 gboolean
 psppire_var_view_get_iter_first (PsppireVarView *vv, GtkTreeIter *iter)
 {
-  return gtk_tree_model_get_iter_first (GTK_TREE_MODEL (vv->list), iter);
+  GtkTreeIter dummy;
+  GtkTreeModel *model = gtk_tree_view_get_model (GTK_TREE_VIEW (vv));
+  return gtk_tree_model_get_iter_first (model, iter ? iter : &dummy);
 }
 
 gboolean
 psppire_var_view_get_iter_next (PsppireVarView *vv, GtkTreeIter *iter)
 {
-  return gtk_tree_model_iter_next (GTK_TREE_MODEL (vv->list), iter);
+  GtkTreeModel *model = gtk_tree_view_get_model (GTK_TREE_VIEW (vv));
+  return gtk_tree_model_iter_next (model, iter);
 }
 
 const struct variable *
-psppire_var_view_get_variable (PsppireVarView *vv, gint column, GtkTreeIter *iter)
+psppire_var_view_get_var_from_model (GtkTreeModel *model, gint column, GtkTreeIter *iter)
 {
   const struct variable *var = NULL;
   GValue value = {0};
-  gtk_tree_model_get_value (GTK_TREE_MODEL (vv->list), iter, column, &value);
+  gtk_tree_model_get_value (model, iter, column, &value);
 
   if ( G_VALUE_TYPE (&value) == PSPPIRE_VAR_PTR_TYPE)
     var = g_value_get_boxed (&value);
   else
-    g_critical ("Unsupported type \"%s\", in variable name treeview.",
+    g_critical ("Unsupported type `%s', in variable name treeview.",
                G_VALUE_TYPE_NAME (&value));
 
   g_value_unset (&value);
@@ -265,6 +337,15 @@ psppire_var_view_get_variable (PsppireVarView *vv, gint column, GtkTreeIter *ite
   return var;
 }
 
+const struct variable *
+psppire_var_view_get_variable (PsppireVarView *vv, gint column, GtkTreeIter *iter)
+{
+  GtkTreeModel *model = gtk_tree_view_get_model (GTK_TREE_VIEW (vv));
+  return psppire_var_view_get_var_from_model (model, column, iter);
+}
+
+
+
 /*
   Append the names of selected variables to STRING.
   Returns the number of variables appended.
@@ -291,26 +372,57 @@ psppire_var_view_append_names (PsppireVarView *vv, gint column, GString *string)
   return n_vars;
 }
 
-/* Returns TRUE iff VV contains the item V.
-   V must be an initialised value containing a
-   PSPPIRE_VAR_PTR_TYPE.
+/* Return a linked list of struct variables which are
+   contained in VV.
+   The caller is responsible for freeing the returned list.
+   The variables however are owned by their dictionary
+   and should not be freed.
+  */
+GSList *
+psppire_var_view_list_names (PsppireVarView *vv, gint column)
+{
+  GtkTreeIter iter;
+  GSList *list = NULL;
+  
+  if ( psppire_var_view_get_iter_first (vv, &iter) )
+    {
+      do
+       {
+         const struct variable *var = psppire_var_view_get_variable (vv, column, &iter);
+         list = g_slist_prepend (list, CONST_CAST (struct variable *, var));
+       }
+      while (psppire_var_view_get_iter_next (vv, &iter));
+    }
+
+  return list;
+}
+
+
+/*
+  Append the names of selected variables to STR
+  Returns the number of variables appended.
 */
-gboolean
-psppire_var_view_contains_var (PsppireVarView *vv, const GValue *v)
+gint 
+psppire_var_view_append_names_str (PsppireVarView *vv, gint column, struct string *str)
 {
-  gboolean ok;
+  gint n_vars = 0;
   GtkTreeIter iter;
-  g_return_val_if_fail (G_VALUE_HOLDS (v, PSPPIRE_VAR_PTR_TYPE), FALSE);
 
-  for (ok = psppire_var_view_get_iter_first (vv, &iter);
-       ok;
-       ok = psppire_var_view_get_iter_next (vv, &iter))
+  if ( psppire_var_view_get_iter_first (vv, &iter) )
     {
-      const struct variable *var = psppire_var_view_get_variable (vv, 0, &iter);
-      if (var == g_value_get_boxed (v))
-       return TRUE;
+      do
+       {
+         const struct variable *var = psppire_var_view_get_variable (vv, column, &iter);
+         ds_put_cstr (str, " ");
+         ds_put_cstr (str, var_get_name (var));
+
+         n_vars++;
+       }
+      while (psppire_var_view_get_iter_next (vv, &iter));
     }
 
-  return FALSE;
+  return n_vars;
 }
 
+
+