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 heap 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;
  }

Two things are worth pointing out: one is that gtk_tree_model_get sets our gchar pointer variables to a copy of the string stored, which means that we need to free it once we are done with it; the second is that 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 contain the value 0 until it is set to a new value, and strings and all kind of pointer types will be NULL until set to something else. Run the above program with an additional empty row and look at the output to see this in effect.