]> git.tdb.fi Git - ext/subsurface.git/commitdiff
Improve tree model implementation
authorDirk Hohndel <dirk@hohndel.org>
Mon, 13 Aug 2012 20:09:40 +0000 (13:09 -0700)
committerDirk Hohndel <dirk@hohndel.org>
Tue, 14 Aug 2012 19:42:54 +0000 (12:42 -0700)
We now support three hierarchy levels: day, month, and year. Each
indicated by a negative DIVE_INDEX for -1 to -3. This allows a nice
compact overview when doing date based sorting (the default).

As indicated in the previous commit, things still go wrong with sorting by
other columns as the entries are only sorted within each day, not globally
across the whole dive list.

Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
divelist.c

index 8899d74297d267a6d2585a263457480e2fa95d0b..137b8a148fe173aee07627e4fba2fd2767e99acf 100644 (file)
@@ -52,6 +52,12 @@ enum {
        DIVELIST_COLUMNS
 };
 
+/* magic numbers that indicate (as negative values) model entries that
+ * are summary entries for day / month / year */
+#define NEW_DAY 1
+#define NEW_MON 2
+#define NEW_YR  3
+
 #ifdef DEBUG_MODEL
 static gboolean dump_model_entry(GtkTreeModel *model, GtkTreePath *path,
                                GtkTreeIter *iter, gpointer data)
@@ -77,7 +83,6 @@ static GList *selected_dives;
 static void selection_cb(GtkTreeSelection *selection, GtkTreeModel *model)
 {
        GtkTreeIter iter;
-       GValue value = {0, };
        GtkTreePath *path;
 
        int nr_selected = gtk_tree_selection_count_selected_rows(selection);
@@ -96,10 +101,23 @@ static void selection_cb(GtkTreeSelection *selection, GtkTreeModel *model)
                amount_selected = 1;
                path = g_list_nth_data(selected_dives, 0);
                if (gtk_tree_model_get_iter(model, &iter, path)) {
-                       gtk_tree_model_get_value(model, &iter, DIVE_INDEX, &value);
-                       /* an index of -1 should mean select all dives from that day
-                        * ===> still needs to be implemented */
-                       selected_dive = g_value_get_int(&value);
+                       gtk_tree_model_get(model, &iter, DIVE_INDEX, &selected_dive, -1);
+                       /* a negative index means we picked a summary entry;
+                          expand that entry and use first real child instead */
+                       while (selected_dive < 0) {
+                               GtkTreeIter parent;
+                               GtkTreePath *tpath;
+                               memcpy(&parent, &iter, sizeof(parent));
+                               tpath = gtk_tree_model_get_path(model, &parent);
+                               if (!gtk_tree_model_iter_children(model, &iter, &parent))
+                                       /* we should never have a parent without child */
+                                       return;
+                               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_model_get(model, &iter, DIVE_INDEX, &selected_dive, -1);
+                       }
                        repaint_dive();
                }
                return;
@@ -135,7 +153,7 @@ static void star_data_func(GtkTreeViewColumn *col,
        char buffer[40];
 
        gtk_tree_model_get(model, iter, DIVE_INDEX, &idx, DIVE_RATING, &nr_stars, -1);
-       if (idx == -1) {
+       if (idx < 0) {
                *buffer = '\0';
        } else {
                if (nr_stars < 0 || nr_stars > 5)
@@ -162,19 +180,32 @@ static void date_data_func(GtkTreeViewColumn *col,
        when = val;
 
        tm = gmtime(&when);
-       if (idx == -1)
+       switch(idx) {
+       case -NEW_DAY:
                snprintf(buffer, sizeof(buffer),
                        "%s, %s %d, %d",
                        weekday(tm->tm_wday),
                        monthname(tm->tm_mon),
                        tm->tm_mday, tm->tm_year + 1900);
-       else
+               break;
+       case -NEW_MON:
+               snprintf(buffer, sizeof(buffer),
+                       "%s %d",
+                       monthname(tm->tm_mon),
+                       tm->tm_year + 1900);
+               break;
+       case -NEW_YR:
+               snprintf(buffer, sizeof(buffer),
+                       "%d", tm->tm_year + 1900);
+               break;
+       default:
                snprintf(buffer, sizeof(buffer),
                        "%s, %s %d, %d %02d:%02d",
                        weekday(tm->tm_wday),
                        monthname(tm->tm_mon),
                        tm->tm_mday, tm->tm_year + 1900,
                        tm->tm_hour, tm->tm_min);
+       }
        g_object_set(renderer, "text", buffer, NULL);
 }
 
@@ -189,7 +220,7 @@ static void depth_data_func(GtkTreeViewColumn *col,
 
        gtk_tree_model_get(model, iter, DIVE_INDEX, &idx, DIVE_DEPTH, &depth, -1);
 
-       if (idx == -1) {
+       if (idx < 0) {
                *buffer = '\0';
        } else {
                switch (output_units.length) {
@@ -224,11 +255,12 @@ static void duration_data_func(GtkTreeViewColumn *col,
                               GtkTreeIter *iter,
                               gpointer data)
 {
-       unsigned int sec, idx;
+       unsigned int sec;
+       int idx;
        char buffer[16];
 
        gtk_tree_model_get(model, iter, DIVE_INDEX, &idx, DIVE_DURATION, &sec, -1);
-       if (idx == -1)
+       if (idx < 0)
                *buffer = '\0';
        else
                snprintf(buffer, sizeof(buffer), "%d:%02d", sec / 60, sec % 60);
@@ -248,7 +280,7 @@ static void temperature_data_func(GtkTreeViewColumn *col,
        gtk_tree_model_get(model, iter, DIVE_INDEX, &idx, DIVE_TEMPERATURE, &value, -1);
 
        *buffer = 0;
-       if (idx != -1 && value) {
+       if (idx >= 0 && value) {
                double deg;
                switch (output_units.temperature) {
                case CELSIUS:
@@ -276,7 +308,7 @@ static void nr_data_func(GtkTreeViewColumn *col,
        char buffer[40];
 
        gtk_tree_model_get(model, iter, DIVE_INDEX, &idx, DIVE_NR, &nr, -1);
-       if (idx == -1)
+       if (idx < 0)
                *buffer = '\0';
        else
                snprintf(buffer, sizeof(buffer), "%d", nr);
@@ -360,16 +392,16 @@ static void nitrox_data_func(GtkTreeViewColumn *col,
                             GtkTreeIter *iter,
                             gpointer data)
 {
-       int index, o2, he, o2low;
+       int idx, o2, he, o2low;
        char buffer[80];
        struct dive *dive;
 
-       gtk_tree_model_get(model, iter, DIVE_INDEX, &index, -1);
-       if (index == -1) {
+       gtk_tree_model_get(model, iter, DIVE_INDEX, &idx, -1);
+       if (idx < 0) {
                *buffer = '\0';
                goto exit;
        }
-       dive = get_dive(index);
+       dive = get_dive(idx);
        get_dive_gas(dive, &o2, &he, &o2low);
        o2 = (o2 + 5) / 10;
        he = (he + 5) / 10;
@@ -402,7 +434,7 @@ static void sac_data_func(GtkTreeViewColumn *col,
 
        gtk_tree_model_get(model, iter, DIVE_INDEX, &idx, DIVE_SAC, &value, -1);
 
-       if (idx == -1 || !value) {
+       if (idx < 0 || !value) {
                *buffer = '\0';
                goto exit;
        }
@@ -434,7 +466,7 @@ static void otu_data_func(GtkTreeViewColumn *col,
 
        gtk_tree_model_get(model, iter, DIVE_INDEX, &idx, DIVE_OTU, &value, -1);
 
-       if (idx == -1 || !value)
+       if (idx < 0 || !value)
                *buffer = '\0';
        else
                snprintf(buffer, sizeof(buffer), "%d", value);
@@ -592,8 +624,8 @@ static gboolean set_one_dive(GtkTreeModel *model,
 
        /* Get the dive number */
        gtk_tree_model_get(model, iter, DIVE_INDEX, &idx, -1);
-       if (idx == -1)
-               return TRUE;
+       if (idx < 0)
+               return FALSE;
        dive = get_dive(idx);
        if (!dive)
                return TRUE;
@@ -642,46 +674,36 @@ void update_dive_list_col_visibility(void)
        return;
 }
 
-static int new_day(struct dive *dive, struct dive **last_dive, time_t *tm_date)
+static int new_date(struct dive *dive, struct dive **last_dive, const int flag, time_t *tm_date)
 {
        if (!last_dive)
                return TRUE;
-       if (!*last_dive) {
-               *last_dive = dive;
-               if (tm_date) {
-                       struct tm *tm1 = gmtime(&dive->when);
-                       tm1->tm_sec = 0;
-                       tm1->tm_min = 0;
-                       tm1->tm_hour = 0;
-                       *tm_date = mktime(tm1);
-               }
-               return TRUE;
-       } else {
+       if (*last_dive) {
                struct dive *ldive = *last_dive;
                struct tm tm1, tm2;
                (void) gmtime_r(&dive->when, &tm1);
                (void) gmtime_r(&ldive->when, &tm2);
-               if (tm1.tm_year != tm2.tm_year ||
-                   tm1.tm_mon != tm2.tm_mon ||
-                   tm1.tm_mday != tm2.tm_mday) {
-                       *last_dive = dive;
-                       if (tm_date) {
-                               tm1.tm_sec = 0;
-                               tm1.tm_min = 0;
-                               tm1.tm_hour = 0;
-                               *tm_date = mktime(&tm1);
-                       }
-                       return TRUE;
-               }
+               if (tm1.tm_year == tm2.tm_year &&
+                       (tm1.tm_mon == tm2.tm_mon || flag > NEW_MON) &&
+                       (tm1.tm_mday == tm2.tm_mday || flag > NEW_DAY))
+                       return FALSE;
        }
-       return FALSE;
-
+       if (flag == NEW_DAY)
+               *last_dive = dive;
+       if (tm_date) {
+               struct tm *tm1 = gmtime(&dive->when);
+               tm1->tm_sec = 0;
+               tm1->tm_min = 0;
+               tm1->tm_hour = 0;
+               *tm_date = mktime(tm1);
+       }
+       return TRUE;
 }
 
 static void fill_dive_list(void)
 {
-       int i;
-       GtkTreeIter iter, parent_iter, *parent = NULL;
+       int i, j;
+       GtkTreeIter iter, parent_iter[NEW_YR + 2], *parents[NEW_YR + 2] = {NULL, };
        GtkTreeStore *store;
        struct dive *last_dive = NULL;
        time_t dive_date;
@@ -692,21 +714,23 @@ static void fill_dive_list(void)
        while (--i >= 0) {
                struct dive *dive = dive_table.dives[i];
 
-               if (new_day(dive, &last_dive, &dive_date))
-               {
-                       gtk_tree_store_append(store, &parent_iter, NULL);
-                       parent = &parent_iter;
-                       gtk_tree_store_set(store, parent,
-                               DIVE_INDEX, -1,
-                               DIVE_NR, -1,
-                               DIVE_DATE, dive_date,
-                               DIVE_LOCATION, "",
-                               DIVE_TEMPERATURE, 0,
-                               DIVE_SAC, 0,
-                               -1);
+               for (j = NEW_YR; j >= NEW_DAY; j--) {
+                       if (new_date(dive, &last_dive, j, &dive_date))
+                       {
+                               gtk_tree_store_append(store, &parent_iter[j], parents[j+1]);
+                               parents[j] = &parent_iter[j];
+                               gtk_tree_store_set(store, parents[j],
+                                               DIVE_INDEX, -j,
+                                               DIVE_NR, -j,
+                                               DIVE_DATE, dive_date,
+                                               DIVE_LOCATION, "",
+                                               DIVE_TEMPERATURE, 0,
+                                               DIVE_SAC, 0,
+                                               -1);
+                       }
                }
                update_cylinder_related_info(dive);
-               gtk_tree_store_append(store, &iter, parent);
+               gtk_tree_store_append(store, &iter, parents[NEW_DAY]);
                gtk_tree_store_set(store, &iter,
                        DIVE_INDEX, i,
                        DIVE_NR, dive->number,
@@ -796,8 +820,8 @@ static void row_activated_cb(GtkTreeView *tree_view,
        if (!gtk_tree_model_get_iter(model, &iter, path))
                return;
        gtk_tree_model_get(model, &iter, DIVE_INDEX, &index, -1);
-       /* an index of -1 is special for the "group by date" entries */
-       if (index != -1)
+       /* a negative index is special for the "group by date" entries */
+       if (index >= 0)
                edit_dive_info(get_dive(index));
 }