Search code examples
cgtk4

gtk_tree_selection_get_selected_rows method returns list with NULL paths if multiple rows selected


I'm trying to implement function which deletes selected rows in GtkTreeView widget, when button is clicked. The function looks like this:

static void delete_selected_rows(GtkButton *activated, GtkTreeView *tree_view) {
   GtkTreeSelection *tree_selection = gtk_tree_view_get_selection(tree_view);
   GtkTreeModel *model;
   GList *selected_list = gtk_tree_selection_get_selected_rows(tree_selection, &model);

   for (size_t i = 0; i < g_list_length(selected_list); i++) {
       GtkTreeIter iter;
       GtkTreePath *path = selected_list[i].data;
       gtk_tree_model_get_iter(model, &iter, path);
       gtk_list_store_remove(GTK_LIST_STORE(model), &iter);
   }
   g_list_free_full(selected_list, (GDestroyNotify) gtk_tree_path_free);
}

It works well when 1 row is selected, but when 2 or more rows selected gtk_tree_selection_get_selected_rows returns list, in which some of the pointers to GtkTreePath are NULL. It causes crash with segmentation fault.

So, I'm trying to find out whether it's me doing something wrong or is it bug in gtk4. Any help would be appreciated.


Solution

  • I figured it out. I was dumb treating GList as an array, not a linked list as it is. I corrected it, changed loop and crashes disappeared. However, deleting more than 2 selected rows did not work as expected. Several selected rows still remained after deletion. The solution was to iterate from last GList element to first, so after each deletion tree paths for lower rows won't have been changed. Here's the working solution:

    static void
    delete_selected_rows (GtkButton * activated, GtkTreeView * tree_view)
    {
      GtkTreeSelection * selection = gtk_tree_view_get_selection (tree_view);
      GtkTreeModel *model;
      GList * selected_list = gtk_tree_selection_get_selected_rows (selection, &model);
      GList * cursor = g_list_last (selected_list);
      while (cursor != NULL) {
        GtkTreeIter iter;
        GtkTreePath * path = cursor->data;
        gtk_tree_model_get_iter (model, &iter, path);
        gtk_list_store_remove (GTK_LIST_STORE (model), &iter);
        cursor = cursor->prev;
      }
      g_list_free_full (selected_list, (GDestroyNotify) gtk_tree_path_free);
    }