diff options
Diffstat (limited to 'core')
-rw-r--r-- | core/dive.c | 96 | ||||
-rw-r--r-- | core/dive.h | 15 | ||||
-rw-r--r-- | core/equipment.c | 61 | ||||
-rw-r--r-- | core/equipment.h | 5 | ||||
-rw-r--r-- | core/parse-xml.c | 25 | ||||
-rw-r--r-- | core/planner.c | 33 | ||||
-rw-r--r-- | core/profile.c | 13 | ||||
-rw-r--r-- | core/qthelper.cpp | 33 | ||||
-rw-r--r-- | core/qthelper.h | 2 | ||||
-rw-r--r-- | core/subsurface-qt/divelistnotifier.h | 6 |
10 files changed, 182 insertions, 107 deletions
diff --git a/core/dive.c b/core/dive.c index c97c229f6..df5d7951d 100644 --- a/core/dive.c +++ b/core/dive.c @@ -11,6 +11,7 @@ #include "device.h" #include "divelist.h" #include "divesite.h" +#include "errorhelper.h" #include "qthelper.h" #include "metadata.h" #include "membuffer.h" @@ -126,10 +127,10 @@ int event_is_gaschange(const struct event *ev) ev->type == SAMPLE_EVENT_GASCHANGE2; } -struct event *add_event(struct divecomputer *dc, unsigned int time, int type, int flags, int value, const char *name) +struct event *create_event(unsigned int time, int type, int flags, int value, const char *name) { int gas_index = -1; - struct event *ev, **p; + struct event *ev; unsigned int size, len = strlen(name); size = sizeof(*ev) + len + 1; @@ -164,18 +165,85 @@ struct event *add_event(struct divecomputer *dc, unsigned int time, int type, in break; } + return ev; +} + +/* warning: does not test idx for validity */ +struct event *create_gas_switch_event(struct dive *dive, struct divecomputer *dc, int seconds, int idx) +{ + /* The gas switch event format is insane for historical reasons */ + struct gasmix mix = get_cylinder(dive, idx)->gasmix; + int o2 = get_o2(mix); + int he = get_he(mix); + struct event *ev; + int value; + + o2 = (o2 + 5) / 10; + he = (he + 5) / 10; + value = o2 + (he << 16); + + ev = create_event(seconds, he ? SAMPLE_EVENT_GASCHANGE2 : SAMPLE_EVENT_GASCHANGE, 0, value, "gaschange"); + ev->gas.index = idx; + ev->gas.mix = mix; + return ev; +} + +struct event *clone_event_rename(const struct event *ev, const char *name) +{ + return create_event(ev->time.seconds, ev->type, ev->flags, ev->value, name); +} + +void add_event_to_dc(struct divecomputer *dc, struct event *ev) +{ + struct event **p; + p = &dc->events; /* insert in the sorted list of events */ - while (*p && (*p)->time.seconds <= time) + while (*p && (*p)->time.seconds <= ev->time.seconds) p = &(*p)->next; ev->next = *p; *p = ev; +} + +struct event *add_event(struct divecomputer *dc, unsigned int time, int type, int flags, int value, const char *name) +{ + struct event *ev = create_event(time, type, flags, value, name); + + if (!ev) + return NULL; + + add_event_to_dc(dc, ev); + remember_event(name); return ev; } -static int same_event(const struct event *a, const struct event *b) +void add_gas_switch_event(struct dive *dive, struct divecomputer *dc, int seconds, int idx) +{ + /* sanity check so we don't crash */ + if (idx < 0 || idx >= dive->cylinders.nr) { + report_error("Unknown cylinder index: %d", idx); + return; + } + struct event *ev = create_gas_switch_event(dive, dc, seconds, idx); + add_event_to_dc(dc, ev); +} + +/* Substitutes an event in a divecomputer for another. No reordering is performed! */ +void swap_event(struct divecomputer *dc, struct event *from, struct event *to) +{ + for (struct event **ep = &dc->events; *ep; ep = &(*ep)->next) { + if (*ep == from) { + to->next = from->next; + *ep = to; + from->next = NULL; // For good measure. + break; + } + } +} + +bool same_event(const struct event *a, const struct event *b) { if (a->time.seconds != b->time.seconds) return 0; @@ -188,19 +256,15 @@ static int same_event(const struct event *a, const struct event *b) return !strcmp(a->name, b->name); } -void remove_event(struct event *event) +/* Remove given event from dive computer. Does *not* free the event. */ +void remove_event_from_dc(struct divecomputer *dc, struct event *event) { - struct event **ep = ¤t_dc->events; - while (ep && !same_event(*ep, event)) - ep = &(*ep)->next; - if (ep) { - /* we can't link directly with event->next - * because 'event' can be a copy from another - * dive (for instance the displayed_dive - * that we use on the interface to show things). */ - struct event *temp = (*ep)->next; - free(*ep); - *ep = temp; + for (struct event **ep = &dc->events; *ep; ep = &(*ep)->next) { + if (*ep == event) { + *ep = event->next; + event->next = NULL; // For good measure. + break; + } } } diff --git a/core/dive.h b/core/dive.h index 13de360ed..0d2dbc2a6 100644 --- a/core/dive.h +++ b/core/dive.h @@ -358,10 +358,15 @@ extern void copy_used_cylinders(const struct dive *s, struct dive *d, bool used_ extern void copy_samples(const struct divecomputer *s, struct divecomputer *d); extern bool is_cylinder_used(const struct dive *dive, int idx); extern bool is_cylinder_prot(const struct dive *dive, int idx); -extern void fill_default_cylinder(const struct dive *dive, cylinder_t *cyl); extern void add_gas_switch_event(struct dive *dive, struct divecomputer *dc, int time, int idx); +extern struct event *create_event(unsigned int time, int type, int flags, int value, const char *name); +extern struct event *create_gas_switch_event(struct dive *dive, struct divecomputer *dc, int seconds, int idx); +extern struct event *clone_event_rename(const struct event *ev, const char *name); +extern void add_event_to_dc(struct divecomputer *dc, struct event *ev); +extern void swap_event(struct divecomputer *dc, struct event *from, struct event *to); +extern bool same_event(const struct event *a, const struct event *b); extern struct event *add_event(struct divecomputer *dc, unsigned int time, int type, int flags, int value, const char *name); -extern void remove_event(struct event *event); +extern void remove_event_from_dc(struct divecomputer *dc, struct event *event); extern void update_event_name(struct dive *d, struct event *event, const char *name); extern void add_extra_data(struct divecomputer *dc, const char *key, const char *value); extern void per_cylinder_mean_depth(const struct dive *dive, struct divecomputer *dc, int *mean, int *duration); @@ -372,15 +377,9 @@ extern int nr_weightsystems(const struct dive *dive); /* UI related protopypes */ -// extern void report_error(GError* error); - extern void remember_event(const char *eventname); extern void invalidate_dive_cache(struct dive *dc); -#if WE_DONT_USE_THIS /* this is a missing feature in Qt - selecting which events to display */ -extern int evn_foreach(void (*callback)(const char *, bool *, void *), void *data); -#endif /* WE_DONT_USE_THIS */ - extern void clear_events(void); extern void set_dc_nickname(struct dive *dive); diff --git a/core/equipment.c b/core/equipment.c index c9c0539c3..4be46ed1e 100644 --- a/core/equipment.c +++ b/core/equipment.c @@ -29,7 +29,7 @@ void free_weightsystem(weightsystem_t ws) ws.description = NULL; } -static void free_cylinder(cylinder_t c) +void free_cylinder(cylinder_t c) { free((void *)c.type.description); c.type.description = NULL; @@ -137,12 +137,18 @@ void add_cloned_weightsystem_at(struct weightsystem_table *t, weightsystem_t ws) add_to_weightsystem_table(t, t->nr, clone_weightsystem(ws)); } +cylinder_t clone_cylinder(cylinder_t cyl) +{ + cylinder_t res = cyl; + res.type.description = copy_string(res.type.description); + return res; +} + /* Add a clone of a cylinder to the end of a cylinder table. * Cloned in means that the description-string is copied. */ void add_cloned_cylinder(struct cylinder_table *t, cylinder_t cyl) { - cyl.type.description = copy_string(cyl.type.description); - add_to_cylinder_table(t, t->nr, cyl); + add_to_cylinder_table(t, t->nr, clone_cylinder(cyl)); } bool same_weightsystem(weightsystem_t w1, weightsystem_t w2) @@ -151,15 +157,6 @@ bool same_weightsystem(weightsystem_t w1, weightsystem_t w2) same_string(w1.description, w2.description); } -bool same_cylinder(cylinder_t cyl1, cylinder_t cyl2) -{ - return same_string(cyl1.type.description, cyl2.type.description) && - same_gasmix(cyl1.gasmix, cyl2.gasmix) && - cyl1.start.mbar == cyl2.start.mbar && - cyl1.end.mbar == cyl2.end.mbar && - cyl1.cylinder_use == cyl2.cylinder_use; -} - void get_gas_string(struct gasmix gasmix, char *text, int len) { if (gasmix_is_air(gasmix)) @@ -377,6 +374,46 @@ cylinder_t *get_or_create_cylinder(struct dive *d, int idx) return &d->cylinders.cylinders[idx]; } +/* if a default cylinder is set, use that */ +void fill_default_cylinder(const struct dive *dive, cylinder_t *cyl) +{ + const char *cyl_name = prefs.default_cylinder; + struct tank_info_t *ti = tank_info; + pressure_t pO2 = {.mbar = lrint(prefs.modpO2 * 1000.0)}; + + if (!cyl_name) + return; + while (ti->name != NULL && ti < tank_info + MAX_TANK_INFO) { + if (strcmp(ti->name, cyl_name) == 0) + break; + ti++; + } + if (ti->name == NULL) + /* didn't find it */ + return; + cyl->type.description = strdup(ti->name); + if (ti->ml) { + cyl->type.size.mliter = ti->ml; + cyl->type.workingpressure.mbar = ti->bar * 1000; + } else { + cyl->type.workingpressure.mbar = psi_to_mbar(ti->psi); + if (ti->psi) + cyl->type.size.mliter = lrint(cuft_to_l(ti->cuft) * 1000 / bar_to_atm(psi_to_bar(ti->psi))); + } + // MOD of air + cyl->depth = gas_mod(cyl->gasmix, pO2, dive, 1); +} + +cylinder_t create_new_cylinder(const struct dive *d) +{ + cylinder_t cyl = empty_cylinder; + fill_default_cylinder(d, &cyl); + cyl.start = cyl.type.workingpressure; + cyl.manually_added = true; + cyl.cylinder_use = OC_GAS; + return cyl; +} + #ifdef DEBUG_CYL void dump_cylinders(struct dive *dive, bool verbose) { diff --git a/core/equipment.h b/core/equipment.h index b62587447..081a13835 100644 --- a/core/equipment.h +++ b/core/equipment.h @@ -75,6 +75,8 @@ extern weightsystem_t clone_weightsystem(weightsystem_t ws); extern void free_weightsystem(weightsystem_t ws); extern void copy_cylinder_types(const struct dive *s, struct dive *d); extern void add_cloned_weightsystem(struct weightsystem_table *t, weightsystem_t ws); +extern cylinder_t clone_cylinder(cylinder_t cyl); +extern void free_cylinder(cylinder_t cyl); extern cylinder_t *add_empty_cylinder(struct cylinder_table *t); extern void add_cloned_cylinder(struct cylinder_table *t, cylinder_t cyl); extern cylinder_t *get_cylinder(const struct dive *d, int idx); @@ -82,13 +84,14 @@ extern cylinder_t *get_or_create_cylinder(struct dive *d, int idx); extern void add_cylinder_description(const cylinder_type_t *); extern void add_weightsystem_description(const weightsystem_t *); extern bool same_weightsystem(weightsystem_t w1, weightsystem_t w2); -extern bool same_cylinder(cylinder_t cyl1, cylinder_t cyl2); extern void remove_cylinder(struct dive *dive, int idx); extern void remove_weightsystem(struct dive *dive, int idx); extern void set_weightsystem(struct dive *dive, int idx, weightsystem_t ws); extern void reset_cylinders(struct dive *dive, bool track_gas); extern int gas_volume(const cylinder_t *cyl, pressure_t p); /* Volume in mliter of a cylinder at pressure 'p' */ extern int find_best_gasmix_match(struct gasmix mix, const struct cylinder_table *cylinders); +extern void fill_default_cylinder(const struct dive *dive, cylinder_t *cyl); /* dive is needed to fill out MOD, which depends on salinity. */ +extern cylinder_t create_new_cylinder(const struct dive *dive); /* dive is needed to fill out MOD, which depends on salinity. */ #ifdef DEBUG_CYL extern void dump_cylinders(struct dive *dive, bool verbose); #endif diff --git a/core/parse-xml.c b/core/parse-xml.c index 490e56275..50639d1d1 100644 --- a/core/parse-xml.c +++ b/core/parse-xml.c @@ -698,31 +698,6 @@ static void try_to_match_autogroup(const char *name, char *buf) nonmatch("autogroup", name, buf); } -void add_gas_switch_event(struct dive *dive, struct divecomputer *dc, int seconds, int idx) -{ - /* sanity check so we don't crash */ - if (idx < 0 || idx >= dive->cylinders.nr) { - report_error("Unknown cylinder index: %d", idx); - return; - } - /* The gas switch event format is insane for historical reasons */ - struct gasmix mix = get_cylinder(dive, idx)->gasmix; - int o2 = get_o2(mix); - int he = get_he(mix); - struct event *ev; - int value; - - o2 = (o2 + 5) / 10; - he = (he + 5) / 10; - value = o2 + (he << 16); - - ev = add_event(dc, seconds, he ? SAMPLE_EVENT_GASCHANGE2 : SAMPLE_EVENT_GASCHANGE, 0, value, "gaschange"); - if (ev) { - ev->gas.index = idx; - ev->gas.mix = mix; - } -} - static void get_cylinderindex(char *buffer, uint8_t *i, struct parser_state *state) { *i = atoi(buffer); diff --git a/core/planner.c b/core/planner.c index 0e26a9a57..a5f0d36bc 100644 --- a/core/planner.c +++ b/core/planner.c @@ -175,37 +175,6 @@ static int tissue_at_end(struct deco_state *ds, struct dive *dive, struct deco_s return surface_interval; } - -/* if a default cylinder is set, use that */ -void fill_default_cylinder(const struct dive *dive, cylinder_t *cyl) -{ - const char *cyl_name = prefs.default_cylinder; - struct tank_info_t *ti = tank_info; - pressure_t pO2 = {.mbar = 1600}; - - if (!cyl_name) - return; - while (ti->name != NULL && ti < tank_info + MAX_TANK_INFO) { - if (strcmp(ti->name, cyl_name) == 0) - break; - ti++; - } - if (ti->name == NULL) - /* didn't find it */ - return; - cyl->type.description = strdup(ti->name); - if (ti->ml) { - cyl->type.size.mliter = ti->ml; - cyl->type.workingpressure.mbar = ti->bar * 1000; - } else { - cyl->type.workingpressure.mbar = psi_to_mbar(ti->psi); - if (ti->psi) - cyl->type.size.mliter = lrint(cuft_to_l(ti->cuft) * 1000 / bar_to_atm(psi_to_bar(ti->psi))); - } - // MOD of air - cyl->depth = gas_mod(cyl->gasmix, pO2, dive, 1); -} - /* calculate the new end pressure of the cylinder, based on its current end pressure and the * latest segment. */ static void update_cylinder_pressure(struct dive *d, int old_depth, int new_depth, int duration, int sac, cylinder_t *cyl, bool in_deco, enum divemode_t divemode) @@ -315,7 +284,7 @@ static void create_dive_from_plan(struct diveplan *diveplan, struct dive *dive, } if (dp->divemode != type) { type = dp->divemode; - add_event(dc, lasttime, 8, 0, type, "modechange"); + add_event(dc, lasttime, SAMPLE_EVENT_BOOKMARK, 0, type, "modechange"); } /* Create sample */ diff --git a/core/profile.c b/core/profile.c index 88b48d1cd..26488cc30 100644 --- a/core/profile.c +++ b/core/profile.c @@ -120,19 +120,6 @@ struct ev_select *ev_namelist; int evn_allocated; int evn_used; -#if WE_DONT_USE_THIS /* we need to implement event filters in Qt */ -int evn_foreach (void (*callback)(const char *, bool *, void *), void *data) -{ - int i; - - for (i = 0; i < evn_used; i++) { - /* here we display an event name on screen - so translate */ - callback(translate("gettextFromC", ev_namelist[i].ev_name), &ev_namelist[i].plot_ev, data); - } - return i; -} -#endif /* WE_DONT_USE_THIS */ - void clear_events(void) { for (int i = 0; i < evn_used; i++) diff --git a/core/qthelper.cpp b/core/qthelper.cpp index eb755bf20..91b3a3ee7 100644 --- a/core/qthelper.cpp +++ b/core/qthelper.cpp @@ -1662,3 +1662,36 @@ extern "C" char *get_changes_made() else return nullptr; } + +// Generate a cylinder-renumber map for use when the n-th cylinder +// of a dive with count cylinders is removed. It fills an int vector +// with 0..n, -1, n..count-1. Each entry in the vector represents +// the new id of the cylinder, whereby <0 means that this particular +// cylinder does not get any new id. This should probably be moved +// to the C-core, but using std::vector is simply more convenient. +// The function assumes that n < count! +std::vector<int> get_cylinder_map_for_remove(int count, int n) +{ + // 1) Fill mapping[0]..mapping[n-1] with 0..n-1 + // 2) Set mapping[n] to -1 + // 3) Fill mapping[n+1]..mapping[count-1] with n..count-2 + std::vector<int> mapping(count); + std::iota(mapping.begin(), mapping.begin() + n, 0); + mapping[n] = -1; + std::iota(mapping.begin() + n + 1, mapping.end(), n); + return mapping; +} + +// Generate a cylinder-renumber map for use when a cylinder is added +// before the n-th cylinder. It fills an int vector with +// with 0..n-1, n+1..count. Each entry in the vector represents +// the new id of the cylinder. This probably should be moved +// to the C-core, but using std::vector is simply more convenient. +// This function assumes that that n <= count! +std::vector<int> get_cylinder_map_for_add(int count, int n) +{ + std::vector<int> mapping(count); + std::iota(mapping.begin(), mapping.begin() + n, 0); + std::iota(mapping.begin() + n, mapping.end(), n + 1); + return mapping; +} diff --git a/core/qthelper.h b/core/qthelper.h index bb8876383..848763138 100644 --- a/core/qthelper.h +++ b/core/qthelper.h @@ -83,6 +83,8 @@ QLocale getLocale(); QVector<QPair<QString, int>> selectedDivesGasUsed(); QString getUserAgent(); QString printGPSCoords(const location_t *loc); +std::vector<int> get_cylinder_map_for_remove(int count, int n); +std::vector<int> get_cylinder_map_for_add(int count, int n); extern QString (*changesCallback)(); void uiNotification(const QString &msg); diff --git a/core/subsurface-qt/divelistnotifier.h b/core/subsurface-qt/divelistnotifier.h index aafe29c0c..63355fbcc 100644 --- a/core/subsurface-qt/divelistnotifier.h +++ b/core/subsurface-qt/divelistnotifier.h @@ -87,6 +87,9 @@ signals: void divesTimeChanged(timestamp_t delta, const QVector<dive *> &dives); void cylindersReset(const QVector<dive *> &dives); + void cylinderAdded(dive *d, int pos); + void cylinderRemoved(dive *d, int pos); + void cylinderEdited(dive *d, int pos); void weightsystemsReset(const QVector<dive *> &dives); void weightAdded(dive *d, int pos); void weightRemoved(dive *d, int pos); @@ -110,6 +113,9 @@ signals: void numShownChanged(); void filterReset(); + // Event-related signals. Currently, we're very blunt: only one signal for any changes to the events. + void eventsChanged(dive *d); + // This signal is emited every time a command is executed. // This is used to hide an old multi-dives-edited warning message. // This is necessary, so that the user can't click on the "undo" button and undo |