};
static struct DiveList dive_list;
+GList *dive_trip_list;
+gboolean autogroup = FALSE;
+
+const char *tripflag_names[NUM_TRIPFLAGS] = { "TF_NONE", "NOTRIP", "INTRIP" };
/*
* The dive list has the dive data in both string format (for showing)
DIVELIST_COLUMNS
};
-/* magic numbers that indicate (as negative values) model entries that
- * are summary entries for a divetrip */
-#define NEW_TRIP 1
-
#ifdef DEBUG_MODEL
static gboolean dump_model_entry(GtkTreeModel *model, GtkTreePath *path,
GtkTreeIter *iter, gpointer data)
{
char *location;
- int idx, nr, rating, depth;
+ int idx, nr, duration;
+ struct dive *dive;
+
+ gtk_tree_model_get(model, iter, DIVE_INDEX, &idx, DIVE_NR, &nr, DIVE_DURATION, &duration, DIVE_LOCATION, &location, -1);
+ printf("entry #%d : nr %d duration %d location %s ", idx, nr, duration, location);
+ dive = get_dive(idx);
+ if (dive)
+ printf("tripflag %d\n", dive->tripflag);
+ else
+ printf("without matching dive\n");
- gtk_tree_model_get(model, iter, DIVE_INDEX, &idx, DIVE_NR, &nr, DIVE_RATING, &rating, DIVE_DEPTH, &depth, DIVE_LOCATION, &location, -1);
- printf("entry #%d : nr %d rating %d depth %d location %s \n", idx, nr, rating, depth, location);
free(location);
return FALSE;
}
#endif
-static GList *selected_dives;
-static int *selectiontracker;
+#if DEBUG_SELECTION_TRACKING
+void dump_selection(void)
+{
+ int i;
+ struct dive *dive;
+
+ printf("currently selected are %d dives:", amount_selected);
+ for_each_dive(i, dive) {
+ if (dive->selected)
+ printf(" %d", i);
+ }
+ printf("\n");
+}
+#endif
/* when subsurface starts we want to have the last dive selected. So we simply
walk to the first leaf (and skip the summary entries - which have negative
}
}
-/* if we click on a summary dive, we actually want to select / unselect
- all the dives "below" it */
-static void select_children(GtkTreeModel *model, GtkTreeSelection * selection,
- GtkTreeIter *iter, gboolean was_selected)
+/* make sure that if we expand a summary row that is selected, the children show
+ up as selected, too */
+void row_expanded_cb(GtkTreeView *tree_view, GtkTreeIter *iter, GtkTreePath *path, gpointer data)
{
- int i, nr_children;
- GtkTreeIter parent;
- GtkTreePath *tpath;
+ GtkTreeIter child;
+ GtkTreeModel *model = GTK_TREE_MODEL(dive_list.model);
+ GtkTreeSelection *selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(dive_list.tree_view));
- memcpy(&parent, iter, sizeof(parent));
+ if (!gtk_tree_model_iter_children(model, &child, iter))
+ return;
+
+ do {
+ int idx;
+ struct dive *dive;
- tpath = gtk_tree_model_get_path(model, &parent);
- if(!gtk_tree_view_row_expanded(GTK_TREE_VIEW(dive_list.tree_view), tpath))
- gtk_tree_view_expand_row(GTK_TREE_VIEW(dive_list.tree_view), tpath, FALSE);
+ gtk_tree_model_get(model, &child, DIVE_INDEX, &idx, -1);
+ dive = get_dive(idx);
- nr_children = gtk_tree_model_iter_n_children(model, &parent);
- for (i = 0; i < nr_children; i++) {
- gtk_tree_model_iter_nth_child(model, iter, &parent, i);
- if (was_selected)
- gtk_tree_selection_unselect_iter(selection, iter);
+ if (dive->selected)
+ gtk_tree_selection_select_iter(selection, &child);
else
- gtk_tree_selection_select_iter(selection, iter);
- }
+ gtk_tree_selection_unselect_iter(selection, &child);
+ } while (gtk_tree_model_iter_next(model, &child));
+}
+
+static int selected_children(GtkTreeModel *model, GtkTreeIter *iter)
+{
+ GtkTreeIter child;
+
+ if (!gtk_tree_model_iter_children(model, &child, iter))
+ return FALSE;
+
+ do {
+ int idx;
+ struct dive *dive;
+
+ gtk_tree_model_get(model, &child, DIVE_INDEX, &idx, -1);
+ dive = get_dive(idx);
+
+ if (dive->selected)
+ return TRUE;
+ } while (gtk_tree_model_iter_next(model, &child));
+ return FALSE;
+}
+
+/* Make sure that if we collapse a summary row with any selected children, the row
+ shows up as selected too */
+void row_collapsed_cb(GtkTreeView *tree_view, GtkTreeIter *iter, GtkTreePath *path, gpointer data)
+{
+ GtkTreeModel *model = GTK_TREE_MODEL(dive_list.model);
+ GtkTreeSelection *selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(dive_list.tree_view));
+
+ if (selected_children(model, iter))
+ gtk_tree_selection_select_iter(selection, iter);
}
-/* this is called _before_ the selection is changed, for every single entry;
- * we simply have it call down the tree to make sure that summary items toggle
- * their children */
+static GList *selection_changed = NULL;
+
+/*
+ * This is called _before_ the selection is changed, for every single entry;
+ *
+ * We simply create a list of all changed entries, and make sure that the
+ * group entries go at the end of the list.
+ */
gboolean modify_selection_cb(GtkTreeSelection *selection, GtkTreeModel *model,
GtkTreePath *path, gboolean was_selected, gpointer userdata)
{
- GtkTreeIter iter;
- int dive_idx;
+ GtkTreeIter iter, *p;
- if (gtk_tree_model_get_iter(model, &iter, path)) {
- gtk_tree_model_get(model, &iter, DIVE_INDEX, &dive_idx, -1);
- if (dive_idx < 0) {
- select_children(model, selection, &iter, was_selected);
- }
- }
- /* allow this selection to proceed */
+ if (!gtk_tree_model_get_iter(model, &iter, path))
+ return TRUE;
+
+ /* Add the group entries to the end */
+ p = gtk_tree_iter_copy(&iter);
+ if (gtk_tree_model_iter_has_child(model, p))
+ selection_changed = g_list_append(selection_changed, p);
+ else
+ selection_changed = g_list_prepend(selection_changed, p);
return TRUE;
}
-/* this is called when gtk thinks that the selection has changed */
-static void selection_cb(GtkTreeSelection *selection, gpointer userdata)
+static void select_dive(struct dive *dive, int selected)
{
- GtkTreeIter iter;
- GtkTreePath *path;
-
- int nr_selected = gtk_tree_selection_count_selected_rows(selection);
-
- if (selected_dives) {
- g_list_foreach (selected_dives, (GFunc) gtk_tree_path_free, NULL);
- g_list_free (selected_dives);
+ if (dive->selected != selected) {
+ amount_selected += selected ? 1 : -1;
+ dive->selected = selected;
}
- selected_dives = gtk_tree_selection_get_selected_rows(selection, NULL);
- selectiontracker = realloc(selectiontracker, nr_selected * sizeof(int));
+}
- switch (nr_selected) {
- case 0: /* there is no clear way to figure out which dive to show */
- amount_selected = 0;
- selected_dive = -1;
- return;
- case 1:
- /* just pick that dive as selected */
- amount_selected = 1;
- path = g_list_nth_data(selected_dives, 0);
- if (gtk_tree_model_get_iter(GTK_TREE_MODEL(dive_list.model), &iter, path)) {
- gtk_tree_model_get(GTK_TREE_MODEL(dive_list.model), &iter, DIVE_INDEX, &selected_dive, -1);
- /* due to the way this callback gets invoked it is possible that
- in the process of unselecting a summary dive we get here with
- just one summary dive selected - ignore that case */
- if (selected_dive < 0) {
- amount_selected = 0;
- return;
- }
- selectiontracker[0] = selected_dive;
- repaint_dive();
- }
+/*
+ * This gets called when a dive group has changed selection.
+ */
+static void select_dive_group(GtkTreeModel *model, GtkTreeSelection *selection, GtkTreeIter *iter, int selected)
+{
+ int first = 1;
+ GtkTreeIter child;
+
+ if (selected == selected_children(model, iter))
return;
- default: /* multiple selections - what now?
- * We don't change the selected dive unless there is exactly one dive selected; not sure this
- * is the most intuitive solution.
- * The dives that have been selected are processed */
- amount_selected = g_list_length(selected_dives);
- process_selected_dives(selected_dives, selectiontracker, GTK_TREE_MODEL(dive_list.model));
- repaint_dive();
+
+ if (!gtk_tree_model_iter_children(model, &child, iter))
return;
+
+ do {
+ int idx;
+ struct dive *dive;
+
+ gtk_tree_model_get(model, &child, DIVE_INDEX, &idx, -1);
+ if (first && selected)
+ selected_dive = idx;
+ first = 0;
+ dive = get_dive(idx);
+ if (dive->selected == selected)
+ continue;
+
+ select_dive(dive, selected);
+ if (selected)
+ gtk_tree_selection_select_iter(selection, &child);
+ else
+ gtk_tree_selection_unselect_iter(selection, &child);
+ } while (gtk_tree_model_iter_next(model, &child));
+}
+
+/*
+ * This gets called _after_ the selections have changed, for each entry that
+ * may have changed. Check if the gtk selection state matches our internal
+ * selection state to verify.
+ *
+ * The group entries are at the end, this guarantees that we have handled
+ * all the dives before we handle groups.
+ */
+static void check_selection_cb(GtkTreeIter *iter, GtkTreeSelection *selection)
+{
+ GtkTreeModel *model = GTK_TREE_MODEL(dive_list.model);
+ struct dive *dive;
+ int idx, gtk_selected;
+
+ gtk_tree_model_get(model, iter,
+ DIVE_INDEX, &idx,
+ -1);
+ dive = get_dive(idx);
+ gtk_selected = gtk_tree_selection_iter_is_selected(selection, iter);
+ if (idx < 0)
+ select_dive_group(model, selection, iter, gtk_selected);
+ else {
+ select_dive(dive, gtk_selected);
+ if (gtk_selected)
+ selected_dive = idx;
}
+ gtk_tree_iter_free(iter);
+}
+
+/* this is called when gtk thinks that the selection has changed */
+static void selection_cb(GtkTreeSelection *selection, GtkTreeModel *model)
+{
+ GList *changed = selection_changed;
+
+ selection_changed = NULL;
+ g_list_foreach(changed, (GFunc) check_selection_cb, selection);
+ g_list_free(changed);
+#if DEBUG_SELECTION_TRACKING
+ dump_selection();
+#endif
+
+ process_selected_dives();
+ repaint_dive();
}
const char *star_strings[] = {
GtkTreeIter *iter,
gpointer data)
{
- int val, idx;
+ int val, idx, nr;
struct tm *tm;
time_t when;
char buffer[40];
- gtk_tree_model_get(model, iter, DIVE_INDEX, &idx, DIVE_DATE, &val, -1);
+ gtk_tree_model_get(model, iter, DIVE_INDEX, &idx, DIVE_DATE, &val, DIVE_NR, &nr, -1);
/* 2038 problem */
when = val;
tm = gmtime(&when);
- switch(idx) {
- case -NEW_TRIP:
+ if (idx < 0) {
snprintf(buffer, sizeof(buffer),
- "Trip %s, %s %d, %d",
+ "Trip %s, %s %d, %d (%d dive%s)",
weekday(tm->tm_wday),
monthname(tm->tm_mon),
- tm->tm_mday, tm->tm_year + 1900);
- break;
- default:
+ tm->tm_mday, tm->tm_year + 1900,
+ nr, nr > 1 ? "s" : "");
+ } else {
snprintf(buffer, sizeof(buffer),
"%s, %s %d, %d %02d:%02d",
weekday(tm->tm_wday),
return;
}
-/* random heuristic - not diving in three days implies new dive trip */
-#define TRIP_THRESHOLD 3600*24*3
-static int new_group(struct dive *dive, struct dive **last_dive, time_t *tm_date)
-{
- if (!last_dive)
- return TRUE;
- if (*last_dive) {
- struct dive *ldive = *last_dive;
- if (abs(dive->when - ldive->when) < TRIP_THRESHOLD) {
- *last_dive = dive;
- return FALSE;
- }
- }
- *last_dive = dive;
- if (tm_date) {
- struct tm *tm1 = gmtime(&dive->when);
- tm1->tm_sec = 0;
- tm1->tm_min = 0;
- tm1->tm_hour = 0;
- *tm_date = mktime(tm1);
- }
- return TRUE;
-}
-
static void fill_dive_list(void)
{
int i;
- GtkTreeIter iter, parent_iter;
+ GtkTreeIter iter, parent_iter, *parent_ptr = NULL;
GtkTreeStore *liststore, *treestore;
- struct dive *last_dive = NULL;
- struct dive *first_trip_dive = NULL;
- struct dive *last_trip_dive = NULL;
- time_t dive_date;
+ struct dive *last_trip = NULL;
+ GList *trip;
+ struct dive *dive_trip = NULL;
+
+ /* if we have pre-existing trips, start on the last one */
+ trip = g_list_last(dive_trip_list);
treestore = GTK_TREE_STORE(dive_list.treemodel);
liststore = GTK_TREE_STORE(dive_list.listmodel);
i = dive_table.nr;
while (--i >= 0) {
- struct dive *dive = dive_table.dives[i];
-
- if (new_group(dive, &last_dive, &dive_date))
- {
- /* make sure we display the first date of the trip in previous summary */
- if (first_trip_dive && last_trip_dive && last_trip_dive->when < first_trip_dive->when)
- gtk_tree_store_set(treestore, &parent_iter,
- DIVE_DATE, last_trip_dive->when,
- DIVE_LOCATION, last_trip_dive->location,
- -1);
- first_trip_dive = dive;
-
- gtk_tree_store_append(treestore, &parent_iter, NULL);
- gtk_tree_store_set(treestore, &parent_iter,
- DIVE_INDEX, -NEW_TRIP,
- DIVE_NR, -NEW_TRIP,
- DIVE_DATE, dive_date,
- DIVE_LOCATION, dive->location,
- DIVE_TEMPERATURE, 0,
- DIVE_SAC, 0,
+ struct dive *dive = get_dive(i);
+
+ /* make sure we display the first date of the trip in previous summary */
+ if (dive_trip && parent_ptr) {
+ gtk_tree_store_set(treestore, parent_ptr,
+ DIVE_NR, dive_trip->number,
+ DIVE_DATE, dive_trip->when,
+ DIVE_LOCATION, dive_trip->location,
-1);
}
- last_trip_dive = dive;
+ /* the dive_trip info might have been killed by a previous UNGROUPED dive */
+ if (trip)
+ dive_trip = DIVE_TRIP(trip);
+ /* tripflag defines how dives are handled;
+ * TF_NONE "not handled yet" - create time based group if autogroup == TRUE
+ * NO_TRIP "set as no group" - simply leave at top level
+ * IN_TRIP "use the trip with the largest trip time (when) that is <= this dive"
+ */
+ if (UNGROUPED_DIVE(dive)) {
+ /* first dives that go to the top level */
+ parent_ptr = NULL;
+ dive_trip = NULL;
+ } else if (autogroup && !DIVE_IN_TRIP(dive)) {
+ if ( ! dive_trip || ! DIVE_FITS_TRIP(dive, dive_trip)) {
+ /* allocate new trip - all fields default to 0
+ and get filled in further down */
+ dive_trip = alloc_dive();
+ dive_trip_list = insert_trip(dive_trip, dive_trip_list);
+ trip = FIND_TRIP(dive_trip, dive_trip_list);
+ }
+ } else { /* either the dive has a trip or we aren't creating trips */
+ if (! (trip && DIVE_FITS_TRIP(dive, DIVE_TRIP(trip)))) {
+ GList *last_trip = trip;
+ trip = PREV_TRIP(trip, dive_trip_list);
+ if (! (trip && DIVE_FITS_TRIP(dive, DIVE_TRIP(trip)))) {
+ /* we could get here if there are no trips in the XML file
+ * and we aren't creating trips, either.
+ * Otherwise we need to create a new trip */
+ if (autogroup) {
+ dive_trip = alloc_dive();
+ dive_trip_list = insert_trip(dive_trip, dive_trip_list);
+ trip = FIND_TRIP(dive_trip, dive_trip_list);
+ } else {
+ /* let's go back to the last valid trip */
+ trip = last_trip;
+ }
+ } else {
+ dive_trip = trip->data;
+ dive_trip->number = 0;
+ }
+ }
+ }
+ /* update dive_trip to include this dive, increase number of dives in
+ the trip and update location if necessary */
+ if (dive_trip) {
+ dive->tripflag = IN_TRIP;
+ dive_trip->number++;
+ dive_trip->when = dive->when;
+ if (!dive_trip->location && dive->location)
+ dive_trip->location = dive->location;
+ if (dive_trip != last_trip) {
+ last_trip = dive_trip;
+ /* create trip entry */
+ gtk_tree_store_append(treestore, &parent_iter, NULL);
+ parent_ptr = &parent_iter;
+ /* a duration of 0 (and negative index) identifies a group */
+ gtk_tree_store_set(treestore, parent_ptr,
+ DIVE_INDEX, -1,
+ DIVE_NR, dive_trip->number,
+ DIVE_DATE, dive_trip->when,
+ DIVE_LOCATION, dive_trip->location,
+ DIVE_DURATION, 0,
+ -1);
+ }
+ }
+
+ /* store dive */
update_cylinder_related_info(dive);
- gtk_tree_store_append(treestore, &iter, &parent_iter);
+ gtk_tree_store_append(treestore, &iter, parent_ptr);
gtk_tree_store_set(treestore, &iter,
DIVE_INDEX, i,
DIVE_NR, dive->number,
-1);
}
+ /* make sure we display the first date of the trip in previous summary */
+ if (parent_ptr && dive_trip)
+ gtk_tree_store_set(treestore, parent_ptr,
+ DIVE_NR, dive_trip->number,
+ DIVE_DATE, dive_trip->when,
+ DIVE_LOCATION, dive_trip->location,
+ -1);
update_dive_list_units();
if (gtk_tree_model_get_iter_first(GTK_TREE_MODEL(dive_list.model), &iter)) {
GtkTreeSelection *selection;
first_leaf(GTK_TREE_MODEL(dive_list.model), &iter, &selected_dive);
selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(dive_list.tree_view));
gtk_tree_selection_select_iter(selection, &iter);
- selectiontracker = realloc(selectiontracker, sizeof(int));
- *selectiontracker = selected_dive;
}
}
gtk_widget_grab_focus(tree_view);
}
+/*
+ * Double-clicking on a group entry will expand a collapsed group
+ * and vice versa.
+ */
+static void collapse_expand(GtkTreeView *tree_view, GtkTreePath *path)
+{
+ if (!gtk_tree_view_row_expanded(tree_view, path))
+ gtk_tree_view_expand_row(tree_view, path, FALSE);
+ else
+ gtk_tree_view_collapse_row(tree_view, path);
+
+}
+
+/* Double-click on a dive list */
static void row_activated_cb(GtkTreeView *tree_view,
GtkTreePath *path,
GtkTreeViewColumn *column,
if (!gtk_tree_model_get_iter(GTK_TREE_MODEL(dive_list.model), &iter, path))
return;
+
gtk_tree_model_get(GTK_TREE_MODEL(dive_list.model), &iter, DIVE_INDEX, &index, -1);
/* a negative index is special for the "group by date" entries */
- if (index >= 0)
- edit_dive_info(get_dive(index));
+ if (index < 0) {
+ collapse_expand(tree_view, path);
+ return;
+ }
+ edit_dive_info(get_dive(index));
}
void add_dive_cb(GtkWidget *menuitem, gpointer data)
void edit_dive_cb(GtkWidget *menuitem, gpointer data)
{
- edit_multi_dive_info(amount_selected, selectiontracker);
+ edit_multi_dive_info(NULL);
+}
+
+static void expand_all_cb(GtkWidget *menuitem, GtkTreeView *tree_view)
+{
+ gtk_tree_view_expand_all(tree_view);
+}
+
+static void collapse_all_cb(GtkWidget *menuitem, GtkTreeView *tree_view)
+{
+ gtk_tree_view_collapse_all(tree_view);
}
static void popup_divelist_menu(GtkTreeView *tree_view, GtkTreeModel *model, int button)
{
- GtkWidget *menu, *menuitem;
+ GtkWidget *menu, *menuitem, *image;
char editlabel[] = "Edit dives";
menu = gtk_menu_new();
- menuitem = gtk_menu_item_new_with_label("Add dive");
+ menuitem = gtk_image_menu_item_new_with_label("Add dive");
+ image = gtk_image_new_from_stock(GTK_STOCK_ADD, GTK_ICON_SIZE_MENU);
+ gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(menuitem), image);
g_signal_connect(menuitem, "activate", G_CALLBACK(add_dive_cb), NULL);
gtk_menu_shell_append(GTK_MENU_SHELL(menu), menuitem);
if (amount_selected) {
g_signal_connect(menuitem, "activate", G_CALLBACK(edit_dive_cb), model);
gtk_menu_shell_append(GTK_MENU_SHELL(menu), menuitem);
}
+ menuitem = gtk_menu_item_new_with_label("Expand all");
+ g_signal_connect(menuitem, "activate", G_CALLBACK(expand_all_cb), tree_view);
+ gtk_menu_shell_append(GTK_MENU_SHELL(menu), menuitem);
+ menuitem = gtk_menu_item_new_with_label("Collapse all");
+ g_signal_connect(menuitem, "activate", G_CALLBACK(collapse_all_cb), tree_view);
+ gtk_menu_shell_append(GTK_MENU_SHELL(menu), menuitem);
gtk_widget_show_all(menu);
gtk_menu_popup(GTK_MENU(menu), NULL, NULL, NULL, NULL,
when gtk_tree_selection_select_path is called. We also need to
keep copies of the sort order so we can restore that as well after
switching models. */
-static int *oldselection;
-static int old_nr_selected;
static gboolean second_call = FALSE;
static GtkSortType sortorder[] = { [0 ... DIVELIST_COLUMNS - 1] = GTK_SORT_DESCENDING, };
static int lastcol = DIVE_DATE;
/* Check if this dive was selected previously and select it again in the new model;
* This is used after we switch models to maintain consistent selections.
* We always return FALSE to iterate through all dives */
-static gboolean select_selected(GtkTreeModel *model, GtkTreePath *path,
+static gboolean set_selected(GtkTreeModel *model, GtkTreePath *path,
GtkTreeIter *iter, gpointer data)
{
- int i, idx;
GtkTreeSelection *selection = GTK_TREE_SELECTION(data);
+ int idx, selected;
+ struct dive *dive;
- gtk_tree_model_get(model, iter, DIVE_INDEX, &idx, -1);
- for (i = 0; i < old_nr_selected; i++)
- if (oldselection[i] == idx) {
- gtk_tree_view_expand_to_path(GTK_TREE_VIEW(dive_list.tree_view), path);
- gtk_tree_selection_select_path(selection, path);
-
- return FALSE;
- }
+ gtk_tree_model_get(model, iter,
+ DIVE_INDEX, &idx,
+ -1);
+ if (idx < 0) {
+ GtkTreeIter child;
+ if (gtk_tree_model_iter_children(model, &child, iter))
+ gtk_tree_model_get(model, &child, DIVE_INDEX, &idx, -1);
+ }
+ dive = get_dive(idx);
+ selected = dive && dive->selected;
+ if (selected) {
+ gtk_tree_view_expand_to_path(GTK_TREE_VIEW(dive_list.tree_view), path);
+ gtk_tree_selection_select_path(selection, path);
+ }
return FALSE;
}
if (dive_list.model != currentmodel) {
GtkTreeSelection *selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(dive_list.tree_view));
- /* remember what is currently selected, switch models and reselect the selected rows */
- old_nr_selected = amount_selected;
- oldselection = malloc(old_nr_selected * sizeof(int));
- if (amount_selected)
- memcpy(oldselection, selectiontracker, amount_selected * sizeof(int));
gtk_tree_view_set_model(GTK_TREE_VIEW(dive_list.tree_view), GTK_TREE_MODEL(dive_list.model));
-
update_column_and_order(colid);
-
- if (old_nr_selected) {
- /* we need to select all the dives that were selected */
- /* this is fundamentally an n^2 algorithm as implemented - YUCK */
- gtk_tree_model_foreach(GTK_TREE_MODEL(dive_list.model), select_selected, selection);
- }
+ gtk_tree_model_foreach(GTK_TREE_MODEL(dive_list.model), set_selected, selection);
} else {
if (order != sortorder[colid]) {
update_column_and_order(colid);
g_signal_connect_after(dive_list.tree_view, "realize", G_CALLBACK(realize_cb), NULL);
g_signal_connect(dive_list.tree_view, "row-activated", G_CALLBACK(row_activated_cb), NULL);
+ g_signal_connect(dive_list.tree_view, "row-expanded", G_CALLBACK(row_expanded_cb), NULL);
+ g_signal_connect(dive_list.tree_view, "row-collapsed", G_CALLBACK(row_collapsed_cb), NULL);
g_signal_connect(dive_list.tree_view, "button-press-event", G_CALLBACK(button_press_cb), NULL);
g_signal_connect(dive_list.tree_view, "popup-menu", G_CALLBACK(popup_menu_cb), NULL);
- g_signal_connect(selection, "changed", G_CALLBACK(selection_cb), NULL);
+ g_signal_connect(selection, "changed", G_CALLBACK(selection_cb), dive_list.model);
g_signal_connect(dive_list.listmodel, "sort-column-changed", G_CALLBACK(sort_column_change_cb), NULL);
g_signal_connect(dive_list.treemodel, "sort-column-changed", G_CALLBACK(sort_column_change_cb), NULL);