mirror of
https://github.com/subsurface/subsurface.git
synced 2025-02-19 22:16:15 +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 GList *selected_dives;
|
||||||
static int *selectiontracker;
|
static int *selectiontracker;
|
||||||
|
|
||||||
/* if we are sorting by date and are using a tree model, we don't want the selection
|
/* when subsurface starts we want to have the last dive selected. So we simply
|
||||||
to be a summary entry, but instead the first child below that entry. So we descend
|
walk to the first leaf (and skip the summary entries - which have negative
|
||||||
down the tree until we find a leaf (entry with non-negative index)
|
DIVE_INDEX) */
|
||||||
*/
|
|
||||||
static void first_leaf(GtkTreeModel *model, GtkTreeIter *iter, int *diveidx)
|
static void first_leaf(GtkTreeModel *model, GtkTreeIter *iter, int *diveidx)
|
||||||
{
|
{
|
||||||
GtkTreeIter parent;
|
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))
|
if (!gtk_tree_model_iter_children(model, iter, &parent))
|
||||||
/* we should never have a parent without child */
|
/* we should never have a parent without child */
|
||||||
return;
|
return;
|
||||||
/* clicking on a parent should toggle expand status */
|
if(!gtk_tree_view_row_expanded(GTK_TREE_VIEW(dive_list.tree_view), tpath))
|
||||||
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
|
|
||||||
gtk_tree_view_expand_row(GTK_TREE_VIEW(dive_list.tree_view), tpath, FALSE);
|
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);
|
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)
|
static void selection_cb(GtkTreeSelection *selection, gpointer userdata)
|
||||||
{
|
{
|
||||||
GtkTreeIter iter;
|
GtkTreeIter iter;
|
||||||
|
@ -120,7 +161,9 @@ static void selection_cb(GtkTreeSelection *selection, gpointer userdata)
|
||||||
selectiontracker = realloc(selectiontracker, nr_selected * sizeof(int));
|
selectiontracker = realloc(selectiontracker, nr_selected * sizeof(int));
|
||||||
|
|
||||||
switch (nr_selected) {
|
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;
|
return;
|
||||||
case 1:
|
case 1:
|
||||||
/* just pick that dive as selected */
|
/* 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);
|
path = g_list_nth_data(selected_dives, 0);
|
||||||
if (gtk_tree_model_get_iter(GTK_TREE_MODEL(dive_list.model), &iter, path)) {
|
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);
|
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 */
|
/* due to the way this callback gets invoked it is possible that
|
||||||
first_leaf (GTK_TREE_MODEL(dive_list.model), &iter, &selected_dive);
|
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;
|
selectiontracker[0] = selected_dive;
|
||||||
repaint_dive();
|
repaint_dive();
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
default: /* multiple selections - what now? At this point I
|
default: /* multiple selections - what now?
|
||||||
* don't want to change the selected dive unless
|
* We don't change the selected dive unless there is exactly one dive selected; not sure this
|
||||||
* there is exactly one dive selected; not sure this
|
|
||||||
* is the most intuitive solution.
|
* is the most intuitive solution.
|
||||||
* I do however want to keep around which dives have
|
* The dives that have been selected are processed */
|
||||||
* 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 */
|
|
||||||
amount_selected = g_list_length(selected_dives);
|
amount_selected = g_list_length(selected_dives);
|
||||||
process_selected_dives(selected_dives, selectiontracker, GTK_TREE_MODEL(dive_list.model));
|
process_selected_dives(selected_dives, selectiontracker, GTK_TREE_MODEL(dive_list.model));
|
||||||
repaint_dive();
|
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)) {
|
if (gtk_tree_model_get_iter_first(GTK_TREE_MODEL(dive_list.model), &iter)) {
|
||||||
GtkTreeSelection *selection;
|
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);
|
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);
|
first_leaf(GTK_TREE_MODEL(dive_list.model), &iter, &selected_dive);
|
||||||
selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(dive_list.tree_view));
|
selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(dive_list.tree_view));
|
||||||
gtk_tree_selection_select_iter(selection, &iter);
|
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.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);
|
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);
|
dive_list.container_widget = gtk_scrolled_window_new(NULL, NULL);
|
||||||
gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(dive_list.container_widget),
|
gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(dive_list.container_widget),
|
||||||
GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
|
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)
|
void process_selected_dives(GList *selected_dives, int *selectiontracker, GtkTreeModel *model)
|
||||||
{
|
{
|
||||||
struct dive *dp;
|
struct dive *dp;
|
||||||
unsigned int i;
|
unsigned int i, j;
|
||||||
int idx;
|
int idx;
|
||||||
GtkTreeIter iter;
|
GtkTreeIter iter;
|
||||||
GtkTreePath *path;
|
GtkTreePath *path;
|
||||||
|
|
||||||
memset(&stats_selection, 0, sizeof(stats_selection));
|
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, };
|
GValue value = {0, };
|
||||||
path = g_list_nth_data(selected_dives, i);
|
path = g_list_nth_data(selected_dives, i);
|
||||||
if (gtk_tree_model_get_iter(model, &iter, path)) {
|
if (gtk_tree_model_get_iter(model, &iter, path)) {
|
||||||
gtk_tree_model_get_value(model, &iter, 0, &value);
|
gtk_tree_model_get_value(model, &iter, 0, &value);
|
||||||
idx = g_value_get_int(&value);
|
idx = g_value_get_int(&value);
|
||||||
dp = get_dive(idx);
|
if (idx > 0) {
|
||||||
if (dp) {
|
dp = get_dive(idx);
|
||||||
selectiontracker[i] = idx;
|
if (dp) {
|
||||||
process_dive(dp, &stats_selection);
|
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, ...)
|
static void set_label(GtkWidget *w, const char *fmt, ...)
|
||||||
|
|
Loading…
Add table
Reference in a new issue