diff options
author | Ďoďo <dodo.sk@gmail.com> | 2013-04-09 17:54:36 +0200 |
---|---|---|
committer | Dirk Hohndel <dirk@hohndel.org> | 2013-04-09 10:31:36 -0700 |
commit | ed3f67bc33fbd9aac819687317d3066c22799f83 (patch) | |
tree | 0ca44c39b68f5e2681ebfd915e86105b8a4a0900 | |
parent | 68545465ba971952e4c66606e44786d9337f97ad (diff) | |
download | subsurface-ed3f67bc33fbd9aac819687317d3066c22799f83.tar.gz |
Add dive tags and support invalid dives
This started out as a way to keep dives in the dive list but being able to
mark them as 'invalid' so they wouldn't be visible (with an option to
disable that feature).
Now it supports an (at this point, fixed) set of tags that can be assigned
to a dive with 'invalid' being just one of them (but one that is special
as it gets some additional support for hiding such dive and marking dives
as (in)valid from the divelist).
[Dirk Hohndel: merged with the latest code and minor changes for coding
style and consistency. Ensure divelist is marked as
modified when changing 'invalid' tag]
Signed-Off-By: Jozef Ivanecký (dodo.sk@gmail.com)
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
-rw-r--r-- | dive.h | 13 | ||||
-rw-r--r-- | divelist-gtk.c | 54 | ||||
-rw-r--r-- | gtk-gui.c | 7 | ||||
-rw-r--r-- | info.c | 75 | ||||
-rw-r--r-- | parse-xml.c | 2 | ||||
-rw-r--r-- | pref.h | 1 | ||||
-rw-r--r-- | prefs.c | 7 | ||||
-rw-r--r-- | save-xml.c | 2 | ||||
-rw-r--r-- | statistics.c | 42 |
9 files changed, 198 insertions, 5 deletions
@@ -28,6 +28,18 @@ #define SEAWATER_SALINITY 10300 #define FRESHWATER_SALINITY 10000 +/* Dive types definition */ +#define DTYPE_INVALID 1 +#define DTYPE_BOAT 2 +#define DTYPE_SHORE 4 +#define DTYPE_DRIFT 8 +#define DTYPE_DEEP 16 +#define DTYPE_CAVERN 32 +#define DTYPE_ICE 64 +#define DTYPE_WRECK 128 +#define DTYPE_CAVE 256 +#define DTYPE_ALTITUDE 512 +#define DTYPE_POOL 1024 /* * Some silly typedefs to make our units very explicit. @@ -342,6 +354,7 @@ struct dive { pressure_t surface_pressure; duration_t duration; int salinity; // kg per 10000 l + int dive_tags; struct divecomputer dc; }; diff --git a/divelist-gtk.c b/divelist-gtk.c index dc441881c..c8ad1a6ca 100644 --- a/divelist-gtk.c +++ b/divelist-gtk.c @@ -715,7 +715,10 @@ static void fill_dive_list(void) i = dive_table.nr; while (--i >= 0) { struct dive *dive = get_dive(i); - dive_trip_t *trip = dive->divetrip; + dive_trip_t *trip; + if ((dive->dive_tags & DTYPE_INVALID) && !prefs.display_invalid_dives) + continue; + trip = dive->divetrip; if (!trip) { parent_ptr = NULL; @@ -1061,6 +1064,42 @@ static void save_as_cb(GtkWidget *menuitem, struct dive *dive) } } +static void invalid_dives_cb(GtkWidget *menuitem, GtkTreePath *path) +{ + int i; + int changed = 0; + struct dive *dive; + + if (!amount_selected) + return; + /* walk the dive list in chronological order */ + for_each_dive(i, dive) { + dive = get_dive(i); + if (!dive) + continue; + if (!dive->selected) + continue; + /* now swap the invalid tag if just 1 dive was selected + * otherwise set all to invalid */ + if(amount_selected == 1) { + if (dive->dive_tags & DTYPE_INVALID) + dive->dive_tags &= ~DTYPE_INVALID; + else + dive->dive_tags |= DTYPE_INVALID; + changed = 1; + } else { + if (! dive->dive_tags & DTYPE_INVALID) { + dive->dive_tags |= DTYPE_INVALID; + changed = 1; + } + } + } + if (changed) { + dive_list_update_dives(); + mark_divelist_changed(TRUE); + } +} + static void expand_all_cb(GtkWidget *menuitem, GtkTreeView *tree_view) { gtk_tree_view_expand_all(tree_view); @@ -1626,7 +1665,7 @@ static void popup_divelist_menu(GtkTreeView *tree_view, GtkTreeModel *model, int gtk_menu_shell_append(GTK_MENU_SHELL(menu), menuitem); } else { dive = get_dive(idx); - /* if we right click on selected dive(s), edit or delete those */ + /* if we right click on selected dive(s), edit, delete or tag them as invalid */ if (dive->selected) { if (amount_selected == 1) { deletelabel = _(deletesinglelabel); @@ -1642,6 +1681,17 @@ static void popup_divelist_menu(GtkTreeView *tree_view, GtkTreeModel *model, int g_signal_connect(menuitem, "activate", G_CALLBACK(save_as_cb), dive); gtk_menu_shell_append(GTK_MENU_SHELL(menu), menuitem); + if (amount_selected == 1) { + if (dive->dive_tags & DTYPE_INVALID) + menuitem = gtk_menu_item_new_with_label(_("Mark valid")); + else + menuitem = gtk_menu_item_new_with_label(_("Mark invalid")); + } else { + menuitem = gtk_menu_item_new_with_label(_("Mark invalid")); + } + g_signal_connect(menuitem, "activate", G_CALLBACK(invalid_dives_cb), path); + gtk_menu_shell_append(GTK_MENU_SHELL(menu), menuitem); + menuitem = gtk_menu_item_new_with_label(deletelabel); g_signal_connect(menuitem, "activate", G_CALLBACK(delete_selected_dives_cb), path); gtk_menu_shell_append(GTK_MENU_SHELL(menu), menuitem); @@ -626,6 +626,7 @@ OPTIONCALLBACK(maxcns_toggle, prefs.visible_cols.maxcns) OPTIONCALLBACK(sac_toggle, prefs.visible_cols.sac) OPTIONCALLBACK(nitrox_toggle, prefs.visible_cols.nitrox) OPTIONCALLBACK(temperature_toggle, prefs.visible_cols.temperature) +OPTIONCALLBACK(display_invalid_dives_toggle, prefs.display_invalid_dives) OPTIONCALLBACK(totalweight_toggle, prefs.visible_cols.totalweight) OPTIONCALLBACK(suit_toggle, prefs.visible_cols.suit) OPTIONCALLBACK(cylinder_toggle, prefs.visible_cols.cylinder) @@ -852,6 +853,11 @@ static void preferences_dialog(GtkWidget *w, gpointer data) box = gtk_hbox_new(FALSE, 6); gtk_container_add(GTK_CONTAINER(frame), box); + button = gtk_check_button_new_with_label(_("Display invalid dives")); + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(button), prefs.display_invalid_dives); + gtk_box_pack_end(GTK_BOX(box), button, FALSE, FALSE, 6); + g_signal_connect(G_OBJECT(button), "toggled", G_CALLBACK(display_invalid_dives_toggle), NULL); + frame = gtk_frame_new(_("Default XML Data File")); gtk_box_pack_start(GTK_BOX(box), frame, FALSE, FALSE, 5); hbox = gtk_hbox_new(FALSE, 6); @@ -1073,6 +1079,7 @@ static void preferences_dialog(GtkWidget *w, gpointer data) free((void *)provider); #endif save_preferences(); + dive_list_update_dives(); } else if (result == GTK_RESPONSE_CANCEL) { prefs = oldprefs; set_gf(prefs.gflow, prefs.gfhigh); @@ -606,6 +606,10 @@ static void save_dive_info_changes(struct dive *dive, struct dive *master, struc if (old_text) g_free(old_text); } + if (dive->dive_tags != master->dive_tags) { + changed = 1; + dive->dive_tags = master->dive_tags; + } if (changed) { mark_divelist_changed(TRUE); update_dive(dive); @@ -793,9 +797,18 @@ static gboolean base_data_cb(GtkWidget *w, GdkEvent *event, gpointer _data) return FALSE; } +void divetag_toggle_cb(GtkWidget *widget, gpointer data) +{ + int DT = GPOINTER_TO_INT (data); + if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget))) + edit_dive.dive_tags |= DT; + else + edit_dive.dive_tags &= ~DT; +} + static void dive_info_widget(GtkWidget *obox, struct dive *dive, struct dive_info *info, gboolean multi) { - GtkWidget *hbox, *frame, *equipment, *ibox, *box; + GtkWidget *hbox, *frame, *equipment, *ibox, *box, *button, *sbox, *framebox; #if HAVE_OSM_GPS_MAP GtkWidget *image; #endif @@ -870,6 +883,66 @@ static void dive_info_widget(GtkWidget *obox, struct dive *dive, struct dive_inf airtemp[0] = '\0'; info->airtemp = single_text_entry(hbox, buffer, airtemp); + frame = gtk_frame_new(_("Dive Type")); + gtk_box_pack_start(GTK_BOX(box), frame, FALSE, FALSE, 0); + + framebox = gtk_vbox_new(FALSE, 3); + gtk_container_add(GTK_CONTAINER(frame), framebox); + + sbox = gtk_hbox_new(FALSE, 6); + gtk_box_pack_start(GTK_BOX(framebox), sbox, TRUE, FALSE, 3); +/* 1st line */ + button = gtk_check_button_new_with_label(_("Boat Dive")); + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(button), dive->dive_tags & DTYPE_BOAT); + gtk_box_pack_start(GTK_BOX(sbox), button, FALSE, FALSE, 6); + g_signal_connect(G_OBJECT(button), "toggled", G_CALLBACK(divetag_toggle_cb), GINT_TO_POINTER (DTYPE_BOAT)); + + button = gtk_check_button_new_with_label(_("Shore Dive")); + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(button), dive->dive_tags & DTYPE_SHORE); + gtk_box_pack_start(GTK_BOX(sbox), button, FALSE, FALSE, 6); + g_signal_connect(G_OBJECT(button), "toggled", G_CALLBACK(divetag_toggle_cb), GINT_TO_POINTER (DTYPE_SHORE)); + + button = gtk_check_button_new_with_label(_("Pool Dive")); + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(button), dive->dive_tags & DTYPE_POOL); + gtk_box_pack_start(GTK_BOX(sbox), button, FALSE, FALSE, 6); + g_signal_connect(G_OBJECT(button), "toggled", G_CALLBACK(divetag_toggle_cb), GINT_TO_POINTER (DTYPE_POOL)); + + sbox = gtk_hbox_new(FALSE, 6); + gtk_box_pack_start(GTK_BOX(framebox), sbox, TRUE, FALSE, 3); +/* 2nd line */ + button = gtk_check_button_new_with_label(_("Drift Dive")); + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(button), dive->dive_tags & DTYPE_DRIFT); + gtk_box_pack_start(GTK_BOX(sbox), button, FALSE, FALSE, 6); + g_signal_connect(G_OBJECT(button), "toggled", G_CALLBACK(divetag_toggle_cb), GINT_TO_POINTER (DTYPE_DRIFT)); + + button = gtk_check_button_new_with_label(_("Deep Dive")); + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(button), dive->dive_tags & DTYPE_DEEP); + gtk_box_pack_start(GTK_BOX(sbox), button, FALSE, FALSE, 6); + g_signal_connect(G_OBJECT(button), "toggled", G_CALLBACK(divetag_toggle_cb), GINT_TO_POINTER (DTYPE_DEEP)); + + button = gtk_check_button_new_with_label(_("Cavern Dive")); + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(button), dive->dive_tags & DTYPE_CAVERN); + gtk_box_pack_start(GTK_BOX(sbox), button, FALSE, FALSE, 6); + g_signal_connect(G_OBJECT(button), "toggled", G_CALLBACK(divetag_toggle_cb), GINT_TO_POINTER (DTYPE_CAVERN)); + + sbox = gtk_hbox_new(FALSE, 6); + gtk_box_pack_start(GTK_BOX(framebox), sbox, TRUE, FALSE, 3); +/* 3rd line */ + button = gtk_check_button_new_with_label(_("Ice Dive")); + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(button), dive->dive_tags & DTYPE_ICE); + gtk_box_pack_start(GTK_BOX(sbox), button, FALSE, FALSE, 6); + g_signal_connect(G_OBJECT(button), "toggled", G_CALLBACK(divetag_toggle_cb), GINT_TO_POINTER (DTYPE_ICE)); + + button = gtk_check_button_new_with_label(_("Wreck Dive")); + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(button), dive->dive_tags & DTYPE_WRECK); + gtk_box_pack_start(GTK_BOX(sbox), button, FALSE, FALSE, 6); + g_signal_connect(G_OBJECT(button), "toggled", G_CALLBACK(divetag_toggle_cb), GINT_TO_POINTER (DTYPE_WRECK)); + + button = gtk_check_button_new_with_label(_("Cave Dive")); + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(button), dive->dive_tags & DTYPE_CAVE); + gtk_box_pack_start(GTK_BOX(sbox), button, FALSE, FALSE, 6); + g_signal_connect(G_OBJECT(button), "toggled", G_CALLBACK(divetag_toggle_cb), GINT_TO_POINTER (DTYPE_CAVE)); + /* only show notes if editing a single dive */ if (multi) { info->notes = NULL; diff --git a/parse-xml.c b/parse-xml.c index 4701a173a..431cd376d 100644 --- a/parse-xml.c +++ b/parse-xml.c @@ -1033,6 +1033,8 @@ static void try_to_fill_dive(struct dive *dive, const char *name, char *buf) if (MATCH(".number", get_index, &dive->number)) return; + if (MATCH(".tags", get_index, &dive->dive_tags)) + return; if (MATCH(".tripflag", get_tripflag, &dive->tripflag)) return; if (MATCH(".date", divedate, &dive->when)) @@ -36,6 +36,7 @@ struct preferences { int map_provider; const char *divelist_font; const char *default_filename; + short display_invalid_dives; }; extern struct preferences prefs, default_prefs; @@ -113,6 +113,7 @@ void save_preferences(void) SAVE_STRING("default_filename", default_filename); SAVE_INT("map_provider", map_provider); + SAVE_INT("display_invalid_dives", display_invalid_dives); /* Flush the changes out to the system */ subsurface_flush_conf(); @@ -204,6 +205,10 @@ void load_preferences(void) prefs.default_filename = conf_value; int_value = subsurface_get_conf_int("map_provider"); - if(int_value >= 0) + if (int_value >= 0) prefs.map_provider = int_value; + + int_value = subsurface_get_conf_int("display_invalid_dives"); + if (int_value >= 0) + prefs.display_invalid_dives = int_value; } diff --git a/save-xml.c b/save-xml.c index 7ae71dd57..d7ac878c5 100644 --- a/save-xml.c +++ b/save-xml.c @@ -451,6 +451,8 @@ void save_dive(FILE *f, struct dive *dive) fprintf(f, " rating='%d'", dive->rating); if (dive->visibility) fprintf(f, " visibility='%d'", dive->visibility); + if (dive->dive_tags) + fprintf(f, " tags='%d'", dive->dive_tags); show_date(f, dive->when); fprintf(f, " duration='%u:%02u min'>\n", FRACTION(dive->dc.duration.seconds, 60)); diff --git a/statistics.c b/statistics.c index 502c06cb4..552694563 100644 --- a/statistics.c +++ b/statistics.c @@ -28,7 +28,8 @@ typedef struct { *sac, *otu, *o2he, - *gas_used; + *gas_used, + *dive_type; } single_stat_widget_t; static single_stat_widget_t single_w; @@ -631,6 +632,38 @@ static void show_single_dive_stats(struct dive *dive) } else { set_label(single_w.gas_used, ""); } + /* Dive type */ + if (dive->dive_tags) { + buf[0]=0; + if(dive->dive_tags & DTYPE_INVALID) + strcat(buf, " Invalid,"); + if(dive->dive_tags & DTYPE_BOAT) + strcat(buf, " Boat,"); + if(dive->dive_tags & DTYPE_SHORE) + strcat(buf, " Shore,"); + if(dive->dive_tags & DTYPE_DRIFT) + strcat(buf, " Drift,"); + if(dive->dive_tags & DTYPE_DEEP) + strcat(buf, " Deep,"); + if(dive->dive_tags & DTYPE_CAVERN) + strcat(buf, " Cavern,"); + if(dive->dive_tags & DTYPE_ICE) + strcat(buf, " Ice,"); + if(dive->dive_tags & DTYPE_WRECK) + strcat(buf, " Wreck,"); + if(dive->dive_tags & DTYPE_CAVE) + strcat(buf, " Cave,"); + if(dive->dive_tags & DTYPE_ALTITUDE) + strcat(buf, " Altitude,"); + if(dive->dive_tags & DTYPE_POOL) + strcat(buf, " Pool,"); + if(strlen(buf) > 1) + buf[strlen(buf)-1] = 0; + } + else { + buf[0] = 0; + } + set_label(single_w.dive_type, buf); } /* this gets called when at least two but not all dives are selected */ @@ -865,6 +898,12 @@ GtkWidget *single_stats_widget(void) single_w.o2he = new_info_label_in_frame(hbox, "O" UTF8_SUBSCRIPT_2 " / He"); single_w.gas_used = new_info_label_in_frame(hbox, C_("Amount","Gas Used")); + /* fifth row */ + hbox = gtk_hbox_new(FALSE, 3); + gtk_box_pack_start(GTK_BOX(framebox), hbox, TRUE, FALSE, 3); + + single_w.dive_type = new_info_label_in_frame(hbox, _("Dive Type")); + return vbox; } @@ -884,6 +923,7 @@ void clear_stats_widgets(void) set_label(single_w.otu, ""); set_label(single_w.o2he, ""); set_label(single_w.gas_used, ""); + set_label(single_w.dive_type, ""); set_label(stats_w.total_time,""); set_label(stats_w.avg_time,""); set_label(stats_w.shortest_time,""); |