Add exposure protection tracking

For simplicity and shortness, throughout subsurface exposure protection is
simply referred to as "suit".

Add the fields to the data structures, add the column to the dive_list
and the preferences dialog (once again with it being turned invisible by
default). Support loading and saving of the suit information.

Display the suit information in the Dive Info pane (this may be a bit
controversial as people could argue this should be in the Equipment pane)
and allow editing of the suit info, with our usual support for completion
and drop down lists to pick from.

Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
This commit is contained in:
Dirk Hohndel 2012-08-14 16:07:25 -07:00
parent 3c542b5a41
commit e8ec3df371
8 changed files with 52 additions and 5 deletions

View file

@ -15,6 +15,7 @@ typedef struct {
gboolean cylinder; gboolean cylinder;
gboolean temperature; gboolean temperature;
gboolean totalweight; gboolean totalweight;
gboolean suit;
gboolean nitrox; gboolean nitrox;
gboolean sac; gboolean sac;
gboolean otu; gboolean otu;

2
dive.c
View file

@ -486,6 +486,7 @@ struct dive *fixup_dive(struct dive *dive)
add_people(dive->buddy); add_people(dive->buddy);
add_people(dive->divemaster); add_people(dive->divemaster);
add_location(dive->location); add_location(dive->location);
add_suit(dive->suit);
for (i = 0; i < MAX_CYLINDERS; i++) { for (i = 0; i < MAX_CYLINDERS; i++) {
cylinder_t *cyl = dive->cylinder + i; cylinder_t *cyl = dive->cylinder + i;
add_cylinder_description(&cyl->type); add_cylinder_description(&cyl->type);
@ -703,6 +704,7 @@ struct dive *try_to_merge(struct dive *a, struct dive *b)
MERGE_TXT(res, a, b, buddy); MERGE_TXT(res, a, b, buddy);
MERGE_TXT(res, a, b, divemaster); MERGE_TXT(res, a, b, divemaster);
MERGE_MAX(res, a, b, rating); MERGE_MAX(res, a, b, rating);
MERGE_TXT(res, a, b, suit);
MERGE_MAX(res, a, b, number); MERGE_MAX(res, a, b, number);
MERGE_MAX(res, a, b, maxdepth.mm); MERGE_MAX(res, a, b, maxdepth.mm);
res->meandepth.mm = 0; res->meandepth.mm = 0;

2
dive.h
View file

@ -243,6 +243,7 @@ struct dive {
temperature_t airtemp, watertemp; temperature_t airtemp, watertemp;
cylinder_t cylinder[MAX_CYLINDERS]; cylinder_t cylinder[MAX_CYLINDERS];
weightsystem_t weightsystem[MAX_WEIGHTSYSTEMS]; weightsystem_t weightsystem[MAX_WEIGHTSYSTEMS];
char *suit;
int sac, otu; int sac, otu;
struct event *events; struct event *events;
int samples, alloc_samples; int samples, alloc_samples;
@ -342,6 +343,7 @@ extern void add_cylinder_description(cylinder_type_t *);
extern void add_weightsystem_description(weightsystem_t *); extern void add_weightsystem_description(weightsystem_t *);
extern void add_people(const char *string); extern void add_people(const char *string);
extern void add_location(const char *string); extern void add_location(const char *string);
extern void add_suit(const char *string);
extern void remember_event(const char *eventname); extern void remember_event(const char *eventname);
extern void evn_foreach(void (*callback)(const char *, int *, void *), void *data); extern void evn_foreach(void (*callback)(const char *, int *, void *), void *data);

View file

@ -26,7 +26,7 @@ struct DiveList {
GtkWidget *container_widget; GtkWidget *container_widget;
GtkListStore *model; GtkListStore *model;
GtkTreeViewColumn *nr, *date, *stars, *depth, *duration, *location; GtkTreeViewColumn *nr, *date, *stars, *depth, *duration, *location;
GtkTreeViewColumn *temperature, *cylinder, *totalweight, *nitrox, *sac, *otu; GtkTreeViewColumn *temperature, *cylinder, *totalweight, *suit, *nitrox, *sac, *otu;
int changed; int changed;
}; };
@ -45,6 +45,7 @@ enum {
DIVE_DURATION, /* int: in seconds */ DIVE_DURATION, /* int: in seconds */
DIVE_TEMPERATURE, /* int: in mkelvin */ DIVE_TEMPERATURE, /* int: in mkelvin */
DIVE_TOTALWEIGHT, /* int: in grams */ DIVE_TOTALWEIGHT, /* int: in grams */
DIVE_SUIT, /* "wet, 3mm" */
DIVE_CYLINDER, DIVE_CYLINDER,
DIVE_NITROX, /* int: dummy */ DIVE_NITROX, /* int: dummy */
DIVE_SAC, /* int: in ml/min */ DIVE_SAC, /* int: in ml/min */
@ -534,6 +535,11 @@ static void get_cylinder(struct dive *dive, char **str)
get_string(str, dive->cylinder[0].type.description); 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 * Set up anything that could have changed due to editing
* of dive information * of dive information
@ -542,10 +548,11 @@ static void fill_one_dive(struct dive *dive,
GtkTreeModel *model, GtkTreeModel *model,
GtkTreeIter *iter) GtkTreeIter *iter)
{ {
char *location, *cylinder; char *location, *cylinder, *suit;
get_cylinder(dive, &cylinder); get_cylinder(dive, &cylinder);
get_location(dive, &location); get_location(dive, &location);
get_suit(dive, &suit);
gtk_list_store_set(GTK_LIST_STORE(model), iter, gtk_list_store_set(GTK_LIST_STORE(model), iter,
DIVE_NR, dive->number, DIVE_NR, dive->number,
@ -555,7 +562,11 @@ static void fill_one_dive(struct dive *dive,
DIVE_SAC, dive->sac, DIVE_SAC, dive->sac,
DIVE_OTU, dive->otu, DIVE_OTU, dive->otu,
DIVE_TOTALWEIGHT, total_weight(dive), DIVE_TOTALWEIGHT, total_weight(dive),
DIVE_SUIT, suit,
-1); -1);
/* this will create a merge conflict with the memory leak patches */
free(suit);
} }
static gboolean set_one_dive(GtkTreeModel *model, static gboolean set_one_dive(GtkTreeModel *model,
@ -614,6 +625,7 @@ 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.cylinder, visible_cols.cylinder);
gtk_tree_view_column_set_visible(dive_list.temperature, visible_cols.temperature); 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.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.nitrox, visible_cols.nitrox);
gtk_tree_view_column_set_visible(dive_list.sac, visible_cols.sac); gtk_tree_view_column_set_visible(dive_list.sac, visible_cols.sac);
gtk_tree_view_column_set_visible(dive_list.otu, visible_cols.otu); gtk_tree_view_column_set_visible(dive_list.otu, visible_cols.otu);
@ -643,6 +655,7 @@ static void fill_dive_list(void)
DIVE_LOCATION, "location", DIVE_LOCATION, "location",
DIVE_TEMPERATURE, dive->watertemp.mkelvin, DIVE_TEMPERATURE, dive->watertemp.mkelvin,
DIVE_TOTALWEIGHT, 0, DIVE_TOTALWEIGHT, 0,
DIVE_SUIT, dive->suit,
DIVE_SAC, 0, DIVE_SAC, 0,
-1); -1);
} }
@ -676,6 +689,7 @@ static struct divelist_column {
[DIVE_DURATION] = { "min", duration_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_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_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_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_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_SAC] = { "SAC", sac_data_func, NULL, 0, &visible_cols.sac },
@ -783,6 +797,7 @@ GtkWidget *dive_list_create(void)
G_TYPE_INT, /* Duration */ G_TYPE_INT, /* Duration */
G_TYPE_INT, /* Temperature */ G_TYPE_INT, /* Temperature */
G_TYPE_INT, /* Total weight */ G_TYPE_INT, /* Total weight */
G_TYPE_STRING, /* Suit */
G_TYPE_STRING, /* Cylinder */ G_TYPE_STRING, /* Cylinder */
G_TYPE_INT, /* Nitrox */ G_TYPE_INT, /* Nitrox */
G_TYPE_INT, /* SAC */ G_TYPE_INT, /* SAC */
@ -804,6 +819,7 @@ GtkWidget *dive_list_create(void)
dive_list.duration = divelist_column(&dive_list, dl_column + DIVE_DURATION); dive_list.duration = divelist_column(&dive_list, dl_column + DIVE_DURATION);
dive_list.temperature = divelist_column(&dive_list, dl_column + DIVE_TEMPERATURE); dive_list.temperature = divelist_column(&dive_list, dl_column + DIVE_TEMPERATURE);
dive_list.totalweight = divelist_column(&dive_list, dl_column + DIVE_TOTALWEIGHT); 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.cylinder = divelist_column(&dive_list, dl_column + DIVE_CYLINDER);
dive_list.nitrox = divelist_column(&dive_list, dl_column + DIVE_NITROX); dive_list.nitrox = divelist_column(&dive_list, dl_column + DIVE_NITROX);
dive_list.sac = divelist_column(&dive_list, dl_column + DIVE_SAC); dive_list.sac = divelist_column(&dive_list, dl_column + DIVE_SAC);

View file

@ -349,6 +349,7 @@ OPTIONCALLBACK(sac_toggle, visible_cols.sac)
OPTIONCALLBACK(nitrox_toggle, visible_cols.nitrox) OPTIONCALLBACK(nitrox_toggle, visible_cols.nitrox)
OPTIONCALLBACK(temperature_toggle, visible_cols.temperature) OPTIONCALLBACK(temperature_toggle, visible_cols.temperature)
OPTIONCALLBACK(totalweight_toggle, visible_cols.totalweight) OPTIONCALLBACK(totalweight_toggle, visible_cols.totalweight)
OPTIONCALLBACK(suit_toggle, visible_cols.suit)
OPTIONCALLBACK(cylinder_toggle, visible_cols.cylinder) OPTIONCALLBACK(cylinder_toggle, visible_cols.cylinder)
static void event_toggle(GtkWidget *w, gpointer _data) static void event_toggle(GtkWidget *w, gpointer _data)
@ -440,6 +441,11 @@ static void preferences_dialog(GtkWidget *w, gpointer data)
gtk_box_pack_start(GTK_BOX(box), button, FALSE, FALSE, 6); gtk_box_pack_start(GTK_BOX(box), button, FALSE, FALSE, 6);
g_signal_connect(G_OBJECT(button), "toggled", G_CALLBACK(totalweight_toggle), NULL); g_signal_connect(G_OBJECT(button), "toggled", G_CALLBACK(totalweight_toggle), NULL);
button = gtk_check_button_new_with_label("Show Suit");
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(button), visible_cols.suit);
gtk_box_pack_start(GTK_BOX(box), button, FALSE, FALSE, 6);
g_signal_connect(G_OBJECT(button), "toggled", G_CALLBACK(suit_toggle), NULL);
font = gtk_font_button_new_with_font(divelist_font); font = gtk_font_button_new_with_font(divelist_font);
gtk_box_pack_start(GTK_BOX(vbox), font, FALSE, FALSE, 5); gtk_box_pack_start(GTK_BOX(vbox), font, FALSE, FALSE, 5);
@ -464,6 +470,7 @@ static void preferences_dialog(GtkWidget *w, gpointer data)
subsurface_set_conf("lbs", PREF_BOOL, BOOL_TO_PTR(output_units.weight == LBS)); subsurface_set_conf("lbs", PREF_BOOL, BOOL_TO_PTR(output_units.weight == LBS));
subsurface_set_conf("TEMPERATURE", PREF_BOOL, BOOL_TO_PTR(visible_cols.temperature)); subsurface_set_conf("TEMPERATURE", PREF_BOOL, BOOL_TO_PTR(visible_cols.temperature));
subsurface_set_conf("TOTALWEIGHT", PREF_BOOL, BOOL_TO_PTR(visible_cols.totalweight)); subsurface_set_conf("TOTALWEIGHT", PREF_BOOL, BOOL_TO_PTR(visible_cols.totalweight));
subsurface_set_conf("SUIT", PREF_BOOL, BOOL_TO_PTR(visible_cols.suit));
subsurface_set_conf("CYLINDER", PREF_BOOL, BOOL_TO_PTR(visible_cols.cylinder)); subsurface_set_conf("CYLINDER", PREF_BOOL, BOOL_TO_PTR(visible_cols.cylinder));
subsurface_set_conf("NITROX", PREF_BOOL, BOOL_TO_PTR(visible_cols.nitrox)); subsurface_set_conf("NITROX", PREF_BOOL, BOOL_TO_PTR(visible_cols.nitrox));
subsurface_set_conf("SAC", PREF_BOOL, BOOL_TO_PTR(visible_cols.sac)); subsurface_set_conf("SAC", PREF_BOOL, BOOL_TO_PTR(visible_cols.sac));
@ -734,6 +741,7 @@ void init_ui(int *argcp, char ***argvp)
visible_cols.cylinder = PTR_TO_BOOL(subsurface_get_conf("CYLINDER", PREF_BOOL)); visible_cols.cylinder = PTR_TO_BOOL(subsurface_get_conf("CYLINDER", PREF_BOOL));
visible_cols.temperature = PTR_TO_BOOL(subsurface_get_conf("TEMPERATURE", PREF_BOOL)); visible_cols.temperature = PTR_TO_BOOL(subsurface_get_conf("TEMPERATURE", PREF_BOOL));
visible_cols.totalweight = PTR_TO_BOOL(subsurface_get_conf("TOTALWEIGHT", PREF_BOOL)); visible_cols.totalweight = PTR_TO_BOOL(subsurface_get_conf("TOTALWEIGHT", PREF_BOOL));
visible_cols.suit = PTR_TO_BOOL(subsurface_get_conf("SUIT", PREF_BOOL));
visible_cols.nitrox = PTR_TO_BOOL(subsurface_get_conf("NITROX", PREF_BOOL)); visible_cols.nitrox = PTR_TO_BOOL(subsurface_get_conf("NITROX", PREF_BOOL));
visible_cols.otu = PTR_TO_BOOL(subsurface_get_conf("OTU", PREF_BOOL)); visible_cols.otu = PTR_TO_BOOL(subsurface_get_conf("OTU", PREF_BOOL));
visible_cols.sac = PTR_TO_BOOL(subsurface_get_conf("SAC", PREF_BOOL)); visible_cols.sac = PTR_TO_BOOL(subsurface_get_conf("SAC", PREF_BOOL));

21
info.c
View file

@ -19,9 +19,9 @@
#include "display-gtk.h" #include "display-gtk.h"
#include "divelist.h" #include "divelist.h"
static GtkEntry *location, *buddy, *divemaster, *rating; static GtkEntry *location, *buddy, *divemaster, *rating, *suit;
static GtkTextView *notes; static GtkTextView *notes;
static GtkListStore *location_list, *people_list, *star_list; static GtkListStore *location_list, *people_list, *star_list, *suit_list;
static char *get_text(GtkTextView *view) static char *get_text(GtkTextView *view)
{ {
@ -96,6 +96,7 @@ void show_dive_info(struct dive *dive)
SET_TEXT_VALUE(divemaster); SET_TEXT_VALUE(divemaster);
SET_TEXT_VALUE(buddy); SET_TEXT_VALUE(buddy);
SET_TEXT_VALUE(location); SET_TEXT_VALUE(location);
SET_TEXT_VALUE(suit);
gtk_entry_set_text(rating, star_strings[dive->rating]); gtk_entry_set_text(rating, star_strings[dive->rating]);
gtk_text_buffer_set_text(gtk_text_view_get_buffer(notes), gtk_text_buffer_set_text(gtk_text_view_get_buffer(notes),
dive && dive->notes ? dive->notes : "", -1); dive && dive->notes ? dive->notes : "", -1);
@ -296,6 +297,11 @@ void add_location(const char *string)
add_string_list_entry(string, location_list); add_string_list_entry(string, location_list);
} }
void add_suit(const char *string)
{
add_string_list_entry(string, suit_list);
}
static int get_rating(const char *string) static int get_rating(const char *string)
{ {
int rating_val = 0; int rating_val = 0;
@ -308,7 +314,7 @@ static int get_rating(const char *string)
} }
struct dive_info { struct dive_info {
GtkComboBoxEntry *location, *divemaster, *buddy, *rating; GtkComboBoxEntry *location, *divemaster, *buddy, *rating, *suit;
GtkTextView *notes; GtkTextView *notes;
}; };
@ -336,6 +342,12 @@ static void save_dive_info_changes(struct dive *dive, struct dive_info *info)
changed = 1; changed = 1;
} }
new_text = get_combo_box_entry_text(info->suit, &dive->suit);
if (new_text) {
add_suit(new_text);
changed = 1;
}
rating_string = strdup(star_strings[dive->rating]); rating_string = strdup(star_strings[dive->rating]);
new_text = get_combo_box_entry_text(info->rating, &rating_string); new_text = get_combo_box_entry_text(info->rating, &rating_string);
if (new_text) { if (new_text) {
@ -378,6 +390,7 @@ static void dive_info_widget(GtkWidget *box, struct dive *dive, struct dive_info
gtk_box_pack_start(GTK_BOX(box), hbox, FALSE, TRUE, 0); gtk_box_pack_start(GTK_BOX(box), hbox, FALSE, TRUE, 0);
info->rating = text_entry(hbox, "Rating", star_list, star_strings[dive->rating]); info->rating = text_entry(hbox, "Rating", star_list, star_strings[dive->rating]);
info->suit = text_entry(hbox, "Suit", suit_list, dive->suit);
info->notes = text_view(box, "Notes", READ_WRITE); info->notes = text_view(box, "Notes", READ_WRITE);
if (dive->notes && *dive->notes) if (dive->notes && *dive->notes)
@ -562,6 +575,7 @@ GtkWidget *extended_dive_info_widget(void)
add_string_list_entry(THREE_STARS, star_list); add_string_list_entry(THREE_STARS, star_list);
add_string_list_entry(FOUR_STARS, star_list); add_string_list_entry(FOUR_STARS, star_list);
add_string_list_entry(FIVE_STARS, star_list); add_string_list_entry(FIVE_STARS, star_list);
suit_list = gtk_list_store_new(1, G_TYPE_STRING);
gtk_container_set_border_width(GTK_CONTAINER(vbox), 6); gtk_container_set_border_width(GTK_CONTAINER(vbox), 6);
location = text_value(vbox, "Location"); location = text_value(vbox, "Location");
@ -576,6 +590,7 @@ GtkWidget *extended_dive_info_widget(void)
gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, TRUE, 0); gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, TRUE, 0);
rating = text_value(hbox, "Rating"); rating = text_value(hbox, "Rating");
suit = text_value(hbox, "Suit");
notes = text_view(vbox, "Notes", READ_ONLY); notes = text_view(vbox, "Notes", READ_ONLY);
return vbox; return vbox;

View file

@ -1100,6 +1100,8 @@ static void try_to_fill_dive(struct dive **divep, const char *name, char *buf)
return; return;
if (MATCH(".location", utf8_string, &dive->location)) if (MATCH(".location", utf8_string, &dive->location))
return; return;
if (MATCH(".suit", utf8_string, &dive->suit))
return;
if (MATCH(".notes", utf8_string, &dive->notes)) if (MATCH(".notes", utf8_string, &dive->notes))
return; return;
if (MATCH(".divemaster", utf8_string, &dive->divemaster)) if (MATCH(".divemaster", utf8_string, &dive->divemaster))

View file

@ -183,6 +183,7 @@ static void save_overview(FILE *f, struct dive *dive)
show_utf8(f, dive->divemaster, " <divemaster>","</divemaster>\n"); show_utf8(f, dive->divemaster, " <divemaster>","</divemaster>\n");
show_utf8(f, dive->buddy, " <buddy>","</buddy>\n"); show_utf8(f, dive->buddy, " <buddy>","</buddy>\n");
show_utf8(f, dive->notes, " <notes>","</notes>\n"); show_utf8(f, dive->notes, " <notes>","</notes>\n");
show_utf8(f, dive->suit, " <suit>","</suit>\n");
} }
static void save_cylinder_info(FILE *f, struct dive *dive) static void save_cylinder_info(FILE *f, struct dive *dive)