Toggle cell on a sorted treeviewcolumn loses selection (sample code)



Hi all
If the column is sorted, when one activates the toggle, the tree is
re-sorted (normal) but the selected row is changed (unexpected). I
investigated and I found that  when clicking on a toggle cell renderer, the
"activate" callback is send which update the treemodel. After re-ordering,
the function gtk_tree_view_button_press is called.  This function checks
which row is under the cursor and selects it. I am looking for a way to trap
this event to keep the selection on the "activated" row (like when one edits
a text)

here is a simple example of the "bug" (toggle the cell of the 3rd row to see
the bug).
<code>
#include <gtk/gtk.h>

/* Treemodel column enum */
enum {
  STRING_COLUMN = 0,
  NUMERIC_COLUMN,
  /*count */
  N_COLUMN
};

/* toggle renderer display function */
static void _is_number_odd (GtkTreeViewColumn *tree_column,
               GtkCellRenderer *cell,
               GtkTreeModel *tree_model,
               GtkTreeIter *iter,
               gpointer data)
{
  gint numeric_data;
  gboolean isOdd;
  gtk_tree_model_get(tree_model, iter, NUMERIC_COLUMN, &numeric_data, -1);
  isOdd =  numeric_data % 2 ? TRUE : FALSE;
  g_object_set(G_OBJECT(cell),
           "active", isOdd, NULL);

}
/* toggle renderer activate callback */
static void _toggle_odd_column (GtkCellRendererToggle *cell_renderer,
                gchar *path,
                GtkListStore* list_store)
{
  gint numeric_data;
  GtkTreeIter iter;
  GtkTreePath* tree_path;
  tree_path =  gtk_tree_path_new_from_string  (path);
  if(  gtk_tree_model_get_iter(GTK_TREE_MODEL(list_store),
                   &iter, tree_path))
    {

      gtk_tree_model_get(GTK_TREE_MODEL(list_store), &iter,
             NUMERIC_COLUMN, &numeric_data,
             -1);
      /*  increment numeric */
      gtk_list_store_set (list_store, &iter,
              NUMERIC_COLUMN, ++numeric_data,
              -1);

    }

}
/* fill the list store model */
static void _fill_model(GtkListStore* list_store)
{
  gint i ;
  GtkTreeIter iter;
  for (i = 0; i < 10; ++i)
    {
      gchar* string_data ;
      gint   numeric_data = i;
      string_data = g_strdup_printf("row number %d", numeric_data);
       /* Add a new row to the model */
      gtk_list_store_append (list_store, &iter);
      gtk_list_store_set (list_store, &iter,
              STRING_COLUMN , string_data,
              NUMERIC_COLUMN, numeric_data,
              -1);
    }
}
/* sort function : we group odd and even */
static gint _compare_odd (GtkTreeModel *model,
              GtkTreeIter *a,
              GtkTreeIter *b,
              gpointer user_data)
{
  gint numeric_data_a, numeric_data_b;
  gtk_tree_model_get(model, a,
             NUMERIC_COLUMN, &numeric_data_a,
             -1);
  gtk_tree_model_get(model, b,
             NUMERIC_COLUMN, &numeric_data_b,
             -1);
  if( (numeric_data_a % 2) == (numeric_data_b % 2))
    { /* if both are odd or even return the differnce */
      return numeric_data_a - numeric_data_b;
    }
  else
    {
      if(numeric_data_a % 2 == 0)
      {
    return 1;
    }
      else
      {
    return -1;
    }
    }

}
/* tree model creation */
static GtkTreeModel* _create_model()
{
    GtkListStore* list_store;
    list_store = gtk_list_store_new(N_COLUMN,
                    G_TYPE_STRING,
                    G_TYPE_INT);
    _fill_model(list_store);
    gtk_tree_sortable_set_sort_func(GTK_TREE_SORTABLE(list_store),
                    NUMERIC_COLUMN, _compare_odd, NULL, NULL);
    gtk_tree_sortable_set_sort_column_id(GTK_TREE_SORTABLE(list_store),
NUMERIC_COLUMN, GTK_SORT_ASCENDING);
    return GTK_TREE_MODEL(list_store);
}
/* tree view creation */
static GtkWidget* _create_treeview()
{
  GtkWidget* tree_view;
  GtkCellRenderer* cell_renderer;
  GtkTreeModel *sorted_model = _create_model();
  tree_view = gtk_tree_view_new_with_model(sorted_model);
  /* insert columns */
  cell_renderer = gtk_cell_renderer_text_new();
  gtk_tree_view_insert_column_with_attributes(GTK_TREE_VIEW(tree_view), -1,
                          "name",
                          cell_renderer, "text", STRING_COLUMN, NULL);

  cell_renderer = gtk_cell_renderer_text_new();
  gtk_tree_view_insert_column_with_attributes(GTK_TREE_VIEW(tree_view), -1,
"ID",
                          cell_renderer, "text", NUMERIC_COLUMN, NULL);
  /* technical column */
  cell_renderer = gtk_cell_renderer_toggle_new();
  g_object_set(G_OBJECT(cell_renderer),
           "activatable", TRUE,
           "mode", GTK_CELL_RENDERER_MODE_ACTIVATABLE,
           NULL);
  g_signal_connect(G_OBJECT(cell_renderer),  "toggled",
G_CALLBACK(_toggle_odd_column), sorted_model);
  gtk_tree_view_insert_column_with_data_func(GTK_TREE_VIEW(tree_view), -1,
                         "odd", cell_renderer,
                         _is_number_odd, NULL, NULL);


  return tree_view;
}
/* init the main window */
static GtkWidget* _init_window( )
{
  GtkWidget* top_level =  gtk_window_new(GTK_WINDOW_TOPLEVEL);
  g_signal_connect(G_OBJECT(top_level),
           "delete-event", G_CALLBACK(gtk_main_quit), NULL);
  return top_level;
}

/* main */
gint main(gint argc, gchar** argv)
{
  GtkWidget* top_level;
  GtkWidget* tree_view;
  gtk_disable_setlocale();
  gtk_init(&argc,&argv);
  top_level = _init_window();
  tree_view = _create_treeview();
  gtk_container_add(GTK_CONTAINER(top_level), tree_view);
  gtk_widget_show_all(top_level);
  gtk_main();
  return 0;
}
</code>



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]