mirror of
https://github.com/subsurface/subsurface.git
synced 2025-02-19 22:16:15 +00:00
UI restructure: add helper function to copy and clear a dive
This way we can safely copy around dives (specifically, copy the dive to be displayed / edited into the displayed_dive). Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
This commit is contained in:
parent
b298306eb1
commit
cd65c8512d
3 changed files with 124 additions and 23 deletions
125
dive.c
125
dive.c
|
@ -255,16 +255,106 @@ struct dive *alloc_dive(void)
|
||||||
return dive;
|
return dive;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void free_dc(struct divecomputer *dc);
|
||||||
|
static void free_pic(struct picture *picture);
|
||||||
|
|
||||||
|
#define STRDUP(_ptr) ((_ptr) ? strdup(_ptr) : NULL)
|
||||||
|
|
||||||
|
/* this is very different from the copy_divecomputer later in this file;
|
||||||
|
* this function actually makes full copies of the content */
|
||||||
|
static void copy_dc(struct divecomputer *sdc, struct divecomputer *ddc)
|
||||||
|
{
|
||||||
|
*ddc = *sdc;
|
||||||
|
ddc->model = STRDUP(sdc->model);
|
||||||
|
copy_samples(sdc, ddc);
|
||||||
|
copy_events(sdc, ddc);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* copy an element in a list of pictures */
|
||||||
|
static void copy_pl(struct picture *sp, struct picture *dp)
|
||||||
|
{
|
||||||
|
*dp = *sp;
|
||||||
|
dp->filename = STRDUP(sp->filename);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* copy an element in a list of tags */
|
||||||
|
static void copy_tl(struct tag_entry *st, struct tag_entry *dt)
|
||||||
|
{
|
||||||
|
dt->tag = malloc(sizeof(struct divetag));
|
||||||
|
dt->tag->name = STRDUP(st->tag->name);
|
||||||
|
dt->tag->source = STRDUP(st->tag->source);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Clear everything but the first element;
|
||||||
|
* this works for taglist, picturelist, even dive computers */
|
||||||
|
#define STRUCTURED_LIST_FREE(_type, _start, _free) {\
|
||||||
|
_type *_ptr = _start; \
|
||||||
|
while(_ptr) { \
|
||||||
|
_type *_next = _ptr->next; \
|
||||||
|
_free(_ptr); \
|
||||||
|
_ptr = _next; \
|
||||||
|
}}
|
||||||
|
|
||||||
|
#define STRUCTURED_LIST_COPY(_type, _first, _dest, _cpy) {\
|
||||||
|
_type *_sptr = _first; \
|
||||||
|
_type **_dptr = &_dest; \
|
||||||
|
while(_sptr) { \
|
||||||
|
*_dptr = malloc(sizeof(_type)); \
|
||||||
|
_cpy(_sptr, *_dptr); \
|
||||||
|
_sptr = _sptr->next; \
|
||||||
|
_dptr = &(*_dptr)->next; \
|
||||||
|
} \
|
||||||
|
*_dptr = 0; \
|
||||||
|
}
|
||||||
|
|
||||||
|
/* copy_dive makes duplicates of many components of a dive;
|
||||||
|
* in order not to leak memory, we need to free those .
|
||||||
|
* copy_dive doesn't play with the divetrip and forward/backward pointers
|
||||||
|
* so we can ignore those */
|
||||||
|
void clear_dive(struct dive *d)
|
||||||
|
{
|
||||||
|
if (!d)
|
||||||
|
return;
|
||||||
|
/* free the strings */
|
||||||
|
free(d->buddy);
|
||||||
|
free(d->divemaster);
|
||||||
|
free(d->location);
|
||||||
|
free(d->notes);
|
||||||
|
free(d->suit);
|
||||||
|
/* free tags, additional dive computers, and pictures */
|
||||||
|
taglist_free(d->tag_list);
|
||||||
|
STRUCTURED_LIST_FREE(struct divecomputer, d->dc.next, free_dc);
|
||||||
|
STRUCTURED_LIST_FREE(struct picture, d->picture_list, free_pic);
|
||||||
|
memset(d, 0, sizeof(struct dive));
|
||||||
|
}
|
||||||
|
|
||||||
|
void copy_dive(struct dive *s, struct dive *d)
|
||||||
|
{
|
||||||
|
clear_dive(d);
|
||||||
|
/* simply copy things over, but then make actual copies of the
|
||||||
|
* relevant components that are referenced through pointers,
|
||||||
|
* so all the strings and the structured lists */
|
||||||
|
*d = *s;
|
||||||
|
d->buddy = STRDUP(s->buddy);
|
||||||
|
d->divemaster = STRDUP(s->divemaster);
|
||||||
|
d->location = STRDUP(s->location);
|
||||||
|
d->notes = STRDUP(s->notes);
|
||||||
|
d->suit = STRDUP(s->suit);
|
||||||
|
STRUCTURED_LIST_COPY(struct divecomputer, s->dc.next, d->dc.next, copy_dc);
|
||||||
|
STRUCTURED_LIST_COPY(struct picture, s->picture_list, d->picture_list, copy_pl);
|
||||||
|
STRUCTURED_LIST_COPY(struct tag_entry, s->tag_list, d->tag_list, copy_tl);
|
||||||
|
}
|
||||||
|
|
||||||
/* only copies events from the first dive computer */
|
/* only copies events from the first dive computer */
|
||||||
void copy_events(struct dive *s, struct dive *d)
|
void copy_events(struct divecomputer *s, struct divecomputer *d)
|
||||||
{
|
{
|
||||||
struct event *ev;
|
struct event *ev;
|
||||||
if (!s || !d)
|
if (!s || !d)
|
||||||
return;
|
return;
|
||||||
ev = s->dc.events;
|
ev = s->events;
|
||||||
d->dc.events = NULL;
|
d->events = NULL;
|
||||||
while (ev != NULL) {
|
while (ev != NULL) {
|
||||||
add_event(&d->dc, ev->time.seconds, ev->type, ev->flags, ev->value, ev->name);
|
add_event(d, ev->time.seconds, ev->type, ev->flags, ev->value, ev->name);
|
||||||
ev = ev->next;
|
ev = ev->next;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -305,17 +395,17 @@ void copy_cylinders(struct dive *s, struct dive *d, bool used_only)
|
||||||
memset(&d->cylinder[i], 0, sizeof(cylinder_t));
|
memset(&d->cylinder[i], 0, sizeof(cylinder_t));
|
||||||
}
|
}
|
||||||
|
|
||||||
void copy_samples(struct dive *s, struct dive *d)
|
void copy_samples(struct divecomputer *s, struct divecomputer *d)
|
||||||
{
|
{
|
||||||
/* instead of carefully copying them one by one and calling add_sample
|
/* instead of carefully copying them one by one and calling add_sample
|
||||||
* over and over again, let's just copy the whole blob */
|
* over and over again, let's just copy the whole blob */
|
||||||
if (!s || !d)
|
if (!s || !d)
|
||||||
return;
|
return;
|
||||||
int nr = s->dc.samples;
|
int nr = s->samples;
|
||||||
d->dc.samples = nr;
|
d->samples = nr;
|
||||||
d->dc.sample = malloc(nr * sizeof(struct sample));
|
d->sample = malloc(nr * sizeof(struct sample));
|
||||||
if (d->dc.sample)
|
if (d->sample)
|
||||||
memcpy(d->dc.sample, s->dc.sample, nr * sizeof(struct sample));
|
memcpy(d->sample, s->sample, nr * sizeof(struct sample));
|
||||||
}
|
}
|
||||||
|
|
||||||
struct sample *prepare_sample(struct divecomputer *dc)
|
struct sample *prepare_sample(struct divecomputer *dc)
|
||||||
|
@ -1771,6 +1861,14 @@ static void free_dc(struct divecomputer *dc)
|
||||||
free(dc);
|
free(dc);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void free_pic(struct picture *picture)
|
||||||
|
{
|
||||||
|
if (picture) {
|
||||||
|
free(picture->filename);
|
||||||
|
free(picture);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static int same_event(struct event *a, struct event *b)
|
static int same_event(struct event *a, struct event *b)
|
||||||
{
|
{
|
||||||
if (a->time.seconds != b->time.seconds)
|
if (a->time.seconds != b->time.seconds)
|
||||||
|
@ -2075,14 +2173,9 @@ struct divetag *taglist_add_tag(struct tag_entry **tag_list, const char *tag)
|
||||||
return ret_tag;
|
return ret_tag;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Clear everything but the first element */
|
|
||||||
void taglist_free(struct tag_entry *entry)
|
void taglist_free(struct tag_entry *entry)
|
||||||
{
|
{
|
||||||
while (entry) {
|
STRUCTURED_LIST_FREE(struct tag_entry, entry, free)
|
||||||
struct tag_entry *next = entry->next;
|
|
||||||
free(entry);
|
|
||||||
entry = next;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Merge src1 and src2, write to *dst */
|
/* Merge src1 and src2, write to *dst */
|
||||||
|
|
6
dive.h
6
dive.h
|
@ -598,6 +598,8 @@ extern void utc_mkdate(timestamp_t, struct tm *tm);
|
||||||
|
|
||||||
extern struct dive *alloc_dive(void);
|
extern struct dive *alloc_dive(void);
|
||||||
extern void record_dive(struct dive *dive);
|
extern void record_dive(struct dive *dive);
|
||||||
|
extern void clear_dive(struct dive *dive);
|
||||||
|
extern void copy_dive(struct dive *s, struct dive *d);
|
||||||
|
|
||||||
extern struct sample *prepare_sample(struct divecomputer *dc);
|
extern struct sample *prepare_sample(struct divecomputer *dc);
|
||||||
extern void finish_sample(struct divecomputer *dc);
|
extern void finish_sample(struct divecomputer *dc);
|
||||||
|
@ -612,9 +614,9 @@ extern unsigned int dc_watertemp(struct divecomputer *dc);
|
||||||
extern struct dive *merge_dives(struct dive *a, struct dive *b, int offset, bool prefer_downloaded);
|
extern struct dive *merge_dives(struct dive *a, struct dive *b, int offset, bool prefer_downloaded);
|
||||||
extern struct dive *try_to_merge(struct dive *a, struct dive *b, bool prefer_downloaded);
|
extern struct dive *try_to_merge(struct dive *a, struct dive *b, bool prefer_downloaded);
|
||||||
extern void renumber_dives(int start_nr, bool selected_only);
|
extern void renumber_dives(int start_nr, bool selected_only);
|
||||||
extern void copy_events(struct dive *s, struct dive *d);
|
extern void copy_events(struct divecomputer *s, struct divecomputer *d);
|
||||||
extern void copy_cylinders(struct dive *s, struct dive *d, bool used_only);
|
extern void copy_cylinders(struct dive *s, struct dive *d, bool used_only);
|
||||||
extern void copy_samples(struct dive *s, struct dive *d);
|
extern void copy_samples(struct divecomputer *s, struct divecomputer *d);
|
||||||
extern bool cylinder_is_used(struct dive *d, cylinder_t *cyl);
|
extern bool cylinder_is_used(struct dive *d, cylinder_t *cyl);
|
||||||
extern void fill_default_cylinder(cylinder_t *cyl);
|
extern void fill_default_cylinder(cylinder_t *cyl);
|
||||||
extern void add_gas_switch_event(struct dive *dive, struct divecomputer *dc, int time, int idx);
|
extern void add_gas_switch_event(struct dive *dive, struct divecomputer *dc, int time, int idx);
|
||||||
|
|
|
@ -103,8 +103,13 @@ void DivePlannerPointsModel::loadFromDive(dive *d)
|
||||||
// We need to make a copy, because as soon as the model is modified, it will
|
// We need to make a copy, because as soon as the model is modified, it will
|
||||||
// remove all samples from the dive.
|
// remove all samples from the dive.
|
||||||
memcpy(&backupDive, d, sizeof(struct dive));
|
memcpy(&backupDive, d, sizeof(struct dive));
|
||||||
copy_samples(d, &backupDive);
|
|
||||||
copy_events(d, &backupDive);
|
// this code is just adjusted for the new API, it continues to just copy the first
|
||||||
|
// DC (which here is almost certainly sufficient)
|
||||||
|
// but it should most likely use copy_dive() instead
|
||||||
|
// but this whole section needs to be rewritten, anyway
|
||||||
|
copy_samples(&d->dc, &backupDive.dc);
|
||||||
|
copy_events(&d->dc, &backupDive.dc);
|
||||||
copy_cylinders(d, stagingDive, false); // this way the correct cylinder data is shown
|
copy_cylinders(d, stagingDive, false); // this way the correct cylinder data is shown
|
||||||
CylindersModel::instance()->setDive(stagingDive);
|
CylindersModel::instance()->setDive(stagingDive);
|
||||||
int lasttime = 0;
|
int lasttime = 0;
|
||||||
|
@ -1046,9 +1051,10 @@ void DivePlannerPointsModel::createTemporaryPlan()
|
||||||
plan(&diveplan, &cache, &tempDive, stagingDive, isPlanner(), false);
|
plan(&diveplan, &cache, &tempDive, stagingDive, isPlanner(), false);
|
||||||
MainWindow::instance()->setPlanNotes(tempDive->notes);
|
MainWindow::instance()->setPlanNotes(tempDive->notes);
|
||||||
if (mode == ADD || mode == PLAN) {
|
if (mode == ADD || mode == PLAN) {
|
||||||
// copy the samples and events, but don't overwrite the cylinders
|
// copy the samples and events of the first dive computer, but don't overwrite the cylinders
|
||||||
copy_samples(tempDive, current_dive);
|
// FIXME this needs to be rewritten
|
||||||
copy_events(tempDive, current_dive);
|
copy_samples(&tempDive->dc, ¤t_dive->dc);
|
||||||
|
copy_events(&tempDive->dc, ¤t_dive->dc);
|
||||||
copy_cylinders(tempDive, current_dive, false);
|
copy_cylinders(tempDive, current_dive, false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue