From 0cde0eff103ec8742656c4cb167a0e6245293697 Mon Sep 17 00:00:00 2001 From: Dirk Hohndel Date: Wed, 13 Feb 2013 15:03:25 -0800 Subject: Rewriting the error handling in planner.c Printf is not a way to issue warnings and errors. This is a very late addition but seems necessary for a viable release of the planner. This also adds one artificial limit and two warnings: a) no dives deeper than 400m b) warning of potentially very long calculation times for dives longer than 3h (180min) before the ascent and dives deeper than 150m It also creates quite a number of new strings that need to be translated (and marks a few existing ones for translation as well). Signed-off-by: Dirk Hohndel --- dive.h | 1 + planner.c | 75 +++++++++++++++++++++++++++++++++++++++++++++++++++++---------- 2 files changed, 64 insertions(+), 12 deletions(-) diff --git a/dive.h b/dive.h index 246521554..35becba07 100644 --- a/dive.h +++ b/dive.h @@ -599,6 +599,7 @@ extern void set_autogroup(gboolean value); extern int total_weight(struct dive *); #define DIVE_ERROR_PARSE 1 +#define DIVE_ERROR_PLAN 2 const char *weekday(int wday); const char *monthname(int mon); diff --git a/planner.c b/planner.c index 6ae83333c..017031a19 100644 --- a/planner.c +++ b/planner.c @@ -18,6 +18,7 @@ int decostoplevels[] = { 0, 3000, 6000, 9000, 12000, 15000, 18000, 21000, 24000, 90000}; double plangflow, plangfhigh; char *disclaimer; +GtkWidget *planner, *planner_error_bar, *error_label; #if DEBUG_PLAN void dump_plan(struct diveplan *diveplan) @@ -44,6 +45,43 @@ void dump_plan(struct diveplan *diveplan) } #endif +static void on_error_bar_response(GtkWidget *widget, gint response, gpointer data) +{ + if (response == GTK_RESPONSE_OK) + { + gtk_widget_destroy(widget); + planner_error_bar = NULL; + error_label = NULL; + } +} + +static void show_error(const char *fmt, ...) +{ + va_list args; + GError *error; + GtkWidget *box, *container; + gboolean bar_is_visible = TRUE; + + va_start(args, fmt); + error = g_error_new_valist(g_quark_from_string("subsurface"), DIVE_ERROR_PLAN, fmt, args); + va_end(args); + if (!planner_error_bar) { + planner_error_bar = gtk_info_bar_new_with_buttons(GTK_STOCK_OK, GTK_RESPONSE_OK, NULL); + g_signal_connect(planner_error_bar, "response", G_CALLBACK(on_error_bar_response), NULL); + gtk_info_bar_set_message_type(GTK_INFO_BAR(planner_error_bar), GTK_MESSAGE_ERROR); + bar_is_visible = FALSE; + } + container = gtk_info_bar_get_content_area(GTK_INFO_BAR(planner_error_bar)); + if (error_label) + gtk_container_remove(GTK_CONTAINER(container), error_label); + error_label = gtk_label_new(error->message); + gtk_container_add(GTK_CONTAINER(container), error_label); + box = gtk_dialog_get_content_area(GTK_DIALOG(planner)); + if (!bar_is_visible) + gtk_box_pack_start(GTK_BOX(box), planner_error_bar, FALSE, FALSE, 0); + gtk_widget_show_all(box); +} + void get_gas_from_events(struct divecomputer *dc, int time, int *o2, int *he) { struct event *event = dc->events; @@ -113,7 +151,7 @@ double tissue_at_end(struct dive *dive, char **cached_datap) t1 = sample->time.seconds; get_gas_from_events(&dive->dc, t0, &o2, &he); if ((gasidx = get_gasidx(dive, o2, he)) == -1) { - printf("can't find gas %d/%d\n", (o2 + 5) / 10, (he + 5) / 10); + show_error(_("Can't find gas %d/%d"), (o2 + 5) / 10, (he + 5) / 10); gasidx = 0; } if (i > 0) @@ -168,14 +206,14 @@ int add_gas(struct dive *dive, int o2, int he) return i; } if (i == MAX_CYLINDERS) { - printf("too many cylinders\n"); + show_error(_("Too many gas mixes")); return -1; } mix->o2.permille = o2; mix->he.permille = he; /* since air is stored as 0/0 we need to set a name or an air cylinder * would be seen as unset (by cylinder_nodata()) */ - cyl->type.description = strdup("Cylinder for planning"); + cyl->type.description = strdup(_("Cylinder for planning")); return i; } @@ -322,6 +360,8 @@ void add_duration_to_nth_dp(struct diveplan *diveplan, int idx, int duration, gb duration += pdp->time; } dp->time = duration; + if (duration > 180 * 60) + show_error(_("Warning, extremely long dives can cause long calculation time")); } /* this function is ONLY called from the dialog callback - so it @@ -865,6 +905,9 @@ static int validate_depth(const char *text, int *mm_p) depth *= 100; } *mm_p = depth; + /* we don't support extreme depths */ + if (depth > 400000) + return 0; return 1; } @@ -943,7 +986,7 @@ static GtkWidget *add_entry_to_box(GtkWidget *box, const char *label) return entry; } -#define MAX_WAYPOINTS 8 +#define MAX_WAYPOINTS 12 GtkWidget *entry_depth[MAX_WAYPOINTS], *entry_duration[MAX_WAYPOINTS], *entry_gas[MAX_WAYPOINTS], *entry_po2[MAX_WAYPOINTS]; int nr_waypoints = 0; static GtkListStore *gas_model = NULL; @@ -1008,7 +1051,7 @@ static void gas_changed_cb(GtkWidget *combo, gpointer data) if (!validate_gas(gastext, &o2, &he)) { /* this should never happen as only validated texts should be * in the dropdown */ - printf("invalid gas for row %d\n",idx); + show_error(_("Invalid gas for row %d"),idx); } add_gas_to_nth_dp(&diveplan, idx, o2, he); show_planned_dive(); @@ -1017,16 +1060,22 @@ static void gas_changed_cb(GtkWidget *combo, gpointer data) static gboolean depth_focus_out_cb(GtkWidget *entry, GdkEvent *event, gpointer data) { const char *depthtext; - int depth; + int depth = -1; int idx = data - NULL; depthtext = gtk_entry_get_text(GTK_ENTRY(entry)); + if (validate_depth(depthtext, &depth)) { + if (depth > 150000) + show_error(_("Warning - planning very deep dives can take excessive amounts of time")); add_depth_to_nth_dp(&diveplan, idx, depth); show_planned_dive(); } else { - /* we need to instead change the color of the input field or something */ - printf("invalid depth for row %d\n", idx); + /* it might be better to instead change the color of the input field or something */ + if (depth == -1) + show_error(_("Invalid depth - could not parse \"%s\""), depthtext); + else + show_error(_("Invalid depth - values deeper than 400m not supported")); } return FALSE; } @@ -1089,8 +1138,8 @@ static gboolean starttime_focus_out_cb(GtkWidget *entry, GdkEvent * event, gpoin diveplan.when = cur + starttime; show_planned_dive(); } else { - /* we need to instead change the color of the input field or something */ - printf("invalid starttime\n"); + /* it might be better to instead change the color of the input field or something */ + show_error(_("Invalid starttime")); } return FALSE; } @@ -1190,7 +1239,7 @@ static void add_waypoint_cb(GtkButton *button, gpointer _data) dialog = gtk_widget_get_parent(ovbox); gtk_widget_show_all(dialog); } else { - // some error + show_error(_("Too many waypoints")); } } @@ -1207,7 +1256,7 @@ static void add_entry_with_callback(GtkWidget *box, int length, char *label, cha /* set up the dialog where the user can input their dive plan */ void input_plan() { - GtkWidget *planner, *content, *vbox, *hbox, *outervbox, *add_row, *label; + GtkWidget *content, *vbox, *hbox, *outervbox, *add_row, *label; char *bottom_sac, *deco_sac, gflowstring[4], gfhighstring[4]; char *explanationtext = _("Add segments below.\nEach line describes part of the planned dive.\n" "An entry with depth, time and gas describes a segment that ends " @@ -1301,5 +1350,7 @@ void input_plan() } } gtk_widget_destroy(planner); + planner_error_bar = NULL; + error_label = NULL; set_gf(prefs.gflow, prefs.gfhigh); } -- cgit v1.2.3-70-g09d2 From fd703f3ca0cd36cc93ec81560b926f98b3da8093 Mon Sep 17 00:00:00 2001 From: Dirk Hohndel Date: Wed, 13 Feb 2013 22:23:09 -0800 Subject: Support deeper stops and longer dive notes in planner Since we now support dives all the way down to 400m we should also support deeper stops. And of course this can create insanely long dive plans, so make sure there is plenty of space for those. Signed-off-by: Dirk Hohndel --- planner.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/planner.c b/planner.c index 017031a19..43f5e83cb 100644 --- a/planner.c +++ b/planner.c @@ -15,7 +15,10 @@ int decostoplevels[] = { 0, 3000, 6000, 9000, 12000, 15000, 18000, 21000, 24000, 27000, 30000, 33000, 36000, 39000, 42000, 45000, 48000, 51000, 54000, 57000, 60000, 63000, 66000, 69000, 72000, 75000, 78000, 81000, 84000, 87000, - 90000}; + 90000, 100000, 110000, 120000, 130000, 140000, 150000, 160000, 170000, + 180000, 190000, 200000, 220000, 240000, 260000, 280000, 300000, + 320000, 340000, 360000, 380000 +}; double plangflow, plangfhigh; char *disclaimer; GtkWidget *planner, *planner_error_bar, *error_label; @@ -510,7 +513,7 @@ static int *sort_stops(int *dstops, int dnr, struct gaschanges *gstops, int gnr) static void add_plan_to_notes(struct diveplan *diveplan, struct dive *dive) { - char buffer[2000]; + char buffer[20000]; int consumption[MAX_CYLINDERS] = { 0, }; int len, gasidx, lastdepth = 0, lasttime = 0; struct divedatapoint *dp = diveplan->dp; -- cgit v1.2.3-70-g09d2 From d1ee250524dc211ce120414b87f515ee975aad40 Mon Sep 17 00:00:00 2001 From: Dirk Hohndel Date: Wed, 13 Feb 2013 23:14:55 -0800 Subject: Make planner.c warning consistent Just a tiny change to make them look more consistent. Signed-off-by: Dirk Hohndel --- planner.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/planner.c b/planner.c index 43f5e83cb..0e9725b55 100644 --- a/planner.c +++ b/planner.c @@ -364,7 +364,7 @@ void add_duration_to_nth_dp(struct diveplan *diveplan, int idx, int duration, gb } dp->time = duration; if (duration > 180 * 60) - show_error(_("Warning, extremely long dives can cause long calculation time")); + show_error(_("Warning - extremely long dives can cause long calculation time")); } /* this function is ONLY called from the dialog callback - so it -- cgit v1.2.3-70-g09d2