2

I have a simple GTK program that creates a Tree View:

static GtkTreeModel *
create_and_fill_model (void)
{
  GtkListStore  *store;
  GtkTreeIter    iter;

  store = gtk_list_store_new (NUM_COLS, G_TYPE_STRING, G_TYPE_UINT);

  /*here is some code adding rows using
    gtk_list_store_append
    gtk_list_store_set*/

  return GTK_TREE_MODEL (store);
}

static GtkWidget *
create_view_and_model (void)
{
  GtkCellRenderer     *renderer;
  GtkTreeModel        *model;
  GtkWidget           *view;

  view = gtk_tree_view_new ();

  renderer = gtk_cell_renderer_text_new ();
  gtk_tree_view_insert_column_with_attributes 
       (GTK_TREE_VIEW(view),-1,"Name",renderer,"text", COL_NAME,NULL);

  renderer = gtk_cell_renderer_text_new ();
  gtk_tree_view_insert_column_with_attributes 
       (GTK_TREE_VIEW(view),-1,"Age",renderer,"text", COL_AGE,NULL);

  model = create_and_fill_model ();

  gtk_tree_view_set_model (GTK_TREE_VIEW (view), model);

  g_object_unref (model);

  return view;
}


int
main (int argc, char **argv)
{
  //usual stuff

  view = create_view_and_model ();

  gtk_container_add (GTK_CONTAINER (window), view);

  //usual stuff
}

Can somebody tell me how do I now change the content of this treeview? Do I have to create the "view" object again? Or am I supposed to call gtk_tree_view_set_model with new model?

José Fonte
  • 4,016
  • 2
  • 16
  • 28
Cyanide
  • 85
  • 10

1 Answers1

4

To change the contents of the GtkTreeView you must use the model. In your function:

static GtkTreeModel *
create_and_fill_model (void)
{
  GtkListStore  *store;
  GtkTreeIter    iter;

  store = gtk_list_store_new (NUM_COLS, G_TYPE_STRING, G_TYPE_UINT);

  /*here is some code adding rows using
    gtk_list_store_append
    gtk_list_store_set*/

  return GTK_TREE_MODEL (store);
}

It's commented the place where you should append data, retrieve the GtkTreeIter and set data with the given iterator and function gtk_list_store_set.

You omitted the enumerator for columns but as can be seen from the model GtkListStore creation, you will have 2 columns, one containing strings and other containing unsigned integers. GtkTreeModel is an interface which the stores (tree store and list store) implement.

GtkTreeView follows the MVC (Model View Controller) pattern, so the view will reflect a view from a model and a model can have many views. Imagine the file browser where the model contains information about the files but you can have several views, icons view or list view.

Here is an example, very similar to the one you are showing:

#include <gtk/gtk.h>

enum
{
  COL_FIRST_NAME = 0,
  COL_AGE,
  NUM_COLS
} ;

static GtkTreeModel *
create_and_fill_model (void)
{
  GtkListStore  *liststore;
  GtkTreeIter   iter;

  liststore = gtk_list_store_new(NUM_COLS, G_TYPE_STRING, G_TYPE_UINT);

  gtk_list_store_append(liststore, &iter);
  gtk_list_store_set(liststore, &iter,
                     COL_FIRST_NAME, "Joe",
                     COL_AGE, 20,
                     -1);

  gtk_list_store_append(liststore, &iter);
  gtk_list_store_set(liststore, &iter,
                     COL_FIRST_NAME, "Jane",
                     COL_AGE, 24,
                     -1);

  return GTK_TREE_MODEL(liststore);
}

static GtkWidget *
create_view_and_model (void)
{
  GtkTreeViewColumn   *col;
  GtkCellRenderer     *renderer;
  GtkWidget           *view;
  GtkTreeModel        *model;

  view = gtk_tree_view_new();

  /* --- Column #1 --- */

  col = gtk_tree_view_column_new();

  gtk_tree_view_column_set_title(col, "First Name");

  /* pack tree view column into tree view */
  gtk_tree_view_append_column(GTK_TREE_VIEW(view), col);

  /* New text renderer */
  renderer = gtk_cell_renderer_text_new();

  /* pack cell renderer into tree view column */
  gtk_tree_view_column_pack_start(col, renderer, TRUE);

  /* Set view column to model column */
  gtk_tree_view_column_set_attributes(col, renderer, "text", COL_FIRST_NAME, NULL);


  /* --- Column #2 --- */

  col = gtk_tree_view_column_new();

  gtk_tree_view_column_set_title(col, "Age");

  /* pack tree view column into tree view */
  gtk_tree_view_append_column(GTK_TREE_VIEW(view), col);

  /* New text renderer */
  renderer = gtk_cell_renderer_text_new();

  /* pack cell renderer into tree view column */
  gtk_tree_view_column_pack_start(col, renderer, TRUE);

  /* Set view column to model column */
  gtk_tree_view_column_set_attributes(col, renderer, "text", COL_AGE, NULL);

  model = create_and_fill_model();

  gtk_tree_view_set_model(GTK_TREE_VIEW(view), model);

  g_object_unref(model); /* destroy model automatically with view */

  gtk_tree_selection_set_mode(gtk_tree_view_get_selection(GTK_TREE_VIEW(view)),
                              GTK_SELECTION_NONE);

  return view;
}


int
main (int argc, char **argv)
{
  GtkWidget *window;
  GtkWidget *view;

  gtk_init(&argc, &argv);

  window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
  g_signal_connect(window, "delete_event", gtk_main_quit, NULL); /* dirty */

  view = create_view_and_model();

  gtk_container_add(GTK_CONTAINER(window), view);

  gtk_widget_show_all(window);

  gtk_main();

  return 0;
}

Notice how we add data to the model (GtkListStore) in the create_and_fill_model function:

  ...
  gtk_list_store_append(liststore, &iter);
  gtk_list_store_set(liststore, &iter,
                     COL_FIRST_NAME, "Joe",
                     COL_AGE, 20,
                     -1);
  ...

Check also how we bind data from the view columns to the model columns:

gtk_tree_view_column_set_attributes(col, renderer, "text", COL_FIRST_NAME, NULL);

Where col is the first column with a CellRendererText renderer.

Compile the given example with (name the file, main.c):

gcc -o main main.c `pkg-config --cflags --libs gtk+-3.0`

And the result should be something like this:

enter image description here

José Fonte
  • 4,016
  • 2
  • 16
  • 28