summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGravatar Ďoďo <dodo.sk@gmail.com>2013-04-09 17:54:36 +0200
committerGravatar Dirk Hohndel <dirk@hohndel.org>2013-04-09 10:31:36 -0700
commited3f67bc33fbd9aac819687317d3066c22799f83 (patch)
tree0ca44c39b68f5e2681ebfd915e86105b8a4a0900
parent68545465ba971952e4c66606e44786d9337f97ad (diff)
downloadsubsurface-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.h13
-rw-r--r--divelist-gtk.c54
-rw-r--r--gtk-gui.c7
-rw-r--r--info.c75
-rw-r--r--parse-xml.c2
-rw-r--r--pref.h1
-rw-r--r--prefs.c7
-rw-r--r--save-xml.c2
-rw-r--r--statistics.c42
9 files changed, 198 insertions, 5 deletions
diff --git a/dive.h b/dive.h
index 11b003f68..24f2f37e8 100644
--- a/dive.h
+++ b/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;
};
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);
diff --git a/gtk-gui.c b/gtk-gui.c
index c7714e5fe..81497436a 100644
--- a/gtk-gui.c
+++ b/gtk-gui.c
@@ -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);
diff --git a/info.c b/info.c
index 455fbea1a..26a3f471a 100644
--- a/info.c
+++ b/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;
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))
diff --git a/pref.h b/pref.h
index 60fe1104c..3c6b43c70 100644
--- a/pref.h
+++ b/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;
diff --git a/prefs.c b/prefs.c
index 7d41c0cf6..d1073c88f 100644
--- a/prefs.c
+++ b/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;
}
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,"");