3.5. Retrieving Row Data

Storing data is not very useful if it cannot be retrieved again. This is done using gtk_tree_model_get, which takes similar arguments as gtk_list_store_set or gtk_tree_store_set do, only that it takes (column, pointer) arguments. The pointer must point to a variable that is of the same type as the data stored in that particular model column.

Here is the previous example extended to traverse the list store and print out the data stored. As an extra, we use gtk_tree_model_foreach to traverse the store and retrieve the row number from the GtkTreePath passed to us in the foreach callback function:


  #include <gtk/gtk.h>

  enum
  {
    COL_FIRST_NAME = 0,
    COL_LAST_NAME,
    COL_YEAR_BORN,
    NUM_COLS
  };

  gboolean
  foreach_func (GtkTreeModel *model,
                GtkTreePath  *path,
                GtkTreeIter  *iter,
                gpointer      user_data)
  {
    gchar *first_name, *last_name, *tree_path_str;
    guint  year_of_birth;

    /* Note: here we use 'iter' and not '&iter', because we did not allocate
     *  the iter on the stack and are already getting the pointer to a tree iter */

    gtk_tree_model_get (model, iter,
                        COL_FIRST_NAME, &first_name,
                        COL_LAST_NAME, &last_name,
                        COL_YEAR_BORN, &year_of_birth,
                        -1);

    tree_path_str = gtk_tree_path_to_string(path);

    g_print ("Row %s: %s %s, born %u\n", tree_path_str,
             first_name, last_name, year_of_birth);

    g_free(tree_path_str);

    g_free(first_name); /* gtk_tree_model_get made copies of       */
    g_free(last_name);  /* the strings for us when retrieving them */

    return FALSE; /* do not stop walking the store, call us with next row */
  }

  void
  create_and_fill_and_dump_store (void)
  {
    GtkListStore *liststore;
    GtkTreeIter   iter;

    liststore = gtk_list_store_new(NUM_COLS, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_UINT);

    /* Append an empty row to the list store. Iter will point to the new row */
    gtk_list_store_append(liststore, &iter);

    /* Fill fields with some data */
    gtk_list_store_set (liststore, &iter,
                        COL_FIRST_NAME, "Joe",
                        COL_LAST_NAME, "Average",
                        COL_YEAR_BORN, (guint) 1970,
                        -1);

    /* Append another row, and fill in some data */
    gtk_list_store_append(liststore, &iter);

    gtk_list_store_set (liststore, &iter,
                        COL_FIRST_NAME, "Jane",
                        COL_LAST_NAME, "Common",
                        COL_YEAR_BORN, (guint) 1967,
                        -1);

    /* Append yet another row, and fill it */
    gtk_list_store_append(liststore, &iter);

    gtk_list_store_set (liststore, &iter,
                        COL_FIRST_NAME, "Yo",
                        COL_LAST_NAME, "Da",
                        COL_YEAR_BORN, (guint) 1873,
                        -1);

    /* Now traverse the list */

    gtk_tree_model_foreach(GTK_TREE_MODEL(liststore), foreach_func, NULL);
  }

  int
  main (int argc, char **argv)
  {
    gtk_init(&argc, &argv);

    create_and_fill_and_dump_store();

    return 0;
  }

Note that when a new row is created, all fields of a row are set to a default NIL value appropriate for the data type in question. A field of type G_TYPE_INT will automatically contain the value 0 until it is set to a different value, and strings and all kind of pointer types will be NULL until set to something else. Those are valid contents for the model, and if you are not sure that row contents have been set to something, you need to be prepared to handle NULL pointers and the like in your code.

Run the above program with an additional empty row and look at the output to see this in effect.

3.5.1. Freeing Retrieved Row Data

Unless you are dealing with a model column of type G_TYPE_POINTER, gtk_tree_model_get will always make copies of the data retrieved.

In the case of strings, this means that you need to g_free the string returned when you don't need it any longer, as in the example above.

If you retrieve a GObject such as a GdkPixbuf from the store, gtk_tree_model_get will automatically add a reference to it, so you need to call g_object_unref on the retrieved object once you are done with it:


  ...

  GdkPixbuf *pixbuf;

  gtk_tree_model_get (model, &iter, 
                      COL_PICTURE, &pixbuf, 
                      NULL);

  if (pixbuf != NULL)
  {
    do_something_with_pixbuf (pixbuf);
    g_object_unref (pixbuf);
  }

  ...

Similarly, GBoxed-derived types retrieved from a model need to be freed with g_boxed_free when done with them (don't worry if you have never heard of GBoxed).

If the model column is of type G_TYPE_POINTER, gtk_tree_model_get will simply copy the pointer value, but not the data (even if if it wanted to, it couldn't copy the data, because it would not know how to copy it or what to copy exactly). If you store pointers to objects or strings in a pointer column (which you should not do unless you really know what you are doing and why you are doing it), you do not need to unref or free the returned values as described above, because gtk_tree_model_get would not know what kind of data they are and therefore won't ref or copy them on retrieval.