mirror of
https://github.com/subsurface/subsurface.git
synced 2024-11-30 22:20:21 +00:00
Fix selecting and unselecting summary items
The dive list now seems to behave intuitively. In order to do this we had to intercept the select function in addition to having a selection-changed callback. That way we can simulate the multi-level selection and unselection that was missing. Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
This commit is contained in:
parent
5ba89c13ac
commit
822b6409d7
2 changed files with 81 additions and 27 deletions
85
divelist.c
85
divelist.c
|
@ -81,10 +81,9 @@ static void dump_model(GtkListStore *store)
|
|||
static GList *selected_dives;
|
||||
static int *selectiontracker;
|
||||
|
||||
/* if we are sorting by date and are using a tree model, we don't want the selection
|
||||
to be a summary entry, but instead the first child below that entry. So we descend
|
||||
down the tree until we find a leaf (entry with non-negative index)
|
||||
*/
|
||||
/* 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
|
||||
DIVE_INDEX) */
|
||||
static void first_leaf(GtkTreeModel *model, GtkTreeIter *iter, int *diveidx)
|
||||
{
|
||||
GtkTreeIter parent;
|
||||
|
@ -96,15 +95,57 @@ static void first_leaf(GtkTreeModel *model, GtkTreeIter *iter, int *diveidx)
|
|||
if (!gtk_tree_model_iter_children(model, iter, &parent))
|
||||
/* we should never have a parent without child */
|
||||
return;
|
||||
/* clicking on a parent should toggle expand status */
|
||||
if(gtk_tree_view_row_expanded(GTK_TREE_VIEW(dive_list.tree_view), tpath))
|
||||
gtk_tree_view_collapse_row(GTK_TREE_VIEW(dive_list.tree_view), tpath);
|
||||
else
|
||||
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(GTK_TREE_MODEL(model), iter, DIVE_INDEX, diveidx, -1);
|
||||
}
|
||||
}
|
||||
|
||||
/* 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)
|
||||
{
|
||||
int i, nr_children;
|
||||
GtkTreeIter parent;
|
||||
GtkTreePath *tpath;
|
||||
|
||||
memcpy(&parent, iter, sizeof(parent));
|
||||
|
||||
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);
|
||||
|
||||
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);
|
||||
else
|
||||
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 */
|
||||
gboolean modify_selection_cb(GtkTreeSelection *selection, GtkTreeModel *model,
|
||||
GtkTreePath *path, gboolean was_selected, gpointer userdata)
|
||||
{
|
||||
GtkTreeIter iter;
|
||||
int dive_idx;
|
||||
|
||||
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 */
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/* this is called when gtk thinks that the selection has changed */
|
||||
static void selection_cb(GtkTreeSelection *selection, gpointer userdata)
|
||||
{
|
||||
GtkTreeIter iter;
|
||||
|
@ -120,7 +161,9 @@ static void selection_cb(GtkTreeSelection *selection, gpointer userdata)
|
|||
selectiontracker = realloc(selectiontracker, nr_selected * sizeof(int));
|
||||
|
||||
switch (nr_selected) {
|
||||
case 0: /* keep showing the last selected dive */
|
||||
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 */
|
||||
|
@ -128,21 +171,21 @@ static void selection_cb(GtkTreeSelection *selection, gpointer userdata)
|
|||
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);
|
||||
/* make sure we're not on a summary entry */
|
||||
first_leaf (GTK_TREE_MODEL(dive_list.model), &iter, &selected_dive);
|
||||
/* 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();
|
||||
}
|
||||
return;
|
||||
default: /* multiple selections - what now? At this point I
|
||||
* don't want to change the selected dive unless
|
||||
* there is exactly one dive selected; not sure this
|
||||
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.
|
||||
* I do however want to keep around which dives have
|
||||
* been selected */
|
||||
/* TODO:
|
||||
this also does not handle the case if a summary row is selected;
|
||||
We should iterate and select all dives under that row */
|
||||
* 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();
|
||||
|
@ -792,8 +835,8 @@ static void fill_dive_list(void)
|
|||
if (gtk_tree_model_get_iter_first(GTK_TREE_MODEL(dive_list.model), &iter)) {
|
||||
GtkTreeSelection *selection;
|
||||
|
||||
/* select the last dive (and make sure it's an actual dive that is selected) */
|
||||
gtk_tree_model_get(GTK_TREE_MODEL(dive_list.model), &iter, DIVE_INDEX, &selected_dive, -1);
|
||||
/* make sure it's an actual dive that is selected */
|
||||
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);
|
||||
|
@ -1093,6 +1136,8 @@ GtkWidget *dive_list_create(void)
|
|||
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);
|
||||
|
||||
gtk_tree_selection_set_select_function(selection, modify_selection_cb, NULL, NULL);
|
||||
|
||||
dive_list.container_widget = gtk_scrolled_window_new(NULL, NULL);
|
||||
gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(dive_list.container_widget),
|
||||
GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
|
||||
|
|
23
statistics.c
23
statistics.c
|
@ -142,30 +142,39 @@ static void process_all_dives(struct dive *dive, struct dive **prev_dive)
|
|||
}
|
||||
}
|
||||
|
||||
/* make sure we skip the selected summary entries */
|
||||
void process_selected_dives(GList *selected_dives, int *selectiontracker, GtkTreeModel *model)
|
||||
{
|
||||
struct dive *dp;
|
||||
unsigned int i;
|
||||
unsigned int i, j;
|
||||
int idx;
|
||||
GtkTreeIter iter;
|
||||
GtkTreePath *path;
|
||||
|
||||
memset(&stats_selection, 0, sizeof(stats_selection));
|
||||
stats_selection.selection_size = amount_selected;
|
||||
|
||||
for (i = 0; i < amount_selected; ++i) {
|
||||
/* adjust amount_selected and remove negative index entries from list */
|
||||
for (i = 0, j = 0; j < amount_selected; ++i) {
|
||||
GValue value = {0, };
|
||||
path = g_list_nth_data(selected_dives, i);
|
||||
if (gtk_tree_model_get_iter(model, &iter, path)) {
|
||||
gtk_tree_model_get_value(model, &iter, 0, &value);
|
||||
idx = g_value_get_int(&value);
|
||||
dp = get_dive(idx);
|
||||
if (dp) {
|
||||
selectiontracker[i] = idx;
|
||||
process_dive(dp, &stats_selection);
|
||||
if (idx > 0) {
|
||||
dp = get_dive(idx);
|
||||
if (dp) {
|
||||
selectiontracker[j] = idx;
|
||||
process_dive(dp, &stats_selection);
|
||||
j++;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
/* we didn't process it, so shorten the list */
|
||||
amount_selected--;
|
||||
}
|
||||
/* record the actual number of dives selected */
|
||||
stats_selection.selection_size = amount_selected;
|
||||
}
|
||||
|
||||
static void set_label(GtkWidget *w, const char *fmt, ...)
|
||||
|
|
Loading…
Reference in a new issue