]> git.tdb.fi Git - ext/subsurface.git/commitdiff
Add capability of custom sorts to divelist columns
authorLinus Torvalds <torvalds@linux-foundation.org>
Sun, 11 Dec 2011 22:38:58 +0000 (14:38 -0800)
committerLinus Torvalds <torvalds@linux-foundation.org>
Sun, 11 Dec 2011 22:38:58 +0000 (14:38 -0800)
.. and use this for the nitrox column, which can now be more complex
than just a single number.

The rule for the "nitrox" column is now:

 - we look up the highest Oxygen and Helium mix for the dive

   (Note: we look them up independently, so if you have a EAN50 deco
   bottle, and a 20% Helium low-oxygen bottle for the deep portion, then
   we'll consider the dive to be a "50% Oxygen, 20% Helium" dive, even
   though you obviously never used that combination at the same time)

 - we sort by Helium first, Oxygen second.  So a dive with a 10% Helium
   mix is considered to be "stronger" than a 50% Nitrox mix.

 - If Helium is non-zero, we show "O2/He", otherwise we show just "O2"
   (or "air").  So "21/20" means "21% oxygen, 20% Helium", while "40"
   means "Ean 40".

 - I got rid of the decimals.  We save them, and you can see them in the
   dive equipment details, but for the dive list we just use rounded
   percentages.

Let's see how many bugs I introduced.  I don't actually have any trimix
dives, but I edited a few for (very limited) testing.

Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
display-gtk.h
divelist.c

index d5ffcb246de00702985882648e3372184745d7ae..8ca5a450e35002bcc2fa708c11402a7c7c165a3b 100644 (file)
@@ -57,6 +57,11 @@ typedef void (*data_func_t)(GtkTreeViewColumn *col,
                            GtkTreeIter *iter,
                            gpointer data);
 
+typedef gint (*sort_func_t)(GtkTreeModel *model,
+                           GtkTreeIter *a,
+                           GtkTreeIter *b,
+                           gpointer user_data);
+
 #define ALIGN_LEFT 1
 #define ALIGN_RIGHT 2
 #define INVISIBLE 4
index 6674f1df43d87f8950da23ea7d1cfd7f510d19f0..546d54bd0a16cc37e6583e988a8bf676b498bc64 100644 (file)
@@ -45,7 +45,7 @@ enum {
        DIVE_DURATION,          /* int: in seconds */
        DIVE_TEMPERATURE,       /* int: in mkelvin */
        DIVE_CYLINDER,
-       DIVE_NITROX,            /* int: in permille */
+       DIVE_NITROX,            /* int: dummy */
        DIVE_SAC,               /* int: in ml/min */
        DIVE_OTU,               /* int: in OTUs */
        DIVE_LOCATION,          /* "2nd Cathedral, Lanai" */
@@ -223,19 +223,66 @@ static void temperature_data_func(GtkTreeViewColumn *col,
        g_object_set(renderer, "text", buffer, NULL);
 }
 
+/* Get max O2/He permille levels for a dive for the dive summary */
+static void get_dive_gas(struct dive *dive, int *o2, int *he)
+{
+       int i;
+       int maxo2 = -1, maxhe = -1;
+
+       for (i = 0; i < MAX_CYLINDERS; i++) {
+               struct gasmix *mix = &dive->cylinder[i].gasmix;
+               if (mix->o2.permille > maxo2)
+                       maxo2 = mix->o2.permille;
+               if (mix->he.permille > maxhe)
+                       maxhe = mix->he.permille;
+       }
+       *o2 = maxo2;
+       *he = maxhe;
+}
+
+static gint nitrox_sort_func(GtkTreeModel *model,
+       GtkTreeIter *iter_a,
+       GtkTreeIter *iter_b,
+       gpointer user_data)
+{
+       int index_a, index_b;
+       struct dive *a, *b;
+       int a_o2, b_o2;
+       int a_he, b_he;
+
+       gtk_tree_model_get(model, iter_a, DIVE_INDEX, &index_a, -1);
+       gtk_tree_model_get(model, iter_b, DIVE_INDEX, &index_b, -1);
+       a = get_dive(index_a);
+       b = get_dive(index_b);
+       get_dive_gas(a, &a_o2, &a_he);
+       get_dive_gas(b, &b_o2, &b_he);
+
+       /* Sort by Helium first, O2 second */
+       if (a_he == b_he)
+               return a_o2 - b_o2;
+       return a_he - b_he;
+}
+
 static void nitrox_data_func(GtkTreeViewColumn *col,
                             GtkCellRenderer *renderer,
                             GtkTreeModel *model,
                             GtkTreeIter *iter,
                             gpointer data)
 {
-       int value;
+       int index, o2, he;
        char buffer[80];
+       struct dive *dive;
 
-       gtk_tree_model_get(model, iter, DIVE_NITROX, &value, -1);
+       gtk_tree_model_get(model, iter, DIVE_INDEX, &index, -1);
+       dive = get_dive(index);
+       get_dive_gas(dive, &o2, &he);
+       o2 = (o2 + 5) / 10;
+       he = (he + 5) / 10;
 
-       if (value)
-               snprintf(buffer, sizeof(buffer), "%.1f", value/10.0);
+       if (he)
+               snprintf(buffer, sizeof(buffer), "%d/%d", o2, he);
+       else if (o2)
+               snprintf(buffer, sizeof(buffer), "%d", o2);
        else
                strcpy(buffer, "air");
 
@@ -433,7 +480,6 @@ static void fill_one_dive(struct dive *dive,
                DIVE_RATING, dive->rating,
                DIVE_SAC, dive->sac,
                DIVE_OTU, dive->otu,
-               DIVE_NITROX, dive->cylinder[0].gasmix.o2,
                -1);
 }
 
@@ -517,7 +563,6 @@ static void fill_dive_list(void)
                        DIVE_DURATION, dive->duration.seconds,
                        DIVE_LOCATION, "location",
                        DIVE_TEMPERATURE, dive->watertemp.mkelvin,
-                       DIVE_NITROX, dive->cylinder[0].gasmix.o2,
                        DIVE_SAC, 0,
                        -1);
        }
@@ -537,12 +582,45 @@ void dive_list_update_dives(void)
        repaint_dive();
 }
 
-static GtkTreeViewColumn *divelist_column(struct DiveList *dl, int index, const char *title,
-                               data_func_t data_func, unsigned int flags, int visible)
+static struct divelist_column {
+       const char *header;
+       data_func_t data;
+       sort_func_t sort;
+       unsigned int flags;
+       int *visible;
+} column[] = {
+       [DIVE_NR] = { "#", NULL, NULL, ALIGN_RIGHT | UNSORTABLE },
+       [DIVE_DATE] = { "Date", date_data_func, NULL, ALIGN_LEFT },
+       [DIVE_RATING] = { UTF8_BLACKSTAR, star_data_func, NULL, ALIGN_LEFT },
+       [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_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 },
+       [DIVE_OTU] = { "OTU", otu_data_func, NULL, 0, &visible_cols.otu },
+       [DIVE_LOCATION] = { "Location", NULL, NULL, ALIGN_LEFT },
+};
+
+
+static GtkTreeViewColumn *divelist_column(struct DiveList *dl, struct divelist_column *col)
 {
-       if (!visible)
+       int index = col - &column[0];
+       const char *title = col->header;
+       data_func_t data_func = col->data;
+       sort_func_t sort_func = col->sort;
+       unsigned int flags = col->flags;
+       int *visible = col->visible;
+       GtkWidget *tree_view = dl->tree_view;
+       GtkListStore *model = dl->model;
+       GtkTreeViewColumn *ret;
+
+       if (visible && !*visible)
                flags |= INVISIBLE;
-       return tree_view_column(dl->tree_view, index, title, data_func, flags);
+       ret = tree_view_column(tree_view, index, title, data_func, flags);
+       if (sort_func)
+               gtk_tree_sortable_set_sort_func(GTK_TREE_SORTABLE(model), index, sort_func, NULL, NULL);
+       return ret;
 }
 
 /*
@@ -594,17 +672,17 @@ GtkWidget *dive_list_create(void)
        gtk_tree_selection_set_mode(GTK_TREE_SELECTION(selection), GTK_SELECTION_MULTIPLE);
        gtk_widget_set_size_request(dive_list.tree_view, 200, 200);
 
-       dive_list.nr = divelist_column(&dive_list, DIVE_NR, "#", NULL, ALIGN_RIGHT | UNSORTABLE, TRUE);
-       dive_list.date = divelist_column(&dive_list, DIVE_DATE, "Date", date_data_func, ALIGN_LEFT, TRUE);
-       dive_list.stars = divelist_column(&dive_list, DIVE_RATING, UTF8_BLACKSTAR, star_data_func, ALIGN_LEFT, TRUE);
-       dive_list.depth = divelist_column(&dive_list, DIVE_DEPTH, "ft", depth_data_func, ALIGN_RIGHT, TRUE);
-       dive_list.duration = divelist_column(&dive_list, DIVE_DURATION, "min", duration_data_func, ALIGN_RIGHT, TRUE);
-       dive_list.temperature = divelist_column(&dive_list, DIVE_TEMPERATURE, UTF8_DEGREE "F", temperature_data_func, ALIGN_RIGHT, visible_cols.temperature);
-       dive_list.cylinder = divelist_column(&dive_list, DIVE_CYLINDER, "Cyl", NULL, 0, visible_cols.cylinder);
-       dive_list.nitrox = divelist_column(&dive_list, DIVE_NITROX, "O" UTF8_SUBSCRIPT_2 "%", nitrox_data_func, 0, visible_cols.nitrox);
-       dive_list.sac = divelist_column(&dive_list, DIVE_SAC, "SAC", sac_data_func, 0, visible_cols.sac);
-       dive_list.otu = divelist_column(&dive_list, DIVE_OTU, "OTU", otu_data_func, 0, visible_cols.otu);
-       dive_list.location = divelist_column(&dive_list, DIVE_LOCATION, "Location", NULL, ALIGN_LEFT, TRUE);
+       dive_list.nr = divelist_column(&dive_list, column + DIVE_NR);
+       dive_list.date = divelist_column(&dive_list, column + DIVE_DATE);
+       dive_list.stars = divelist_column(&dive_list, column + DIVE_RATING);
+       dive_list.depth = divelist_column(&dive_list, column + DIVE_DEPTH);
+       dive_list.duration = divelist_column(&dive_list, column + DIVE_DURATION);
+       dive_list.temperature = divelist_column(&dive_list, column + DIVE_TEMPERATURE);
+       dive_list.cylinder = divelist_column(&dive_list, column + DIVE_CYLINDER);
+       dive_list.nitrox = divelist_column(&dive_list, column + DIVE_NITROX);
+       dive_list.sac = divelist_column(&dive_list, column + DIVE_SAC);
+       dive_list.otu = divelist_column(&dive_list, column + DIVE_OTU);
+       dive_list.location = divelist_column(&dive_list, column + DIVE_LOCATION);
 
        fill_dive_list();