Added display sort feature to PsppireDictView
[pspp] / src / ui / gui / dict-display.c
index 356758beeea4100c4f4f1fd3feeaae71ebeb2fb4..6c4e21158fba294a0d9355239d11e8651422c166 100644 (file)
 #include <gettext.h>
 #include <gtk/gtk.h>
 
+#include "psppire-conf.h"
 #include "dict-display.h"
 
 #include "psppire-dict.h"
+#include "psppire-dictview.h"
+#include "psppire-means-layer.h"
+#include "psppire-var-ptr.h"
+#include "psppire-var-view.h"
+#include "psppire-select-dest.h"
+#include <libpspp/i18n.h>
 #include "helper.h"
 #include <data/variable.h>
 #include <data/format.h>
 #define N_(msgid) msgid
 
 
-/* A GtkTreeModelFilterVisibleFunc to filter lines in the treeview */
-static gboolean
-filter_variables (GtkTreeModel *model, GtkTreeIter *iter, gpointer data)
-{
-  var_predicate_func *predicate = data;
-  struct variable *var;
-  PsppireDict *dict = PSPPIRE_DICT (model);
-
-  GtkTreePath *path = gtk_tree_model_get_path (model, iter);
-
-  gint *idx = gtk_tree_path_get_indices (path);
-
-  var =  psppire_dict_get_variable (dict, *idx);
-
-  gtk_tree_path_free (path);
-
-  return predicate (var);
-}
-
-/* A GtkTreeCellDataFunc which sets the icon appropriate to the type
-   of variable */
-static void
-var_icon_cell_data_func (GtkTreeViewColumn *col,
-                      GtkCellRenderer *cell,
-                      GtkTreeModel *model,
-                      GtkTreeIter *iter,
-                      gpointer data)
-{
-  struct variable *var;
-  gtk_tree_model_get (model, iter, DICT_TVM_COL_VAR, &var, -1);
-
-  if ( var_is_alpha (var))
-    {
-      g_object_set (cell, "stock-id", "var-string", NULL);
-    }
-  else
-    {
-      const struct fmt_spec *fs = var_get_write_format (var);
-      int cat = fmt_get_category (fs->type);
-      switch ( var_get_measure (var))
-       {
-       case MEASURE_NOMINAL:
-         g_object_set (cell, "stock-id", "var-nominal", NULL);
-         break;
-       case MEASURE_ORDINAL:
-         g_object_set (cell, "stock-id", "var-ordinal", NULL);
-         break;
-       case MEASURE_SCALE:
-         if ( ( FMT_CAT_DATE | FMT_CAT_TIME ) & cat )
-           g_object_set (cell, "stock-id", "var-date-scale", NULL);
-         else
-           g_object_set (cell, "stock-id", "var-scale", NULL);
-         break;
-       default:
-         g_assert_not_reached ();
-       };
-    }
-}
-
-
 void
 get_base_model (GtkTreeModel *top_model, GtkTreeIter *top_iter,
-               GtkTreeModel **model, GtkTreeIter *iter
-               )
+               GtkTreeModel **model, GtkTreeIter *iter)
 {
   *model = top_model;
-  *iter = *top_iter;
-  while (GTK_IS_TREE_MODEL_FILTER (*model))
-    {
-      GtkTreeIter parent_iter = *iter;
-      GtkTreeModelFilter *parent_model = GTK_TREE_MODEL_FILTER (*model);
-
-      *model = gtk_tree_model_filter_get_model (parent_model);
-
-      gtk_tree_model_filter_convert_iter_to_child_iter (parent_model,
-                                                       iter,
-                                                       &parent_iter);
-    }
-
-  g_assert (PSPPIRE_IS_DICT (*model));
-}
-
-/* A GtkTreeCellDataFunc which renders the name and/or label of the
-   variable */
-static void
-var_description_cell_data_func (GtkTreeViewColumn *col,
-                               GtkCellRenderer *cell,
-                               GtkTreeModel *top_model,
-                               GtkTreeIter *top_iter,
-                               gpointer data)
-{
-  struct variable *var;
-  GtkTreeIter iter;
-  GtkTreeModel *model;
 
+  if ( iter)
+    *iter = *top_iter;
 
-  get_base_model (top_model, top_iter, &model, &iter);
-
-  g_assert (PSPPIRE_IS_DICT (model));
-
-
-  gtk_tree_model_get (model,
-                     &iter, DICT_TVM_COL_VAR, &var, -1);
-
-  if ( var_has_label (var))
-    {
-      gchar *text = g_strdup_printf (
-                                    "<span stretch=\"condensed\">%s</span>",
-                                    var_get_label (var));
-
-
-      char *utf8 = pspp_locale_to_utf8 (text, -1, NULL);
-
-      g_free (text);
-      g_object_set (cell, "markup", utf8, NULL);
-      g_free (utf8);
-    }
-  else
+  while ( ! PSPPIRE_IS_DICT (*model))
     {
-      g_object_set (cell, "text", var_get_name (var), NULL);
-    }
-}
-
-
-#if GTK_CHECK_VERSION (2, 12, 0)
-/* Sets the tooltip to be the name of the variable under the cursor */
-static gboolean
-set_tooltip_for_variable (GtkTreeView  *treeview,
-                         gint        x,
-                         gint        y,
-                         gboolean    keyboard_mode,
-                         GtkTooltip *tooltip,
-                         gpointer    user_data)
-
-{
-  gint bx, by;
-  GtkTreeIter iter;
-  GtkTreePath *path;
-  GtkTreeModel *tree_model;
-  struct variable *var = NULL;
-  gboolean ok;
-
-
-  gtk_tree_view_convert_widget_to_bin_window_coords (treeview,
-                                                     x, y, &bx, &by);
-
-  if (!gtk_tree_view_get_path_at_pos (treeview, bx, by,
-                                      &path, NULL, NULL, NULL))
-    return FALSE;
-
-  tree_model = gtk_tree_view_get_model (treeview);
-
-
-  gtk_tree_view_set_tooltip_row (treeview, tooltip, path);
-
-  ok = gtk_tree_model_get_iter (tree_model, &iter, path);
-
-  gtk_tree_path_free (path);
-  if (!ok)
-    return FALSE;
-
-
-  gtk_tree_model_get (tree_model, &iter, DICT_TVM_COL_VAR,  &var, -1);
-
-  if ( ! var_has_label (var))
-    return FALSE;
-
-  gtk_tooltip_set_text (tooltip, var_get_name (var));
-
-  return TRUE;
-}
-#endif
-
-   /* Sets up TREEVIEW to display the variables of DICT.
-   MODE is the selection mode for TREEVIEW.
-   PREDICATE determines which variables should be visible, or NULL if
-   all are to be visible.
- */
-void
-attach_dictionary_to_treeview (GtkTreeView *treeview, PsppireDict *dict,
-                              GtkSelectionMode mode,
-                              var_predicate_func *predicate
-                              )
-{
-  GtkTreeViewColumn *col;
+      GtkTreeIter parent_iter;
+      if (iter)
+       parent_iter = *iter;
 
-  GtkTreeSelection *selection =
-    gtk_tree_view_get_selection (treeview);
+      if ( GTK_IS_TREE_MODEL_FILTER (*model))
+       {
+         GtkTreeModelFilter *parent_model = GTK_TREE_MODEL_FILTER (*model);
 
-  GtkCellRenderer *renderer;
+         *model = gtk_tree_model_filter_get_model (parent_model);
 
-  GtkTreeModel *model ;
+         if (iter)
+           gtk_tree_model_filter_convert_iter_to_child_iter (parent_model,
+                                                             iter,
+                                                             &parent_iter);
+       }
+      else if (GTK_IS_TREE_MODEL_SORT (*model))
+       {
+         GtkTreeModelSort *parent_model = GTK_TREE_MODEL_SORT (*model);
 
-  if ( predicate )
-    {
-      model = gtk_tree_model_filter_new (GTK_TREE_MODEL (dict),
-                                         NULL);
+         *model = gtk_tree_model_sort_get_model (parent_model);
 
-      gtk_tree_model_filter_set_visible_func (GTK_TREE_MODEL_FILTER (model),
-                                             filter_variables,
-                                             predicate,
-                                             NULL);
+         if (iter)
+           gtk_tree_model_sort_convert_iter_to_child_iter (parent_model,
+                                                           iter,
+                                                           &parent_iter);
+       }
     }
-  else
-    {
-      model = GTK_TREE_MODEL (dict);
-    }
-
-  gtk_tree_view_set_model (GTK_TREE_VIEW (treeview), model);
-
-
-  col = gtk_tree_view_column_new ();
-  gtk_tree_view_column_set_title (col, _("Variable"));
-
-  renderer = gtk_cell_renderer_pixbuf_new ();
-  gtk_tree_view_column_pack_start (col, renderer, FALSE);
-
-  gtk_tree_view_column_set_cell_data_func (col, renderer,
-                                          var_icon_cell_data_func,
-                                          NULL, NULL);
-
-
-  renderer = gtk_cell_renderer_text_new ();
-  gtk_tree_view_column_pack_start (col, renderer, TRUE);
-  gtk_tree_view_column_set_cell_data_func (col, renderer,
-                                          var_description_cell_data_func,
-                                          NULL, NULL);
-
-  g_object_set (renderer, "ellipsize-set", TRUE, NULL);
-  g_object_set (renderer, "ellipsize", PANGO_ELLIPSIZE_MIDDLE, NULL);
-
-  gtk_tree_view_column_set_sizing (col, GTK_TREE_VIEW_COLUMN_FIXED);
-
-  /* FIXME: make this a value in terms of character widths */
-  gtk_tree_view_column_set_min_width (col, 150);
-
-  gtk_tree_view_append_column (treeview, col);
-
-  gtk_tree_selection_set_mode (selection, mode);
-
-  g_object_set (treeview, "has-tooltip", TRUE, NULL);
-
-#if GTK_CHECK_VERSION (2, 12, 0)
-  g_signal_connect (treeview, "query-tooltip", G_CALLBACK (set_tooltip_for_variable), NULL);
-#endif
 }
 
 
@@ -290,7 +90,6 @@ insert_source_row_into_entry (GtkTreeIter iter,
   gint *idx;
   struct variable *var;
   GtkTreeIter dict_iter;
-  gchar *name;
 
   g_return_if_fail (GTK_IS_ENTRY(dest));
 
@@ -304,55 +103,87 @@ insert_source_row_into_entry (GtkTreeIter iter,
 
   gtk_tree_path_free (path);
 
-  name = pspp_locale_to_utf8 (var_get_name (var), -1, NULL);
-  gtk_entry_set_text (GTK_ENTRY (dest),  name);
-  g_free (name);
+  gtk_entry_set_text (GTK_ENTRY (dest),  var_get_name (var));
 }
 
 
 
-void
-insert_source_row_into_tree_view (GtkTreeIter iter,
-                                 GtkWidget *dest,
-                                 GtkTreeModel *model,
-                                 gpointer data
-                                 )
+static void
+insert_source_row_into_tree_model (GtkTreeIter source_iter,
+                                    GtkTreeModel *dest_model,
+                                    GtkTreeModel *source_model,
+                                    gpointer data)
 {
   GtkTreePath *path;
   GtkTreeIter dest_iter;
   GtkTreeIter dict_iter;
   gint *row ;
-  GtkTreeModel *destmodel = gtk_tree_view_get_model ( GTK_TREE_VIEW (dest));
 
+  const struct variable *var;
   GtkTreeModel *dict;
 
-
-  get_base_model (model, &iter, &dict, &dict_iter);
+  get_base_model (source_model, &source_iter, &dict, &dict_iter);
 
   path = gtk_tree_model_get_path (dict, &dict_iter);
 
   row = gtk_tree_path_get_indices (path);
 
-  gtk_list_store_append (GTK_LIST_STORE (destmodel),  &dest_iter);
-  gtk_list_store_set (GTK_LIST_STORE (destmodel), &dest_iter, 0, *row, -1);
+  var = psppire_dict_get_variable (PSPPIRE_DICT (dict), *row);
+
+  gtk_list_store_append (GTK_LIST_STORE (dest_model),  &dest_iter);
+
+  gtk_list_store_set (GTK_LIST_STORE (dest_model), &dest_iter, 0, var, -1);
 
   gtk_tree_path_free (path);
 }
 
 
+
+void
+insert_source_row_into_tree_view (GtkTreeIter iter,
+                                 GtkWidget *dest,
+                                 GtkTreeModel *model,
+                                 gpointer data)
+{
+  GtkTreeModel *destmodel = gtk_tree_view_get_model (GTK_TREE_VIEW (dest));
+
+  insert_source_row_into_tree_model (iter, destmodel, model, data);
+}
+
+
+void
+insert_source_row_into_layers (GtkTreeIter iter,
+                              GtkWidget *dest,
+                              GtkTreeModel *model,
+                              gpointer data)
+{
+  GtkTreeModel *destmodel = psppire_means_layer_get_model (PSPPIRE_MEANS_LAYER (dest));
+
+  insert_source_row_into_tree_model (iter, destmodel, model, data);
+
+  psppire_means_layer_update (PSPPIRE_MEANS_LAYER (dest));
+}
+
+
+
+
 gboolean
 is_currently_in_entry (GtkTreeModel *model, GtkTreeIter *iter,
                       PsppireSelector *selector)
 {
   gboolean result;
-  gchar *name;
   GtkTreeIter dict_iter;
   GtkTreeModel *dict;
   struct variable *var;
   gint dict_index;
   gint *indeces;
   GtkTreePath *path;
-  const gchar *text =   gtk_entry_get_text (GTK_ENTRY (selector->dest));
+  GtkWidget *entry = NULL;
+  const gchar *text = NULL;
+
+  g_object_get (selector, "dest-widget", &entry, NULL);
+
+  text = gtk_entry_get_text (GTK_ENTRY (entry));
 
   get_base_model (model, iter, &dict, &dict_iter);
 
@@ -366,11 +197,38 @@ is_currently_in_entry (GtkTreeModel *model, GtkTreeIter *iter,
 
   gtk_tree_path_free (path);
 
-  name = pspp_locale_to_utf8 (var_get_name (var), -1, NULL);
-  result = ( 0 == strcmp (text, name));
-  g_free (name);
+  result = ( 0 == strcmp (text, var_get_name (var) ));
 
   return result;
 }
 
+gboolean
+is_currently_in_varview (GtkTreeModel *model, GtkTreeIter *iter, PsppireSelector *sel)
+{
+  gboolean ret = false;
+
+  /* First, fetch the variable from the source */
+
+  PsppireDictView *dv = PSPPIRE_DICT_VIEW (sel->source);
+
+  GtkTreePath *path = gtk_tree_model_get_path (model, iter);
+
+  gint *idx = gtk_tree_path_get_indices (path);
+
+  const struct variable *var =  psppire_dict_get_variable (dv->dict, *idx);
+
+
+  /* Now test if that variable exists in the destination */
+
+  GValue value = {0};
+
+  g_value_init (&value, PSPPIRE_VAR_PTR_TYPE);
+  g_value_set_boxed (&value, var);
+
+  ret = psppire_select_dest_widget_contains_var (PSPPIRE_SELECT_DEST_WIDGET (sel->dest), &value);
+
+  g_value_unset (&value);
+
+  return ret ;
+}