mirror of
https://github.com/subsurface/subsurface.git
synced 2024-11-28 05:00:20 +00:00
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>
This commit is contained in:
parent
68545465ba
commit
ed3f67bc33
9 changed files with 198 additions and 5 deletions
13
dive.h
13
dive.h
|
@ -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;
|
||||
};
|
||||
|
|
|
@ -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);
|
||||
|
|
75
info.c
75
info.c
|
@ -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;
|
||||
|
|
|
@ -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))
|
||||
|
|
1
pref.h
1
pref.h
|
@ -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;
|
||||
|
|
7
prefs.c
7
prefs.c
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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));
|
||||
|
|
42
statistics.c
42
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,"");
|
||||
|
|
Loading…
Reference in a new issue