]> git.tdb.fi Git - ext/subsurface.git/blob - divelist.c
Start filling in temperature and nitrox data in dive list
[ext/subsurface.git] / divelist.c
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <string.h>
4 #include <time.h>
5
6 #include "divelist.h"
7 #include "dive.h"
8 #include "display.h"
9
10 /*
11  * The dive list has the dive data in both string format (for showing)
12  * and in "raw" format (for sorting purposes)
13  */
14 enum {
15         DIVE_INDEX = 0,
16         DIVE_DATESTR,           /* "Thu Jun 17th, 2011" or whatever */
17         DIVE_DATE,              /* time_t: dive->when */
18         DIVE_DEPTHSTR,          /* "67" in ft or whatever */
19         DIVE_DEPTH,             /* int: dive->maxdepth in mm */
20         DIVE_DURATIONSTR,       /* "47" in minutes */
21         DIVE_DURATION,          /* int: in seconds */
22         DIVE_TEMPSTR,           /* "78" in fahrenheit or whatever */
23         DIVE_TEMP,              /* int: in mkelvin */
24         DIVE_NITROXSTR,         /* "32.5" in percent */
25         DIVE_NITROX,            /* int: in permille */
26         DIVE_SACSTR,            /* "0.49" in cuft/min */
27         DIVE_SAC,               /* int: in ml/min or something */
28         DIVELIST_COLUMNS
29 };
30
31
32 static void selection_cb(GtkTreeSelection *selection, GtkTreeModel *model)
33 {
34         GtkTreeIter iter;
35         GValue value = {0, };
36
37         if (!gtk_tree_selection_get_selected(selection, NULL, &iter))
38                 return;
39
40         gtk_tree_model_get_value(model, &iter, DIVE_INDEX, &value);
41         selected_dive = g_value_get_int(&value);
42         repaint_dive();
43 }
44
45 static void get_temp(struct dive *dive, int *val, char **str)
46 {
47         int value = dive->watertemp.mkelvin;
48         char buffer[80];
49
50         *val = value;
51         *str = "";
52         if (value) {
53                 double deg;
54                 switch (output_units.temperature) {
55                 case CELSIUS:
56                         deg = mkelvin_to_C(value);
57                         break;
58                 case FAHRENHEIT:
59                         deg = mkelvin_to_F(value);
60                         break;
61                 default:
62                         return;
63                 }
64                 snprintf(buffer, sizeof(buffer), "%.1f", deg);
65                 *str = strdup(buffer);
66         }
67 }
68
69 static void get_nitrox(struct dive *dive, int *val, char **str)
70 {
71         int value = dive->cylinder[0].gasmix.o2.permille;
72         char buffer[80];
73
74         *val = value;
75         *str = "";
76         if (value) {
77                 snprintf(buffer, sizeof(buffer), "%.1f", value/10.0);
78                 *str = strdup(buffer);
79         }
80 }
81
82 static void get_sac(struct dive *dive, int *val, char **str)
83 {
84         *val = 0;
85         *str = "";
86 }
87
88 static gboolean set_one_dive(GtkTreeModel *model,
89                              GtkTreePath *path,
90                              GtkTreeIter *iter,
91                              gpointer data)
92 {
93         int len;
94         GValue value = {0, };
95         struct dive *dive;
96         char buffer[256], *datestr, *depth, *duration;
97         struct tm *tm;
98         int integer, frac;
99         int temp, nitrox, sac;
100         char *tempstr, *nitroxstr, *sacstr;
101
102         /* Get the dive number */
103         gtk_tree_model_get_value(model, iter, DIVE_INDEX, &value);
104         dive = get_dive(g_value_get_int(&value));
105         if (!dive)
106                 return TRUE;
107
108         tm = gmtime(&dive->when);
109         len = snprintf(buffer, sizeof(buffer),
110                 "%02d.%02d.%02d %02d:%02d",
111                 tm->tm_mday, tm->tm_mon+1, tm->tm_year % 100,
112                 tm->tm_hour, tm->tm_min);
113         datestr = malloc(len+1);
114         memcpy(datestr, buffer, len+1);
115
116         switch (output_units.length) {
117         unsigned int depth;
118         case METERS:
119                 depth = (dive->maxdepth.mm + 49) / 100;
120                 integer = depth / 10;
121                 frac = depth % 10;
122                 if (integer < 20)
123                         break;
124                 frac = -1;
125                 /* Rounding? */
126                 break;
127         case FEET:
128                 integer = to_feet(dive->maxdepth);
129                 frac = -1;
130         }
131         len = snprintf(buffer, sizeof(buffer),
132                        "%d", integer);
133         if (frac >= 0)
134                 len += snprintf(buffer+len, sizeof(buffer)-len,
135                         ".%d", frac);
136         depth = malloc(len + 1);
137         memcpy(depth, buffer, len+1);
138
139         len = snprintf(buffer, sizeof(buffer),
140                        "%d", dive->duration.seconds / 60);
141         duration = malloc(len + 1);
142         memcpy(duration, buffer, len+1);
143
144         get_temp(dive, &temp, &tempstr);
145         get_nitrox(dive, &nitrox, &nitroxstr);
146         get_sac(dive, &sac, &sacstr);
147
148         /*
149          * We only set the fields that changed: the strings.
150          * The core data itself is unaffected by units
151          */
152         gtk_list_store_set(GTK_LIST_STORE(model), iter,
153                 DIVE_DATESTR, datestr,
154                 DIVE_DEPTHSTR, depth,
155                 DIVE_DURATIONSTR, duration,
156                 DIVE_TEMPSTR, tempstr,
157                 DIVE_TEMP, temp,
158                 DIVE_NITROXSTR, nitroxstr,
159                 DIVE_NITROX, nitrox,
160                 DIVE_SACSTR, sacstr,
161                 DIVE_NITROX, sac,
162                 -1);
163
164         return FALSE;
165 }
166
167 void update_dive_list_units(struct DiveList *dive_list)
168 {
169         const char *unit;
170         GtkTreeModel *model = GTK_TREE_MODEL(dive_list->model);
171
172         switch (output_units.length) {
173         case METERS:
174                 unit = "m";
175                 break;
176         case FEET:
177                 unit = "ft";
178                 break;
179         }
180         gtk_tree_view_column_set_title(dive_list->depth, unit);
181
182         gtk_tree_model_foreach(model, set_one_dive, NULL);
183 }
184
185 static void fill_dive_list(struct DiveList *dive_list)
186 {
187         int i;
188         GtkTreeIter iter;
189         GtkListStore *store;
190
191         store = GTK_LIST_STORE(dive_list->model);
192
193         for (i = 0; i < dive_table.nr; i++) {
194                 struct dive *dive = dive_table.dives[i];
195
196                 gtk_list_store_append(store, &iter);
197                 gtk_list_store_set(store, &iter,
198                         DIVE_INDEX, i,
199                         DIVE_DATESTR, "date",
200                         DIVE_DATE, dive->when,
201                         DIVE_DEPTHSTR, "depth",
202                         DIVE_DEPTH, dive->maxdepth,
203                         DIVE_DURATIONSTR, "duration",
204                         DIVE_DURATION, dive->duration.seconds,
205                         DIVE_TEMPSTR, "temp",
206                         DIVE_TEMP, dive->watertemp.mkelvin,
207                         DIVE_NITROXSTR, "21.0",
208                         DIVE_NITROX, dive->cylinder[0].gasmix.o2,
209                         DIVE_SACSTR, "sac",
210                         DIVE_SAC, 0,
211                         -1);
212         }
213
214         update_dive_list_units(dive_list);
215 }
216
217 void dive_list_update_dives(struct DiveList dive_list)
218 {
219         gtk_list_store_clear(GTK_LIST_STORE(dive_list.model));
220         fill_dive_list(&dive_list);
221         repaint_dive();
222 }
223
224 struct DiveList dive_list_create(void)
225 {
226         struct DiveList    dive_list;
227         GtkTreeSelection  *selection;
228         GtkCellRenderer   *renderer;
229         GtkTreeViewColumn *col;
230
231         dive_list.model = gtk_list_store_new(DIVELIST_COLUMNS,
232                                 G_TYPE_INT,                     /* index */
233                                 G_TYPE_STRING, G_TYPE_INT,      /* Date */
234                                 G_TYPE_STRING, G_TYPE_INT,      /* Depth */
235                                 G_TYPE_STRING, G_TYPE_INT,      /* Duration */
236                                 G_TYPE_STRING, G_TYPE_INT,      /* Temperature */
237                                 G_TYPE_STRING, G_TYPE_INT,      /* Nitrox */
238                                 G_TYPE_STRING, G_TYPE_INT       /* SAC */
239                                 );
240         dive_list.tree_view = gtk_tree_view_new_with_model(GTK_TREE_MODEL(dive_list.model));
241         selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(dive_list.tree_view));
242
243         gtk_tree_selection_set_mode(GTK_TREE_SELECTION(selection), GTK_SELECTION_BROWSE);
244         gtk_widget_set_size_request(dive_list.tree_view, 200, 100);
245
246         renderer = gtk_cell_renderer_text_new();
247         dive_list.date = col = gtk_tree_view_column_new();
248         gtk_tree_view_column_set_title(col, "Date");
249         gtk_tree_view_column_set_sort_column_id(col, DIVE_DATE);
250         gtk_tree_view_column_set_resizable (col, TRUE);
251         gtk_tree_view_column_pack_start(col, renderer, TRUE);
252         gtk_tree_view_column_add_attribute(col, renderer, "text", DIVE_DATESTR);
253         gtk_tree_view_append_column(GTK_TREE_VIEW(dive_list.tree_view), col);
254
255         renderer = gtk_cell_renderer_text_new();
256         dive_list.depth = col = gtk_tree_view_column_new();
257         gtk_tree_view_column_set_title(col, "ft");
258         gtk_tree_view_column_set_sort_column_id(col, DIVE_DEPTH);
259         gtk_tree_view_column_pack_start(col, renderer, FALSE);
260         gtk_tree_view_column_add_attribute(col, renderer, "text", DIVE_DEPTHSTR);
261         gtk_tree_view_append_column(GTK_TREE_VIEW(dive_list.tree_view), col);
262         gtk_object_set(GTK_OBJECT(renderer), "alignment", PANGO_ALIGN_RIGHT, NULL);
263         gtk_cell_renderer_set_alignment(GTK_CELL_RENDERER(renderer), 1.0, 0.5);
264
265         renderer = gtk_cell_renderer_text_new();
266         dive_list.duration = col = gtk_tree_view_column_new();
267         gtk_tree_view_column_set_title(col, "min");
268         gtk_tree_view_column_set_sort_column_id(col, DIVE_DURATION);
269         gtk_tree_view_column_pack_start(col, renderer, FALSE);
270         gtk_tree_view_column_add_attribute(col, renderer, "text", DIVE_DURATIONSTR);
271         gtk_tree_view_append_column(GTK_TREE_VIEW(dive_list.tree_view), col);
272         gtk_object_set(GTK_OBJECT(renderer), "alignment", PANGO_ALIGN_RIGHT, NULL);
273         gtk_cell_renderer_set_alignment(GTK_CELL_RENDERER(renderer), 1.0, 0.5);
274
275         renderer = gtk_cell_renderer_text_new();
276         dive_list.temperature = col = gtk_tree_view_column_new();
277         gtk_tree_view_column_set_title(col, "deg");
278         gtk_tree_view_column_set_sort_column_id(col, DIVE_TEMP);
279         gtk_tree_view_column_pack_start(col, renderer, FALSE);
280         gtk_tree_view_column_add_attribute(col, renderer, "text", DIVE_TEMPSTR);
281         gtk_tree_view_append_column(GTK_TREE_VIEW(dive_list.tree_view), col);
282         gtk_object_set(GTK_OBJECT(renderer), "alignment", PANGO_ALIGN_RIGHT, NULL);
283         gtk_cell_renderer_set_alignment(GTK_CELL_RENDERER(renderer), 1.0, 0.5);
284
285         renderer = gtk_cell_renderer_text_new();
286         dive_list.nitrox = col = gtk_tree_view_column_new();
287         gtk_tree_view_column_set_title(col, "EAD");
288         gtk_tree_view_column_set_sort_column_id(col, DIVE_NITROX);
289         gtk_tree_view_column_pack_start(col, renderer, FALSE);
290         gtk_tree_view_column_add_attribute(col, renderer, "text", DIVE_NITROXSTR);
291         gtk_tree_view_append_column(GTK_TREE_VIEW(dive_list.tree_view), col);
292         gtk_object_set(GTK_OBJECT(renderer), "alignment", PANGO_ALIGN_RIGHT, NULL);
293         gtk_cell_renderer_set_alignment(GTK_CELL_RENDERER(renderer), 1.0, 0.5);
294
295         renderer = gtk_cell_renderer_text_new();
296         dive_list.sac = col = gtk_tree_view_column_new();
297         gtk_tree_view_column_set_title(col, "SAC");
298         gtk_tree_view_column_set_sort_column_id(col, DIVE_SAC);
299         gtk_tree_view_column_pack_start(col, renderer, FALSE);
300         gtk_tree_view_column_add_attribute(col, renderer, "text", DIVE_SACSTR);
301         gtk_tree_view_append_column(GTK_TREE_VIEW(dive_list.tree_view), col);
302         gtk_object_set(GTK_OBJECT(renderer), "alignment", PANGO_ALIGN_RIGHT, NULL);
303         gtk_cell_renderer_set_alignment(GTK_CELL_RENDERER(renderer), 1.0, 0.5);
304
305         fill_dive_list(&dive_list);
306
307         g_object_set(G_OBJECT(dive_list.tree_view), "headers-visible", TRUE,
308                                           "search-column", 0,
309                                           "rules-hint", TRUE,
310                                           NULL);
311
312         g_signal_connect(selection, "changed", G_CALLBACK(selection_cb), dive_list.model);
313
314         dive_list.container_widget = gtk_scrolled_window_new(NULL, NULL);
315         gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(dive_list.container_widget),
316                                GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
317         gtk_container_add(GTK_CONTAINER(dive_list.container_widget), dive_list.tree_view);
318
319         return dive_list;
320 }