Cell Renderer Combo in a Treeview



The attached and inline program below illustrates the problem I'm having
with rendering a combo box in a treeview.  The two big things are 1) I
can't get the combo to default to a value without setting it globally,
and 2) the values don't get displayed when set and it seems to be
setting the value in the combo list not the tree.

Does any one see the error?

Thanks in advance,
--dhk


/* Compile Command:
 * gcc -Wall -g3 `pkg-config --cflags --libs gtk+-2.0` -o comboTst
comboTst.c
 */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include <gtk/gtk.h>
#include <gdk/gdkkeysyms.h>

enum {COL_DESC, COL_TYPE, COL_DISABLE, COL_NUM};

void treeStore0(GtkWidget *tv);
void treeView0(GtkWidget *tv);
void itemToggled(GtkCellRendererToggle *cell, gchar *path, gpointer
data);
void destroyCb(GtkWidget *widget, gpointer data);
void itemTypeComboEditedCb(GtkCellRendererText *cell, const gchar *path,
const gchar *value, GtkListStore *list);

int main(int argc, char **argv) {
#define TST 0
  GtkWidget *window=NULL;
  GtkWidget *scrolledwindow=NULL;
#if TST
  GtkWidget *tv=NULL;
#else
  GtkWidget *tv[3]={NULL, NULL, NULL};
#endif
  GtkTreeModel *tm=NULL;
  GtkTreeIter iter;

  gtk_init (&argc, &argv);

  window=gtk_window_new(GTK_WINDOW_TOPLEVEL);
  gtk_window_set_title(GTK_WINDOW(window), "Tree View Test");
  gtk_window_set_default_size(GTK_WINDOW(window), 300, 165);
  g_signal_connect(G_OBJECT(window), "delete_event",
G_CALLBACK(destroyCb), NULL);

  scrolledwindow=gtk_scrolled_window_new(NULL, NULL);
  gtk_widget_show(scrolledwindow);
  gtk_container_add(GTK_CONTAINER(window), scrolledwindow);
  gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolledwindow),
GTK_POLICY_NEVER, GTK_POLICY_ALWAYS);

gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(scrolledwindow),
GTK_SHADOW_IN);
  gtk_widget_show(window);

#if TST
  tv=gtk_tree_view_new();
  gtk_widget_show(tv);
  gtk_container_add(GTK_CONTAINER(scrolledwindow), tv);

  treeStore0(tv); /* Make the tree store */
  treeView0(tv); /* Make the tree view */

  tm=gtk_tree_view_get_model(GTK_TREE_VIEW(tv));
#else
  tv[0]=gtk_tree_view_new();
  tv[1]=gtk_tree_view_new();
  tv[2]=gtk_tree_view_new();
  gtk_widget_show(tv[0]);
  gtk_container_add(GTK_CONTAINER(scrolledwindow), tv[0]);

  treeStore0(tv[0]); /* Make the tree store */
  treeView0(tv[0]); /* Make the tree view */

  tm=gtk_tree_view_get_model(GTK_TREE_VIEW(tv[0]));
#endif
#undef TST

  gtk_tree_store_append(GTK_TREE_STORE(tm), &iter, NULL);
  gtk_tree_store_set(GTK_TREE_STORE(tm), &iter, COL_DESC, "Click the
Type for the combo box", -1);
  gtk_tree_store_set(GTK_TREE_STORE(tm), &iter, COL_DISABLE, TRUE, -1);
  gtk_tree_store_append(GTK_TREE_STORE(tm), &iter, NULL);
  gtk_tree_store_set(GTK_TREE_STORE(tm), &iter, COL_DESC, "First I'd
like it to default to one of the values.", -1);
  gtk_tree_store_append(GTK_TREE_STORE(tm), &iter, NULL);
  gtk_tree_store_set(GTK_TREE_STORE(tm), &iter, COL_DESC, "Then I'd like
the box to behave like a combo box should.", -1);
  gtk_tree_store_append(GTK_TREE_STORE(tm), &iter, NULL);
  gtk_tree_store_set(GTK_TREE_STORE(tm), &iter, COL_DESC, "The values
selected don't get displayed.", -1);
  gtk_tree_store_append(GTK_TREE_STORE(tm), &iter, NULL);
  gtk_tree_store_set(GTK_TREE_STORE(tm), &iter, COL_DESC, ". . . and the
list inside changes acorrding to the selection.", -1);

  gtk_main();

  return 0;
}
void treeStore0(GtkWidget *tv) {
  GtkTreeStore *ts=NULL;

  ts=gtk_tree_store_new(COL_NUM,     /* Total number of columns */
    G_TYPE_STRING,      /* <Description>            */
    G_TYPE_STRING,      /* <Type>                   */
    G_TYPE_BOOLEAN      /* Check Box - Disable item */
  );

  gtk_tree_view_set_model(GTK_TREE_VIEW(tv), GTK_TREE_MODEL(ts));
}


void treeView0(GtkWidget *tv) {
  gint ii;
  GtkCellRenderer *renderer=NULL;
  GtkTreeViewColumn *column=NULL;
  gint col_num=0;

   /* Variable for the Combo Box */
  GtkListStore *ls_combo=NULL;
  GtkTreeIter iter;
  gchar *type[5]={"Thoroughbred", "Standardbred", "Shortbread", "Stock",
"Nag"};
  /* --- Description --- */
  renderer = gtk_cell_renderer_text_new();
  g_object_set(renderer, "editable", TRUE, NULL);
  g_object_set(G_OBJECT(renderer), "width-chars", 100, NULL);

  /* Create a Column */
  column=gtk_tree_view_column_new();
  gtk_tree_view_column_set_title(column, "Description");
  gtk_tree_view_column_pack_start(column, renderer, FALSE);
  gtk_tree_view_column_set_attributes(column, renderer, "text",
COL_DESC, NULL);
  col_num=gtk_tree_view_insert_column(GTK_TREE_VIEW(tv), column, -1);

  /* FIELD is the column number not the index:  always one more than
index. */
  g_object_set_data(G_OBJECT(renderer), "FIELD",
GUINT_TO_POINTER(col_num));

  /* PROBLEM v v v v v v PROBLEM */
  /* --- Type --- */
  renderer = gtk_cell_renderer_combo_new();
  /* Create the combo box */
  ls_combo=gtk_list_store_new(1, G_TYPE_STRING);
  for(ii=0; ii<5; ii++) {
    gtk_list_store_append (ls_combo, &iter);
    gtk_list_store_set (ls_combo, &iter, 0, type[ii], -1);
  }

  g_object_set(G_OBJECT(renderer), "model", ls_combo,
                                   "text-column", 0,
                                   //"text", "Stock",
                                   "has-entry", FALSE,
                                   "editable", TRUE,
                                   NULL);

  g_signal_connect(renderer, "edited",
G_CALLBACK(itemTypeComboEditedCb), ls_combo);

  /* Create a Column */
  column=gtk_tree_view_column_new();
  gtk_tree_view_column_set_title(column, "Type");
  gtk_tree_view_column_pack_start(column, renderer, FALSE);
  gtk_tree_view_column_set_attributes(column, renderer, "text",
COL_TYPE, NULL);
  col_num=gtk_tree_view_insert_column(GTK_TREE_VIEW(tv), column, -1);
  //gtk_list_store_set(ls_combo, &iter, 0, "Stock", -1);

  g_object_unref(ls_combo);

  /* FIELD is the column number not the index:  always one more than
index. */
  g_object_set_data(G_OBJECT(renderer), "FIELD",
GUINT_TO_POINTER(col_num));
  /* PROBLEM ^ ^ ^ ^ ^ ^ PROBLEM */
  /* -------------- */

  /* --- Disable Check Box --- */
  renderer=gtk_cell_renderer_toggle_new();

  g_signal_connect(renderer, "toggled", G_CALLBACK(itemToggled), tv);

  /* Create a Column */
  column=gtk_tree_view_column_new();
  gtk_tree_view_column_set_title(column, "Disable");
  gtk_tree_view_column_pack_start(column, renderer, FALSE);
  // Why does setting attributes cause errors and seems unnecessary
anyway?
  //gtk_tree_view_column_set_attributes(column, renderer, "activatable",
TRUE, "active", FALSE, NULL);
  gtk_tree_view_column_set_attributes(column, renderer, "active",
COL_DISABLE, NULL);
  col_num=gtk_tree_view_insert_column(GTK_TREE_VIEW(tv), column, -1);


col_num=gtk_tree_model_get_n_columns(gtk_tree_view_get_model(GTK_TREE_VIEW(tv)));
  /* FIELD is the column number not the index:  always one more than
index. */
  g_object_set_data(G_OBJECT(renderer), "FIELD",
GUINT_TO_POINTER(col_num));
}


/* itemToggled() is basically from the gtk-demo application.  The major
 * difference is the call to gtk_cell_renderer_toggle_set_active()
 * which I don't understand why gtk-demo doesn't do it.*/
void itemToggled(GtkCellRendererToggle *cell, gchar *path, gpointer
data) {
  GtkTreeModel *tm=NULL;
  GtkTreePath *tp=gtk_tree_path_new_from_string(path);
  GtkTreeIter iter;
  gboolean toggle_item=FALSE;
  gint col_num=0;

  tm=gtk_tree_view_get_model(GTK_TREE_VIEW(data));
  if(tm==NULL) {
    g_error("%s:%d Tree Model is NULL", __FILE__, __LINE__);
  }

  col_num=GPOINTER_TO_INT(g_object_get_data(G_OBJECT(cell), "FIELD"));
  col_num--; /* FIELD is set to the column number not the index:
decrement. */

  /* get toggled iter */
  gtk_tree_model_get_iter(tm, &iter, tp);

  /* get the toggle value */
  gtk_tree_model_get(tm, &iter, col_num, &toggle_item, -1);

  toggle_item^=1; /* flip the value */
  /* set the new toggle value */
  gtk_tree_store_set(GTK_TREE_STORE(tm), &iter, col_num, toggle_item,
-1);
  g_print("TOGGLE set to {%s}\n", (toggle_item)?"TRUE":"FALSE");

  /* clean up */
  gtk_tree_path_free(tp);
}

void destroyCb(GtkWidget *widget, gpointer data) {
  gtk_main_quit();
  return;
}

void itemTypeComboEditedCb(GtkCellRendererText *cell, const gchar *path,
const gchar *value, GtkListStore *list) {
  gboolean rc=FALSE;
  GtkTreeIter iter;
  GtkTreePath *tp=NULL;
  //GtkTreeModel *tm=NULL; /* a tree model */
  gint col_num=0;

  tp=gtk_tree_path_new_from_string(path);
  col_num=GPOINTER_TO_INT(g_object_get_data(G_OBJECT (cell), "FIELD"));
  //col_num--;

  //gtk_tree_model_get_iter(GTK_TREE_MODEL(list), &iter, tp);
  rc=gtk_tree_model_get_iter_from_string(GTK_TREE_MODEL(list), &iter,
path);
  if(rc==FALSE) {
    g_error("%s:%d itemTypeComboEditedCb() can not get iter.\n",
__FILE__, __LINE__);
  }

  g_print("path={%s} value={%s}\n", path, value);
  //g_object_set(G_OBJECT(cell), "text", value, NULL);

  gtk_list_store_set(list, &iter, 0, value, -1);

  //tp=gtk_tree_path_new_from_string(path);
  //rc=gtk_tree_model_get_iter(tm, &iter, tp);

  //g_object_set(cell, "text", value, NULL);
  //g_object_set((GtkObject *)cell, "text", value, NULL);
  //gtk_tree_store_set(GTK_TREE_STORE(tm), &iter, ips, xval, -1);
  //gtk_tree_path_free(tp);
}



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