X-Git-Url: http://git.tdb.fi/?a=blobdiff_plain;f=divelist.c;h=99f3446ce5eca25bc21165e3400858fc6e00420c;hb=ed1ce8ebc8590533291a9c5d6460f8d1c9f857dd;hp=19ab600e8d6dec95121eb69b9221b4a74dc6dfab;hpb=7cf0f6d5e19f57449078901a3730f9e40de3a012;p=ext%2Fsubsurface.git diff --git a/divelist.c b/divelist.c index 19ab600..99f3446 100644 --- a/divelist.c +++ b/divelist.c @@ -26,7 +26,7 @@ struct DiveList { GtkWidget *container_widget; GtkTreeStore *model, *listmodel, *treemodel; GtkTreeViewColumn *nr, *date, *stars, *depth, *duration, *location; - GtkTreeViewColumn *temperature, *cylinder, *nitrox, *sac, *otu; + GtkTreeViewColumn *temperature, *cylinder, *totalweight, *suit, *nitrox, *sac, *otu; int changed; }; @@ -44,6 +44,8 @@ enum { DIVE_DEPTH, /* int: dive->maxdepth in mm */ DIVE_DURATION, /* int: in seconds */ DIVE_TEMPERATURE, /* int: in mkelvin */ + DIVE_TOTALWEIGHT, /* int: in grams */ + DIVE_SUIT, /* "wet, 3mm" */ DIVE_CYLINDER, DIVE_NITROX, /* int: dummy */ DIVE_SAC, /* int: in ml/min */ @@ -77,7 +79,6 @@ static void dump_model(GtkListStore *store) #endif static GList *selected_dives; -static int *selectiontracker; static int st_size = 0; gboolean is_in_st(int idx, int *atpos) @@ -151,6 +152,11 @@ void track_unselect(int idx) #endif } +void clear_tracker(void) +{ + amount_selected = 0; +} + /* 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) */ @@ -168,7 +174,6 @@ static void first_leaf(GtkTreeModel *model, GtkTreeIter *iter, int *diveidx) 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); - track_select(*diveidx); } } @@ -178,31 +183,36 @@ static void select_children(GtkTreeModel *model, GtkTreeSelection * selection, GtkTreeIter *iter, gboolean was_selected) { int i, nr_children; - gboolean unexpand = FALSE; + gboolean expanded = FALSE; GtkTreeIter parent; GtkTreePath *tpath; memcpy(&parent, iter, sizeof(parent)); tpath = gtk_tree_model_get_path(model, &parent); - - /* stupid gtk doesn't allow us to select rows that are invisible; so if the - user clicks on a row that isn't expanded, we briefly expand it, select the - children, and then unexpand it again */ - if(!gtk_tree_view_row_expanded(GTK_TREE_VIEW(dive_list.tree_view), tpath)) { - unexpand = TRUE; - gtk_tree_view_expand_row(GTK_TREE_VIEW(dive_list.tree_view), tpath, FALSE); - } + expanded = gtk_tree_view_row_expanded(GTK_TREE_VIEW(dive_list.tree_view), tpath); 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); + + /* if the parent is expanded, just (un)select the children and we'll + track their selection status in the callback + otherwise just change the selection status directly without + bothering gtk */ + if (expanded) { + if (was_selected) + gtk_tree_selection_unselect_iter(selection, iter); + else + gtk_tree_selection_select_iter(selection, iter); + } else { + int idx; + gtk_tree_model_get(model, iter, DIVE_INDEX, &idx, -1); + if (was_selected) + track_unselect(idx); + else + track_select(idx); + } } - if (unexpand) - gtk_tree_view_collapse_row(GTK_TREE_VIEW(dive_list.tree_view), tpath); } /* make sure that if we expand a summary row that is selected, the children show @@ -224,14 +234,29 @@ gboolean modify_selection_cb(GtkTreeSelection *selection, GtkTreeModel *model, GtkTreeIter iter; int dive_idx; + /* if gtk thinks nothing is selected we should clear out our + tracker as well - otherwise hidden selected rows can stay + "stuck". The down side is that we now have a different bug: + If you select a dive, collapse the dive trip and ctrl-click + another dive trip, the initial dive is no longer selected. + Just don't do that, ok? */ + if (gtk_tree_selection_count_selected_rows(selection) == 0) + clear_tracker(); + if (gtk_tree_model_get_iter(model, &iter, path)) { gtk_tree_model_get(model, &iter, DIVE_INDEX, &dive_idx, -1); /* turns out we need to move the selectiontracker here */ - if (was_selected) - track_unselect(dive_idx); - else - track_select(dive_idx); - if (dive_idx < 0) { + +#if DEBUG_SELECTION_TRACKING + printf("modify_selection_cb with idx %d (according to gtk was %sselected)\n", + dive_idx, was_selected ? "" : "un"); +#endif + if (dive_idx >= 0) { + if (was_selected) + track_unselect(dive_idx); + else + track_select(dive_idx); + } else { select_children(model, selection, &iter, was_selected); } } @@ -281,12 +306,12 @@ static void date_data_func(GtkTreeViewColumn *col, 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; @@ -295,10 +320,11 @@ static void date_data_func(GtkTreeViewColumn *col, switch(idx) { case -NEW_TRIP: 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); + tm->tm_mday, tm->tm_year + 1900, + nr, nr > 1 ? "s" : ""); break; default: snprintf(buffer, sizeof(buffer), @@ -459,6 +485,38 @@ newmax: *o2low_p = mino2; } +static int total_weight(struct dive *dive) +{ + int i, total_grams = 0; + + if (dive) + for (i=0; i< MAX_WEIGHTSYSTEMS; i++) + total_grams += dive->weightsystem[i].weight.grams; + return total_grams; +} + +static void weight_data_func(GtkTreeViewColumn *col, + GtkCellRenderer *renderer, + GtkTreeModel *model, + GtkTreeIter *iter, + gpointer data) +{ + int indx, decimals; + double value; + char buffer[80]; + struct dive *dive; + + gtk_tree_model_get(model, iter, DIVE_INDEX, &indx, -1); + dive = get_dive(indx); + value = get_weight_units(total_weight(dive), &decimals, NULL); + if (value == 0.0) + *buffer = '\0'; + else + snprintf(buffer, sizeof(buffer), "%.*f", decimals, value); + + g_object_set(renderer, "text", buffer, NULL); +} + static gint nitrox_sort_func(GtkTreeModel *model, GtkTreeIter *iter_a, GtkTreeIter *iter_b, @@ -693,6 +751,11 @@ static void get_cylinder(struct dive *dive, char **str) get_string(str, dive->cylinder[0].type.description); } +static void get_suit(struct dive *dive, char **str) +{ + get_string(str, dive->suit); +} + /* * Set up anything that could have changed due to editing * of dive information; we need to do this for both models, @@ -708,11 +771,12 @@ static void fill_one_dive(struct dive *dive, GtkTreeModel *model, GtkTreeIter *iter) { - char *location, *cylinder; + char *location, *cylinder, *suit; GtkTreeStore *othermodel; get_cylinder(dive, &cylinder); get_location(dive, &location); + get_suit(dive, &suit); gtk_tree_store_set(GTK_TREE_STORE(model), iter, DIVE_NR, dive->number, @@ -721,7 +785,14 @@ static void fill_one_dive(struct dive *dive, DIVE_RATING, dive->rating, DIVE_SAC, dive->sac, DIVE_OTU, dive->otu, + DIVE_TOTALWEIGHT, total_weight(dive), + DIVE_SUIT, suit, -1); + + free(location); + free(cylinder); + free(suit); + if (model == GTK_TREE_MODEL(dive_list.treemodel)) othermodel = dive_list.listmodel; else @@ -778,6 +849,9 @@ void update_dive_list_units(void) (void) get_temp_units(0, &unit); gtk_tree_view_column_set_title(dive_list.temperature, unit); + (void) get_weight_units(0, NULL, &unit); + gtk_tree_view_column_set_title(dive_list.totalweight, unit); + gtk_tree_model_foreach(model, set_one_dive, NULL); } @@ -785,6 +859,8 @@ void update_dive_list_col_visibility(void) { gtk_tree_view_column_set_visible(dive_list.cylinder, visible_cols.cylinder); gtk_tree_view_column_set_visible(dive_list.temperature, visible_cols.temperature); + gtk_tree_view_column_set_visible(dive_list.totalweight, visible_cols.totalweight); + gtk_tree_view_column_set_visible(dive_list.suit, visible_cols.suit); gtk_tree_view_column_set_visible(dive_list.nitrox, visible_cols.nitrox); gtk_tree_view_column_set_visible(dive_list.sac, visible_cols.sac); gtk_tree_view_column_set_visible(dive_list.otu, visible_cols.otu); @@ -817,12 +893,12 @@ static int new_group(struct dive *dive, struct dive **last_dive, time_t *tm_date static void fill_dive_list(void) { - int i; + int i, group_size; GtkTreeIter iter, parent_iter; GtkTreeStore *liststore, *treestore; struct dive *last_dive = NULL; - struct dive *first_trip_dive = NULL; struct dive *last_trip_dive = NULL; + const char *last_location = NULL; time_t dive_date; treestore = GTK_TREE_STORE(dive_list.treemodel); @@ -835,24 +911,29 @@ static void fill_dive_list(void) 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) + if (last_trip_dive) gtk_tree_store_set(treestore, &parent_iter, - DIVE_DATE, last_trip_dive->when, - DIVE_LOCATION, last_trip_dive->location, - -1); - first_trip_dive = dive; + DIVE_NR, group_size, + DIVE_DATE, last_trip_dive->when, + DIVE_LOCATION, last_location, + -1); 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_NR, 1, DIVE_TEMPERATURE, 0, DIVE_SAC, 0, -1); + + group_size = 0; + /* This might be NULL */ + last_location = dive->location; } + group_size++; last_trip_dive = dive; + if (dive->location) + last_location = dive->location; update_cylinder_related_info(dive); gtk_tree_store_append(treestore, &iter, &parent_iter); gtk_tree_store_set(treestore, &iter, @@ -876,10 +957,20 @@ static void fill_dive_list(void) DIVE_LOCATION, dive->location, DIVE_RATING, dive->rating, DIVE_TEMPERATURE, dive->watertemp.mkelvin, + DIVE_TOTALWEIGHT, 0, + DIVE_SUIT, dive->suit, DIVE_SAC, 0, -1); } + /* make sure we display the first date of the trip in previous summary */ + if (last_trip_dive) + gtk_tree_store_set(treestore, &parent_iter, + DIVE_NR, group_size, + DIVE_DATE, last_trip_dive->when, + DIVE_LOCATION, last_location, + -1); + update_dive_list_units(); if (gtk_tree_model_get_iter_first(GTK_TREE_MODEL(dive_list.model), &iter)) { GtkTreeSelection *selection; @@ -913,6 +1004,8 @@ static struct divelist_column { [DIVE_DEPTH] = { "ft", depth_data_func, NULL, ALIGN_RIGHT }, [DIVE_DURATION] = { "min", duration_data_func, NULL, ALIGN_RIGHT }, [DIVE_TEMPERATURE] = { UTF8_DEGREE "F", temperature_data_func, NULL, ALIGN_RIGHT, &visible_cols.temperature }, + [DIVE_TOTALWEIGHT] = { "lbs", weight_data_func, NULL, ALIGN_RIGHT, &visible_cols.totalweight }, + [DIVE_SUIT] = { "Suit", NULL, NULL, ALIGN_LEFT, &visible_cols.suit }, [DIVE_CYLINDER] = { "Cyl", NULL, NULL, 0, &visible_cols.cylinder }, [DIVE_NITROX] = { "O" UTF8_SUBSCRIPT_2 "%", nitrox_data_func, nitrox_sort_func, 0, &visible_cols.nitrox }, [DIVE_SAC] = { "SAC", sac_data_func, NULL, 0, &visible_cols.sac }, @@ -956,6 +1049,20 @@ static void realize_cb(GtkWidget *tree_view, gpointer userdata) 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, @@ -966,10 +1073,14 @@ static void row_activated_cb(GtkTreeView *tree_view, 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) @@ -992,11 +1103,13 @@ void edit_dive_cb(GtkWidget *menuitem, gpointer data) 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) { @@ -1140,6 +1253,8 @@ GtkWidget *dive_list_create(void) G_TYPE_INT, /* Depth */ G_TYPE_INT, /* Duration */ G_TYPE_INT, /* Temperature */ + G_TYPE_INT, /* Total weight */ + G_TYPE_STRING, /* Suit */ G_TYPE_STRING, /* Cylinder */ G_TYPE_INT, /* Nitrox */ G_TYPE_INT, /* SAC */ @@ -1154,6 +1269,8 @@ GtkWidget *dive_list_create(void) G_TYPE_INT, /* Depth */ G_TYPE_INT, /* Duration */ G_TYPE_INT, /* Temperature */ + G_TYPE_INT, /* Total weight */ + G_TYPE_STRING, /* Suit */ G_TYPE_STRING, /* Cylinder */ G_TYPE_INT, /* Nitrox */ G_TYPE_INT, /* SAC */ @@ -1175,6 +1292,8 @@ GtkWidget *dive_list_create(void) dive_list.depth = divelist_column(&dive_list, dl_column + DIVE_DEPTH); dive_list.duration = divelist_column(&dive_list, dl_column + DIVE_DURATION); dive_list.temperature = divelist_column(&dive_list, dl_column + DIVE_TEMPERATURE); + dive_list.totalweight = divelist_column(&dive_list, dl_column + DIVE_TOTALWEIGHT); + dive_list.suit = divelist_column(&dive_list, dl_column + DIVE_SUIT); dive_list.cylinder = divelist_column(&dive_list, dl_column + DIVE_CYLINDER); dive_list.nitrox = divelist_column(&dive_list, dl_column + DIVE_NITROX); dive_list.sac = divelist_column(&dive_list, dl_column + DIVE_SAC);