mirror of
https://github.com/subsurface/subsurface.git
synced 2024-11-28 05:00:20 +00:00
Core: keep trips in table(s)
Currently, all trips are kept in a linked list. Replace the list by a table in analogy to dive_table. Use this to keep the trip_table sorted as suggested by dump_trip_list(). When inserting a trip into the table do that after adding the dives, to avoid warnings coming out of dump_trip_list(). Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
This commit is contained in:
parent
54fcda4c32
commit
517fb7a462
7 changed files with 89 additions and 78 deletions
10
core/dive.h
10
core/dive.h
|
@ -286,11 +286,13 @@ typedef struct dive_trip
|
|||
/* Used by the io-routines to mark trips that have already been written. */
|
||||
bool saved;
|
||||
bool autogen;
|
||||
struct dive_trip *next;
|
||||
} dive_trip_t;
|
||||
|
||||
/* List of dive trips (sorted by date) */
|
||||
extern dive_trip_t *dive_trip_list;
|
||||
struct trip_table {
|
||||
int nr, allocated;
|
||||
struct dive_trip **trips;
|
||||
};
|
||||
|
||||
struct picture;
|
||||
struct dive {
|
||||
int number;
|
||||
|
@ -420,6 +422,7 @@ extern const struct units *get_units(void);
|
|||
extern int run_survey, verbose, quit, force_root;
|
||||
|
||||
extern struct dive_table dive_table;
|
||||
extern struct trip_table trip_table;
|
||||
extern struct dive displayed_dive;
|
||||
extern unsigned int dc_number;
|
||||
extern struct dive *current_dive;
|
||||
|
@ -543,6 +546,7 @@ extern bool dive_less_than(const struct dive *a, const struct dive *b);
|
|||
extern bool trip_less_than(const struct dive_trip *a, const struct dive_trip *b);
|
||||
extern bool dive_or_trip_less_than(struct dive_or_trip a, struct dive_or_trip b);
|
||||
extern void sort_dive_table(struct dive_table *table);
|
||||
extern void sort_trip_table(struct trip_table *table);
|
||||
extern struct dive *fixup_dive(struct dive *dive);
|
||||
extern void fixup_dc_duration(struct divecomputer *dc);
|
||||
extern int dive_getUniqID();
|
||||
|
|
134
core/divelist.c
134
core/divelist.c
|
@ -3,10 +3,10 @@
|
|||
/* core logic for the dive list -
|
||||
* accessed through the following interfaces:
|
||||
*
|
||||
* void process_loaded_dives();
|
||||
* void process_imported_dives(bool prefer_imported);
|
||||
* dive_trip_t *dive_trip_list;
|
||||
* unsigned int amount_selected;
|
||||
* struct trip_table trip_table
|
||||
* void process_loaded_dives()
|
||||
* void process_imported_dives(bool prefer_imported)
|
||||
* unsigned int amount_selected
|
||||
* void dump_selection(void)
|
||||
* void get_dive_gas(const struct dive *dive, int *o2_p, int *he_p, int *o2low_p)
|
||||
* char *get_dive_gas_string(const struct dive *dive)
|
||||
|
@ -38,6 +38,7 @@
|
|||
* bool trip_less_than(const struct dive_trip *a, const struct dive_trip *b)
|
||||
* bool dive_or_trip_less_than(struct dive_or_trip a, struct dive_or_trip b)
|
||||
* void sort_dive_table(struct dive_table *table)
|
||||
* void sort_trip_table(struct trip_table *table)
|
||||
* bool is_trip_before_after(const struct dive *dive, bool before)
|
||||
* void delete_dive_from_table(struct dive_table *table, int idx)
|
||||
* int find_next_visible_dive(timestamp_t when);
|
||||
|
@ -69,7 +70,7 @@ static bool dive_list_changed = false;
|
|||
|
||||
bool autogroup = false;
|
||||
|
||||
dive_trip_t *dive_trip_list;
|
||||
struct trip_table trip_table;
|
||||
|
||||
unsigned int amount_selected;
|
||||
|
||||
|
@ -748,14 +749,15 @@ void dump_trip_list(void)
|
|||
int i = 0;
|
||||
timestamp_t last_time = 0;
|
||||
|
||||
for (trip = dive_trip_list; trip; trip = trip->next) {
|
||||
for (i = 0; i < trip_table.nr; ++i) {
|
||||
struct tm tm;
|
||||
trip = trip_table.trips[i];
|
||||
utc_mkdate(trip_date(trip), &tm);
|
||||
if (trip_date(trip) < last_time)
|
||||
printf("\n\ndive_trip_list OUT OF ORDER!!!\n\n\n");
|
||||
printf("\n\ntrip_table OUT OF ORDER!!!\n\n\n");
|
||||
printf("%s trip %d to \"%s\" on %04u-%02u-%02u %02u:%02u:%02u (%d dives - %p)\n",
|
||||
trip->autogen ? "autogen " : "",
|
||||
++i, trip->location,
|
||||
i + 1, trip->location,
|
||||
tm.tm_year, tm.tm_mon + 1, tm.tm_mday, tm.tm_hour, tm.tm_min, tm.tm_sec,
|
||||
trip->dives.nr, trip);
|
||||
last_time = trip_date(trip);
|
||||
|
@ -764,23 +766,6 @@ void dump_trip_list(void)
|
|||
}
|
||||
#endif
|
||||
|
||||
/* insert the trip into the dive_trip_list */
|
||||
void insert_trip(dive_trip_t *dive_trip)
|
||||
{
|
||||
dive_trip_t **p = &dive_trip_list;
|
||||
dive_trip_t *trip;
|
||||
|
||||
/* Walk the dive trip list looking for the right location.. */
|
||||
while ((trip = *p) != NULL && trip_less_than(trip, dive_trip))
|
||||
p = &trip->next;
|
||||
|
||||
dive_trip->next = trip;
|
||||
*p = dive_trip;
|
||||
#ifdef DEBUG_TRIP
|
||||
dump_trip_list();
|
||||
#endif
|
||||
}
|
||||
|
||||
/* free resources associated with a trip structure */
|
||||
void free_trip(dive_trip_t *trip)
|
||||
{
|
||||
|
@ -791,32 +776,6 @@ void free_trip(dive_trip_t *trip)
|
|||
}
|
||||
}
|
||||
|
||||
/* remove trip from the trip-list, but don't free its memory.
|
||||
* caller takes ownership of the trip. */
|
||||
void unregister_trip(dive_trip_t *trip)
|
||||
{
|
||||
dive_trip_t **p, *tmp;
|
||||
|
||||
assert(!trip->dives.nr);
|
||||
|
||||
/* Remove the trip from the list of trips */
|
||||
p = &dive_trip_list;
|
||||
while ((tmp = *p) != NULL) {
|
||||
if (tmp == trip) {
|
||||
*p = trip->next;
|
||||
break;
|
||||
}
|
||||
p = &tmp->next;
|
||||
}
|
||||
}
|
||||
|
||||
static void delete_trip(dive_trip_t *trip)
|
||||
{
|
||||
unregister_trip(trip);
|
||||
free_trip(trip);
|
||||
}
|
||||
|
||||
|
||||
timestamp_t trip_date(const struct dive_trip *trip)
|
||||
{
|
||||
if (!trip || trip->dives.nr == 0)
|
||||
|
@ -902,6 +861,18 @@ static int comp_dives(const struct dive *a, const struct dive *b)
|
|||
return 0; /* this should not happen for a != b */
|
||||
}
|
||||
|
||||
/* Trips are compared according to the first dive in the trip. */
|
||||
static int comp_trips(const struct dive_trip *a, const struct dive_trip *b)
|
||||
{
|
||||
/* This should never happen, nevertheless don't crash on trips
|
||||
* with no (or worse a negative number of) dives. */
|
||||
if (a->dives.nr <= 0)
|
||||
return b->dives.nr <= 0 ? 0 : -1;
|
||||
if (b->dives.nr <= 0)
|
||||
return 1;
|
||||
return comp_dives(a->dives.dives[0], b->dives.dives[0]);
|
||||
}
|
||||
|
||||
#define MAKE_GROW_TABLE(table_type, item_type, array_name) \
|
||||
item_type *grow_##table_type(struct table_type *table) \
|
||||
{ \
|
||||
|
@ -920,6 +891,7 @@ static int comp_dives(const struct dive *a, const struct dive *b)
|
|||
}
|
||||
|
||||
MAKE_GROW_TABLE(dive_table, struct dive *, dives)
|
||||
static MAKE_GROW_TABLE(trip_table, struct dive_trip *, trips)
|
||||
|
||||
/* get the index where we want to insert an object so that everything stays
|
||||
* ordered according to a comparison function() */
|
||||
|
@ -935,6 +907,7 @@ MAKE_GROW_TABLE(dive_table, struct dive *, dives)
|
|||
}
|
||||
|
||||
MAKE_GET_INSERTION_INDEX(dive_table, struct dive *, dives, dive_less_than)
|
||||
static MAKE_GET_INSERTION_INDEX(trip_table, struct dive_trip *, trips, trip_less_than)
|
||||
|
||||
/* add object at the given index to a table. */
|
||||
#define MAKE_ADD_TO(table_type, item_type, array_name) \
|
||||
|
@ -952,6 +925,7 @@ MAKE_GET_INSERTION_INDEX(dive_table, struct dive *, dives, dive_less_than)
|
|||
}
|
||||
|
||||
static MAKE_ADD_TO(dive_table, struct dive *, dives)
|
||||
static MAKE_ADD_TO(trip_table, struct dive_trip *, trips)
|
||||
|
||||
#define MAKE_REMOVE_FROM(table_type, array_name) \
|
||||
void remove_from_##table_type(struct table_type *table, int idx) \
|
||||
|
@ -963,6 +937,7 @@ static MAKE_ADD_TO(dive_table, struct dive *, dives)
|
|||
}
|
||||
|
||||
static MAKE_REMOVE_FROM(dive_table, dives)
|
||||
static MAKE_REMOVE_FROM(trip_table, trips)
|
||||
|
||||
#define MAKE_GET_IDX(table_type, item_type, array_name) \
|
||||
int get_idx_in_##table_type(const struct table_type *table, const item_type item) \
|
||||
|
@ -975,6 +950,7 @@ static MAKE_REMOVE_FROM(dive_table, dives)
|
|||
}
|
||||
|
||||
static MAKE_GET_IDX(dive_table, struct dive *, dives)
|
||||
static MAKE_GET_IDX(trip_table, struct dive_trip *, trips)
|
||||
|
||||
#define MAKE_SORT(table_type, item_type, array_name, fun) \
|
||||
static int sortfn_##table_type(const void *_a, const void *_b) \
|
||||
|
@ -990,6 +966,7 @@ static MAKE_GET_IDX(dive_table, struct dive *, dives)
|
|||
}
|
||||
|
||||
MAKE_SORT(dive_table, struct dive *, dives, comp_dives)
|
||||
MAKE_SORT(trip_table, struct dive_trip *, trips, comp_trips)
|
||||
|
||||
/* remove a dive from the trip it's associated to, but don't delete the
|
||||
* trip if this was the last dive in the trip. the caller is responsible
|
||||
|
@ -1010,6 +987,12 @@ struct dive_trip *unregister_dive_from_trip(struct dive *dive)
|
|||
return trip;
|
||||
}
|
||||
|
||||
static void delete_trip(dive_trip_t *trip)
|
||||
{
|
||||
unregister_trip(trip);
|
||||
free_trip(trip);
|
||||
}
|
||||
|
||||
void remove_dive_from_trip(struct dive *dive)
|
||||
{
|
||||
struct dive_trip *trip = unregister_dive_from_trip(dive);
|
||||
|
@ -1036,6 +1019,16 @@ dive_trip_t *alloc_trip(void)
|
|||
return calloc(1, sizeof(dive_trip_t));
|
||||
}
|
||||
|
||||
/* insert the trip into the trip table */
|
||||
void insert_trip(dive_trip_t *dive_trip)
|
||||
{
|
||||
int idx = trip_table_get_insertion_index(&trip_table, dive_trip);
|
||||
add_to_trip_table(&trip_table, idx, dive_trip);
|
||||
#ifdef DEBUG_TRIP
|
||||
dump_trip_list();
|
||||
#endif
|
||||
}
|
||||
|
||||
dive_trip_t *create_trip_from_dive(struct dive *dive)
|
||||
{
|
||||
dive_trip_t *trip;
|
||||
|
@ -1051,12 +1044,22 @@ dive_trip_t *create_and_hookup_trip_from_dive(struct dive *dive)
|
|||
dive_trip_t *dive_trip = alloc_trip();
|
||||
|
||||
dive_trip = create_trip_from_dive(dive);
|
||||
insert_trip(dive_trip);
|
||||
|
||||
add_dive_to_trip(dive, dive_trip);
|
||||
insert_trip(dive_trip);
|
||||
return dive_trip;
|
||||
}
|
||||
|
||||
/* remove trip from the trip-list, but don't free its memory.
|
||||
* caller takes ownership of the trip. */
|
||||
void unregister_trip(dive_trip_t *trip)
|
||||
{
|
||||
int idx = get_idx_in_trip_table(&trip_table, trip);
|
||||
assert(!trip->dives.nr);
|
||||
if (idx >= 0)
|
||||
remove_from_trip_table(&trip_table, idx);
|
||||
}
|
||||
|
||||
/*
|
||||
* Find a trip a new dive should be autogrouped with. If no such trips
|
||||
* exist, allocate a new trip. The bool "*allocated" is set to true
|
||||
|
@ -1153,7 +1156,7 @@ dive_trip_t *get_dives_to_autogroup(struct dive_table *table, int start, int *fr
|
|||
}
|
||||
|
||||
/*
|
||||
* Walk the dives from the oldest dive in the given tabe, and see if we
|
||||
* Walk the dives from the oldest dive in the given table, and see if we
|
||||
* can autogroup them. But only do this when the user selected autogrouping.
|
||||
*/
|
||||
static void autogroup_dives(struct dive_table *table)
|
||||
|
@ -1167,12 +1170,13 @@ static void autogroup_dives(struct dive_table *table)
|
|||
return;
|
||||
|
||||
for (i = 0; (trip = get_dives_to_autogroup(&dive_table, i, &from, &to, &alloc)) != NULL; i = to) {
|
||||
for (j = from; j < to; ++j)
|
||||
add_dive_to_trip(get_dive(j), trip);
|
||||
/* If this was newly allocated, add trip to list */
|
||||
if (alloc)
|
||||
insert_trip(trip);
|
||||
for (j = from; j < to; ++j)
|
||||
add_dive_to_trip(get_dive(j), trip);
|
||||
}
|
||||
sort_trip_table(&trip_table);
|
||||
#ifdef DEBUG_TRIP
|
||||
dump_trip_list();
|
||||
#endif
|
||||
|
@ -1423,6 +1427,7 @@ void process_loaded_dives()
|
|||
set_dc_nickname(dive);
|
||||
|
||||
sort_dive_table(&dive_table);
|
||||
sort_trip_table(&trip_table);
|
||||
|
||||
/* Autogroup dives if desired by user. */
|
||||
autogroup_dives(&dive_table);
|
||||
|
@ -1577,6 +1582,9 @@ void process_imported_dives(struct dive_table *import_table, bool prefer_importe
|
|||
/* Autogroup dives if desired by user. */
|
||||
autogroup_dives(&dive_table);
|
||||
|
||||
/* Trips may have changed - make sure that they are still ordered */
|
||||
sort_trip_table(&trip_table);
|
||||
|
||||
/* We might have deleted the old selected dive.
|
||||
* Choose the newest dive as selected (if any) */
|
||||
current_dive = dive_table.nr > 0 ? dive_table.dives[dive_table.nr - 1] : NULL;
|
||||
|
@ -1660,6 +1668,10 @@ void clear_dive_file_data()
|
|||
delete_single_dive(0);
|
||||
while (dive_site_table.nr)
|
||||
delete_dive_site(get_dive_site(0));
|
||||
if (trip_table.nr != 0) {
|
||||
fprintf(stderr, "Warning: trip table not empty in clear_dive_file_data()!\n");
|
||||
trip_table.nr = 0;
|
||||
}
|
||||
|
||||
clear_dive(&displayed_dive);
|
||||
|
||||
|
@ -1682,18 +1694,6 @@ bool dive_less_than(const struct dive *a, const struct dive *b)
|
|||
return comp_dives(a, b) < 0;
|
||||
}
|
||||
|
||||
/* Trips are compared according to the first dive in the trip. */
|
||||
static int comp_trips(const struct dive_trip *a, const struct dive_trip *b)
|
||||
{
|
||||
/* This should never happen, nevertheless don't crash on trips
|
||||
* with no (or worse a negative number of) dives. */
|
||||
if (a->dives.nr <= 0)
|
||||
return b->dives.nr <= 0 ? 0 : -1;
|
||||
if (b->dives.nr <= 0)
|
||||
return 1;
|
||||
return comp_dives(a->dives.dives[0], b->dives.dives[0]);
|
||||
}
|
||||
|
||||
bool trip_less_than(const struct dive_trip *a, const struct dive_trip *b)
|
||||
{
|
||||
return comp_trips(a, b) < 0;
|
||||
|
|
|
@ -930,8 +930,8 @@ static int create_git_tree(git_repository *repo, struct dir *root, bool select_o
|
|||
|
||||
save_divesites(repo, root);
|
||||
|
||||
for (trip = dive_trip_list; trip != NULL; trip = trip->next)
|
||||
trip->saved = 0;
|
||||
for (i = 0; i < trip_table.nr; ++i)
|
||||
trip_table.trips[i]->saved = 0;
|
||||
|
||||
/* save the dives */
|
||||
git_storage_update_progress(translate("gettextFromC", "Start saving dives"));
|
||||
|
|
|
@ -439,8 +439,8 @@ void write_trips(struct membuffer *b, const char *photos_dir, bool selected_only
|
|||
char sep_ = ' ';
|
||||
char *sep = &sep_;
|
||||
|
||||
for (trip = dive_trip_list; trip != NULL; trip = trip->next)
|
||||
trip->saved = 0;
|
||||
for (i = 0; i < trip_table.nr; ++i)
|
||||
trip_table.trips[i]->saved = 0;
|
||||
|
||||
for_each_dive (i, dive) {
|
||||
trip = dive->divetrip;
|
||||
|
|
|
@ -637,8 +637,8 @@ void save_dives_buffer(struct membuffer *b, const bool select_only, bool anonymi
|
|||
put_format(b, "</site>\n");
|
||||
}
|
||||
put_format(b, "</divesites>\n<dives>\n");
|
||||
for (trip = dive_trip_list; trip != NULL; trip = trip->next)
|
||||
trip->saved = 0;
|
||||
for (i = 0; i < trip_table.nr; ++i)
|
||||
trip_table.trips[i]->saved = 0;
|
||||
|
||||
/* save the dives */
|
||||
for_each_dive(i, dive) {
|
||||
|
|
|
@ -81,10 +81,10 @@ DiveToAdd DiveListBase::removeDive(struct dive *d)
|
|||
// Returns pointer to added dive (which is owned by the backend!)
|
||||
dive *DiveListBase::addDive(DiveToAdd &d)
|
||||
{
|
||||
if (d.tripToAdd)
|
||||
insert_trip(d.tripToAdd.release()); // Return ownership to backend
|
||||
if (d.trip)
|
||||
add_dive_to_trip(d.dive.get(), d.trip);
|
||||
if (d.tripToAdd)
|
||||
insert_trip(d.tripToAdd.release()); // Return ownership to backend
|
||||
dive *res = d.dive.release(); // Give up ownership of dive
|
||||
|
||||
// Set the filter flag according to current filter settings
|
||||
|
@ -530,6 +530,7 @@ void AddDive::redoit()
|
|||
currentDive = current_dive;
|
||||
|
||||
divesToRemove = addDives(divesToAdd);
|
||||
sort_trip_table(&trip_table); // Though unlikely, adding a dive may reorder trips
|
||||
mark_divelist_changed(true);
|
||||
|
||||
// Select the newly added dive
|
||||
|
@ -544,6 +545,7 @@ void AddDive::undoit()
|
|||
{
|
||||
// Simply remove the dive that was previously added...
|
||||
divesToAdd = removeDives(divesToRemove);
|
||||
sort_trip_table(&trip_table); // Though unlikely, removing a dive may reorder trips
|
||||
|
||||
// ...and restore the selection
|
||||
restoreSelection(selection, currentDive);
|
||||
|
@ -566,6 +568,7 @@ bool DeleteDive::workToBeDone()
|
|||
void DeleteDive::undoit()
|
||||
{
|
||||
divesToDelete = addDives(divesToAdd);
|
||||
sort_trip_table(&trip_table); // Though unlikely, removing a dive may reorder trips
|
||||
mark_divelist_changed(true);
|
||||
|
||||
// Select all re-added dives and make the first one current
|
||||
|
@ -576,6 +579,7 @@ void DeleteDive::undoit()
|
|||
void DeleteDive::redoit()
|
||||
{
|
||||
divesToAdd = removeDives(divesToDelete);
|
||||
sort_trip_table(&trip_table); // Though unlikely, adding a dive may reorder trips
|
||||
mark_divelist_changed(true);
|
||||
|
||||
// Deselect all dives and select dive that was close to the first deleted dive
|
||||
|
@ -604,6 +608,7 @@ void ShiftTime::redoit()
|
|||
|
||||
// Changing times may have unsorted the dive table
|
||||
sort_dive_table(&dive_table);
|
||||
sort_trip_table(&trip_table);
|
||||
|
||||
// We send one time changed signal per trip (see comments in DiveListNotifier.h).
|
||||
// Therefore, collect all dives in an array and sort by trip.
|
||||
|
@ -667,6 +672,7 @@ bool TripBase::workToBeDone()
|
|||
void TripBase::redoit()
|
||||
{
|
||||
moveDivesBetweenTrips(divesToMove);
|
||||
sort_trip_table(&trip_table); // Though unlikely, moving dives may reorder trips
|
||||
|
||||
mark_divelist_changed(true);
|
||||
}
|
||||
|
|
|
@ -1131,6 +1131,7 @@ void QMLManager::commitChanges(QString diveId, QString date, QString location, Q
|
|||
// we know that the only thing that might happen in a resort is that
|
||||
// this one dive moves to a different spot in the dive list
|
||||
sort_dive_table(&dive_table);
|
||||
sort_trip_table(&trip_table);
|
||||
int newIdx = get_idx_by_uniq_id(d->id);
|
||||
if (newIdx != oldIdx) {
|
||||
DiveListModel::instance()->removeDive(modelIdx);
|
||||
|
|
Loading…
Reference in a new issue