Update the trip's "when" flag after deleting a dive from it

Both gtk_tree_selection_selected_foreach() and
gtk_tree_selection_get_selected_rows() are problematic.

gtk_tree_selection_get_selected_rows is not compatible with older GTK,
while gtk_tree_selection_selected_foreach() should not be used to
modify the tree. A workaround to is allocate memory and store what
is returned from the gtk_tree_selection_selected_foreach() callback
function as a GtkTreeIter array. Once done iterate trought the array
and pass the values to delete_single_dive().

A bit excesive, but it is not certain how safe is modifying the tree
while in the "_foreach" loop, even if it only shows a warning.

On the other hand the GTK source shows gtk_tree_selection_get_selected_rows()
to be a rather complicated and slow method.

Inside delete_single_dive(), once a dive is no longer part of "dive_table"
and if the dive was part of a trip, remove the dive from the tree
(gtk_tree_store_remove()) and call update_trip_timestamp().

The struct type "tree_selected_st" and tree_selected_foreach() are
reusable.

Reported-by: Dirk Hohndel <dirk@hohndel.org>
Signed-off-by: Lubomir I. Ivanov <neolit123@gmail.com>
This commit is contained in:
Lubomir I. Ivanov 2012-09-23 16:28:23 +03:00
parent 4d9abf6e8e
commit 9036f3f80e

View file

@ -1847,6 +1847,7 @@ static void delete_single_dive(GtkTreeIter *iter)
{ {
int i, idx; int i, idx;
struct dive *dive, *pdive, *ndive; struct dive *dive, *pdive, *ndive;
GtkTreeIter parent;
gtk_tree_model_get(MODEL(dive_list), iter, DIVE_INDEX, &idx, -1); gtk_tree_model_get(MODEL(dive_list), iter, DIVE_INDEX, &idx, -1);
dive = get_dive(idx); dive = get_dive(idx);
@ -1865,8 +1866,10 @@ static void delete_single_dive(GtkTreeIter *iter)
GList *trip = find_matching_trip(dive->when); GList *trip = find_matching_trip(dive->when);
delete_trip(trip); delete_trip(trip);
free(dive->divetrip); free(dive->divetrip);
dive->divetrip = NULL;
} }
} }
/* simply remove the dive and recreate the divelist /* simply remove the dive and recreate the divelist
* (we can't just manipulate the tree_view as the indices for dives change) */ * (we can't just manipulate the tree_view as the indices for dives change) */
for (i = idx; i < dive_table.nr - 1; i++) for (i = idx; i < dive_table.nr - 1; i++)
@ -1874,22 +1877,48 @@ static void delete_single_dive(GtkTreeIter *iter)
dive_table.nr--; dive_table.nr--;
if (dive->selected) if (dive->selected)
amount_selected--; amount_selected--;
/* once the dive is deleted, update the 'when' flag of the trip it was part of
* to the 'when' flag of the earliest dive left in the same trip */
if (dive->divetrip) {
gtk_tree_model_iter_parent(MODEL(dive_list), &parent, iter);
gtk_tree_store_remove(STORE(dive_list), iter);
update_trip_timestamp(&parent, dive->divetrip);
}
free(dive); free(dive);
} }
/* much simpler to use compared to gtk_tree_selection_get_selected_rows() */ /* workaround for not using gtk_tree_selection_get_selected_rows() or modifying the tree
static void delete_selected_foreach(GtkTreeModel *model, GtkTreePath *path, * directly from the gtk_tree_selection_selected_foreach() callback function */
GtkTreeIter *iter, gpointer userdata) struct tree_selected_st {
GtkTreeIter *list;
int total;
};
static void tree_selected_foreach(GtkTreeModel *model, GtkTreePath *path,
GtkTreeIter *iter, gpointer userdata)
{ {
delete_single_dive(iter); struct tree_selected_st *st = (struct tree_selected_st *)userdata;
st->total++;
st->list = (GtkTreeIter *)realloc(st->list, sizeof(GtkTreeIter) * st->total);
memcpy(&st->list[st->total - 1], iter, sizeof(GtkTreeIter));
} }
/* called when multiple dives are selected and one of these is right-clicked for delete */ /* called when multiple dives are selected and one of these is right-clicked for delete */
static void delete_selected_dives_cb(GtkWidget *menuitem, GtkTreePath *path) static void delete_selected_dives_cb(GtkWidget *menuitem, GtkTreePath *path)
{ {
int i;
GtkTreeView *tree_view = GTK_TREE_VIEW(dive_list.tree_view); GtkTreeView *tree_view = GTK_TREE_VIEW(dive_list.tree_view);
GtkTreeSelection *selection = gtk_tree_view_get_selection(tree_view); GtkTreeSelection *selection = gtk_tree_view_get_selection(tree_view);
gtk_tree_selection_selected_foreach(selection, delete_selected_foreach, NULL); struct tree_selected_st st = {NULL, 0};
gtk_tree_selection_selected_foreach(selection, tree_selected_foreach, &st);
for (i = 0; i < st.total; i++)
delete_single_dive(&st.list[i]);
free(st.list);
dive_list_update_dives(); dive_list_update_dives();
mark_divelist_changed(TRUE); mark_divelist_changed(TRUE);