3.6. Removing Rows

Rows can easily be removed with gtk_list_store_remove and gtk_tree_store_remove. The removed row will automatically be removed from the tree view as well, and all data stored will automatically be freed, with the exception of G_TYPE_POINTER columns (see above).

Removing a single row is fairly straight forward: you need to get the iter that identifies the row you want to remove, and then use one of the above functions. Here is a simple example that removes a row when you double-click on it (bad from a user interface point of view, but then it is just an example):


  static void
  onRowActivated (GtkTreeView        *view,
                  GtkTreePath        *path,
                  GtkTreeViewColumn  *col,
                  gpointer            user_data)
  {
    GtkTreeModel *model;
    GtkTreeIter   iter;

    g_print ("Row has been double-clicked. Removing row.\n");

    model = gtk_tree_view_get_model(view);

    if (!gtk_tree_model_get_iter(model, &iter, path))
      return; /* path describes a non-existing row - should not happen */

    gtk_list_store_remove(GTK_LIST_STORE(model), &iter);
  }


  void
  create_treeview (void)
  {
    ...
    g_signal_connect(treeview, "row-activated", G_CALLBACK(onRowActivated), NULL);
    ...
  }

Note: gtk_list_store_remove and gtk_tree_store_remove both have slightly different semantics in Gtk+-2.0 and Gtk+-2.2 and later. In Gtk+-2.0, both functions do not return a value, while in later Gtk+ versions those functions return either TRUE or FALSE to indicate whether the iter given has been set to the next valid row (or invalidated if there is no next row). This is important to keep in mind when writing code that is supposed to work with all Gtk+-2.x versions. In that case you should just ignore the value returned (as in the call above) and check the iter with gtk_list_store_iter_is_valid if you need it.

If you want to remove the n-th row from a list (or the n-th child of a tree node), you have two approaches: either you first create a GtkTreePath that describes that row and then turn it into an iter and remove it; or you take the iter of the parent node and use gtk_tree_model_iter_nth_child (which will also work for list stores if you use NULL as the parent iter. Of course you could also start with the iter of the first top-level row, and then step-by-step move it to the row you want, although that seems a rather awkward way of doing it.

The following code snippet will remove the n-th row of a list if it exists:


   /******************************************************************
    *
    *  list_store_remove_nth_row
    *
    *  Removes the nth row of a list store if it exists.
    *
    *  Returns TRUE on success or FALSE if the row does not exist.
    *
    ******************************************************************/

   gboolean
   list_store_remove_nth_row (GtkListStore *store, gint n)
   {
     GtkTreeIter  iter;

     g_return_val_if_fail (GTK_IS_LIST_STORE(store), FALSE);

     /* NULL means the parent is the virtual root node, so the
      *  n-th top-level element is returned in iter, which is
      *  the n-th row in a list store (as a list store only has
      *  top-level elements, and no children) */
     if (gtk_tree_model_iter_nth_child(GTK_TREE_MODEL(store), &iter, NULL, n))
     {
       gtk_list_store_remove(store, &iter);
       return TRUE;
     }

     return FALSE;
   }