]> git.tdb.fi Git - ext/subsurface.git/blobdiff - divelist.c
Fix default size for scrollable notebook
[ext/subsurface.git] / divelist.c
index 19ab600e8d6dec95121eb69b9221b4a74dc6dfab..99f3446ce5eca25bc21165e3400858fc6e00420c 100644 (file)
@@ -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);