mirror of
				https://github.com/subsurface/subsurface.git
				synced 2025-02-19 22:16:15 +00:00 
			
		
		
		
	Cleanup: move trip-related functions into own translation unit
These functions were spread out over dive.c and divelist.c. Move them into their own file to make all this a bit less monolithic. Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
This commit is contained in:
		
							parent
							
								
									f1c2cd375e
								
							
						
					
					
						commit
						7f4d9db962
					
				
					 45 changed files with 481 additions and 426 deletions
				
			
		|  | @ -150,6 +150,8 @@ set(SUBSURFACE_CORE_LIB_SRCS | |||
| 	taxonomy.c | ||||
| 	taxonomy.h | ||||
| 	time.c | ||||
| 	trip.c | ||||
| 	trip.h | ||||
| 	uemis-downloader.c | ||||
| 	uemis.c | ||||
| 	uemis.h | ||||
|  |  | |||
|  | @ -15,6 +15,7 @@ | |||
| #include "metadata.h" | ||||
| #include "membuffer.h" | ||||
| #include "tag.h" | ||||
| #include "trip.h" | ||||
| #include "structured_list.h" | ||||
| 
 | ||||
| /* one could argue about the best place to have this variable -
 | ||||
|  |  | |||
							
								
								
									
										33
									
								
								core/dive.h
									
										
									
									
									
								
							
							
						
						
									
										33
									
								
								core/dive.h
									
										
									
									
									
								
							|  | @ -179,28 +179,15 @@ typedef struct dive_table { | |||
| 	struct dive **dives; | ||||
| } dive_table_t; | ||||
| 
 | ||||
| typedef struct dive_trip | ||||
| { | ||||
| 	char *location; | ||||
| 	char *notes; | ||||
| 	struct dive_table dives; | ||||
| 	/* Used by the io-routines to mark trips that have already been written. */ | ||||
| 	bool saved; | ||||
| 	bool autogen; | ||||
| } dive_trip_t; | ||||
| 
 | ||||
| typedef struct trip_table { | ||||
| 	int nr, allocated; | ||||
| 	struct dive_trip **trips; | ||||
| } trip_table_t; | ||||
| 
 | ||||
| struct picture; | ||||
| struct dive_site; | ||||
| struct dive_site_table; | ||||
| struct dive_trip; | ||||
| struct trip_table; | ||||
| struct dive { | ||||
| 	int number; | ||||
| 	bool notrip; /* Don't autogroup this dive to a trip */ | ||||
| 	dive_trip_t *divetrip; | ||||
| 	struct dive_trip *divetrip; | ||||
| 	bool selected; | ||||
| 	bool hidden_by_filter; | ||||
| 	timestamp_t when; | ||||
|  | @ -304,23 +291,15 @@ extern depth_t gas_mnd(struct gasmix mix, depth_t end, const struct dive *dive, | |||
| 
 | ||||
| extern bool autogroup; | ||||
| 
 | ||||
| extern void add_dive_to_trip(struct dive *, dive_trip_t *); | ||||
| 
 | ||||
| struct dive *unregister_dive(int idx); | ||||
| extern void delete_single_dive(int idx); | ||||
| 
 | ||||
| extern void insert_trip(dive_trip_t *trip, struct trip_table *trip_table_arg); | ||||
| extern int remove_trip(const dive_trip_t *trip, struct trip_table *trip_table_arg); | ||||
| extern void free_trip(dive_trip_t *trip); | ||||
| extern timestamp_t trip_date(const struct dive_trip *trip); | ||||
| 
 | ||||
| extern const struct units SI_units, IMPERIAL_units; | ||||
| 
 | ||||
| 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; | ||||
|  | @ -430,10 +409,8 @@ extern void add_sample_pressure(struct sample *sample, int sensor, int mbar); | |||
| extern int legacy_format_o2pressures(const struct dive *dive, const struct divecomputer *dc); | ||||
| 
 | ||||
| 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 pressure_t calculate_surface_pressure(const struct dive *dive); | ||||
| extern pressure_t un_fixup_surface_pressure(const struct dive *d); | ||||
|  | @ -621,12 +598,10 @@ extern void average_max_depth(struct diveplan *dive, int *avg_depth, int *max_de | |||
|  * Note: we have to use the typedef "dive_table_t" instead of "struct dive_table", | ||||
|  * because MOC removes the "struct", but dive_table is already the name of a global | ||||
|  * variable, leading to compilation errors. Likewise for "struct trip_table" and | ||||
|  * "struct dive_site_table" (defined in "divesite.h"). */ | ||||
|  * "struct dive_site_table" (defined in "dive.h" and "divesite.h"). */ | ||||
| #include <QObject> | ||||
| Q_DECLARE_METATYPE(struct dive *); | ||||
| Q_DECLARE_METATYPE(struct dive_trip *); | ||||
| Q_DECLARE_METATYPE(dive_table_t *); | ||||
| Q_DECLARE_METATYPE(trip_table_t *); | ||||
| 
 | ||||
| #endif | ||||
| 
 | ||||
|  |  | |||
							
								
								
									
										364
									
								
								core/divelist.c
									
										
									
									
									
								
							
							
						
						
									
										364
									
								
								core/divelist.c
									
										
									
									
									
								
							|  | @ -19,6 +19,7 @@ | |||
| #include "qthelper.h" | ||||
| #include "git-access.h" | ||||
| #include "table.h" | ||||
| #include "trip.h" | ||||
| 
 | ||||
| /* This flag is set to true by operations that are not implemented in the
 | ||||
|  * undo system. It is therefore only cleared on save and load. */ | ||||
|  | @ -26,8 +27,6 @@ static bool dive_list_changed = false; | |||
| 
 | ||||
| bool autogroup = false; | ||||
| 
 | ||||
| struct trip_table trip_table; | ||||
| 
 | ||||
| unsigned int amount_selected; | ||||
| 
 | ||||
| #if DEBUG_SELECTION_TRACKING | ||||
|  | @ -679,72 +678,6 @@ char *get_dive_gas_string(const struct dive *dive) | |||
| 	return buffer; | ||||
| } | ||||
| 
 | ||||
| /*
 | ||||
|  * helper functions for dive_trip handling | ||||
|  */ | ||||
| #ifdef DEBUG_TRIP | ||||
| void dump_trip_list(void) | ||||
| { | ||||
| 	dive_trip_t *trip; | ||||
| 	int i = 0; | ||||
| 	timestamp_t last_time = 0; | ||||
| 
 | ||||
| 	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\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 + 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); | ||||
| 	} | ||||
| 	printf("-----\n"); | ||||
| } | ||||
| #endif | ||||
| 
 | ||||
| /* free resources associated with a trip structure */ | ||||
| void free_trip(dive_trip_t *trip) | ||||
| { | ||||
| 	if (trip) { | ||||
| 		free(trip->location); | ||||
| 		free(trip->notes); | ||||
| 		free(trip->dives.dives); | ||||
| 		free(trip); | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| timestamp_t trip_date(const struct dive_trip *trip) | ||||
| { | ||||
| 	if (!trip || trip->dives.nr == 0) | ||||
| 		return 0; | ||||
| 	return trip->dives.dives[0]->when; | ||||
| } | ||||
| 
 | ||||
| static timestamp_t trip_enddate(const struct dive_trip *trip) | ||||
| { | ||||
| 	if (!trip || trip->dives.nr == 0) | ||||
| 		return 0; | ||||
| 	return dive_endtime(trip->dives.dives[trip->dives.nr - 1]); | ||||
| } | ||||
| 
 | ||||
| /* check if we have a trip right before / after this dive */ | ||||
| bool is_trip_before_after(const struct dive *dive, bool before) | ||||
| { | ||||
| 	int idx = get_idx_by_uniq_id(dive->id); | ||||
| 	if (before) { | ||||
| 		if (idx > 0 && get_dive(idx - 1)->divetrip) | ||||
| 			return true; | ||||
| 	} else { | ||||
| 		if (idx < dive_table.nr - 1 && get_dive(idx + 1)->divetrip) | ||||
| 			return true; | ||||
| 	} | ||||
| 	return false; | ||||
| } | ||||
| 
 | ||||
| struct dive *first_selected_dive() | ||||
| { | ||||
| 	int idx; | ||||
|  | @ -809,7 +742,7 @@ static int comp_dc(const struct divecomputer *dc1, const struct divecomputer *dc | |||
|  * We might also consider sorting by end-time and other criteria, | ||||
|  * but see the caveat above (editing means rearrangement of the dives). | ||||
|  */ | ||||
| static int comp_dives(const struct dive *a, const struct dive *b) | ||||
| int comp_dives(const struct dive *a, const struct dive *b) | ||||
| { | ||||
| 	int cmp; | ||||
| 	if (a->when < b->when) | ||||
|  | @ -839,222 +772,21 @@ 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]); | ||||
| } | ||||
| 
 | ||||
| /* Dive table functions */ | ||||
| MAKE_GROW_TABLE(dive_table, struct dive *, dives) | ||||
| static MAKE_GROW_TABLE(trip_table, struct dive_trip *, trips) | ||||
| 
 | ||||
| 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) | ||||
| 
 | ||||
| MAKE_ADD_TO(dive_table, struct dive *, dives) | ||||
| static MAKE_ADD_TO(trip_table, struct dive_trip *, trips) | ||||
| 
 | ||||
| static MAKE_REMOVE_FROM(dive_table, dives) | ||||
| static MAKE_REMOVE_FROM(trip_table, trips) | ||||
| 
 | ||||
| static MAKE_GET_IDX(dive_table, struct dive *, dives) | ||||
| static MAKE_GET_IDX(trip_table, struct dive_trip *, trips) | ||||
| 
 | ||||
| MAKE_SORT(dive_table, struct dive *, dives, comp_dives) | ||||
| MAKE_SORT(trip_table, struct dive_trip *, trips, comp_trips) | ||||
| 
 | ||||
| MAKE_REMOVE(dive_table, struct dive *, dive) | ||||
| MAKE_REMOVE(trip_table, struct dive_trip *, trip) | ||||
| 
 | ||||
| static void insert_dive(struct dive_table *table, struct dive *d) | ||||
| void insert_dive(struct dive_table *table, struct dive *d) | ||||
| { | ||||
| 	int idx = dive_table_get_insertion_index(table, d); | ||||
| 	add_to_dive_table(table, idx, d); | ||||
| } | ||||
| 
 | ||||
| /* 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 | ||||
|  * for removing the trip, if the trip->dives.nr went to 0. | ||||
|  */ | ||||
| struct dive_trip *unregister_dive_from_trip(struct dive *dive) | ||||
| { | ||||
| 	dive_trip_t *trip = dive->divetrip; | ||||
| 
 | ||||
| 	if (!trip) | ||||
| 		return NULL; | ||||
| 
 | ||||
| 	remove_dive(dive, &trip->dives); | ||||
| 	dive->divetrip = NULL; | ||||
| 	return trip; | ||||
| } | ||||
| 
 | ||||
| static void delete_trip(dive_trip_t *trip, struct trip_table *trip_table_arg) | ||||
| { | ||||
| 	remove_trip(trip, trip_table_arg); | ||||
| 	free_trip(trip); | ||||
| } | ||||
| 
 | ||||
| void remove_dive_from_trip(struct dive *dive, struct trip_table *trip_table_arg) | ||||
| { | ||||
| 	struct dive_trip *trip = unregister_dive_from_trip(dive); | ||||
| 	if (trip && trip->dives.nr == 0) | ||||
| 		delete_trip(trip, trip_table_arg); | ||||
| } | ||||
| 
 | ||||
| /* Add dive to a trip. Caller is responsible for removing dive
 | ||||
|  * from trip beforehand. */ | ||||
| void add_dive_to_trip(struct dive *dive, dive_trip_t *trip) | ||||
| { | ||||
| 	if (dive->divetrip == trip) | ||||
| 		return; | ||||
| 	if (dive->divetrip) | ||||
| 		fprintf(stderr, "Warning: adding dive to trip that has trip set\n"); | ||||
| 	insert_dive(&trip->dives, dive); | ||||
| 	dive->divetrip = trip; | ||||
| } | ||||
| 
 | ||||
| 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, struct trip_table *trip_table_arg) | ||||
| { | ||||
| 	int idx = trip_table_get_insertion_index(trip_table_arg, dive_trip); | ||||
| 	add_to_trip_table(trip_table_arg, idx, dive_trip); | ||||
| #ifdef DEBUG_TRIP | ||||
| 	dump_trip_list(); | ||||
| #endif | ||||
| } | ||||
| 
 | ||||
| dive_trip_t *create_trip_from_dive(struct dive *dive) | ||||
| { | ||||
| 	dive_trip_t *trip; | ||||
| 
 | ||||
| 	trip = alloc_trip(); | ||||
| 	trip->location = copy_string(get_dive_location(dive)); | ||||
| 
 | ||||
| 	return trip; | ||||
| } | ||||
| 
 | ||||
| dive_trip_t *create_and_hookup_trip_from_dive(struct dive *dive, struct trip_table *trip_table_arg) | ||||
| { | ||||
| 	dive_trip_t *dive_trip = alloc_trip(); | ||||
| 
 | ||||
| 	dive_trip = create_trip_from_dive(dive); | ||||
| 
 | ||||
| 	add_dive_to_trip(dive, dive_trip); | ||||
| 	insert_trip(dive_trip, trip_table_arg); | ||||
| 	return dive_trip; | ||||
| } | ||||
| 
 | ||||
| /* random threshold: three days without diving -> new trip
 | ||||
|  * this works very well for people who usually dive as part of a trip and don't | ||||
|  * regularly dive at a local facility; this is why trips are an optional feature */ | ||||
| #define TRIP_THRESHOLD 3600 * 24 * 3 | ||||
| 
 | ||||
| /*
 | ||||
|  * 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 | ||||
|  * if a new trip was allocated. | ||||
|  */ | ||||
| dive_trip_t *get_trip_for_new_dive(struct dive *new_dive, bool *allocated) | ||||
| { | ||||
| 	struct dive *d; | ||||
| 	dive_trip_t *trip; | ||||
| 	int i; | ||||
| 
 | ||||
| 	/* Find dive that is within TRIP_THRESHOLD of current dive */ | ||||
| 	for_each_dive(i, d) { | ||||
| 		/* Check if we're past the range of possible dives */ | ||||
| 		if (d->when >= new_dive->when + TRIP_THRESHOLD) | ||||
| 			break; | ||||
| 
 | ||||
| 		if (d->when + TRIP_THRESHOLD >= new_dive->when && d->divetrip) { | ||||
| 			/* Found a dive with trip in the range */ | ||||
| 			*allocated = false; | ||||
| 			return d->divetrip; | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	/* Didn't find a trip -> allocate a new one */ | ||||
| 	trip = create_trip_from_dive(new_dive); | ||||
| 	trip->autogen = true; | ||||
| 	*allocated = true; | ||||
| 	return trip; | ||||
| } | ||||
| 
 | ||||
| /*
 | ||||
|  * Collect dives for auto-grouping. Pass in first dive which should be checked. | ||||
|  * Returns range of dives that should be autogrouped and trip it should be | ||||
|  * associated to. If the returned trip was newly allocated, the last bool | ||||
|  * is set to true. Caller still has to register it in the system. Note | ||||
|  * whereas this looks complicated - it is needed by the undo-system, which | ||||
|  * manually injects the new trips. If there are no dives to be autogrouped, | ||||
|  * return NULL. | ||||
|  */ | ||||
| dive_trip_t *get_dives_to_autogroup(struct dive_table *table, int start, int *from, int *to, bool *allocated) | ||||
| { | ||||
| 	int i; | ||||
| 	struct dive *lastdive = NULL; | ||||
| 
 | ||||
| 	/* Find first dive that should be merged and remember any previous
 | ||||
| 	 * dive that could be merged into. | ||||
| 	 */ | ||||
| 	for (i = start; i < table->nr; i++) { | ||||
| 		struct dive *dive = table->dives[i]; | ||||
| 		dive_trip_t *trip; | ||||
| 
 | ||||
| 		if (dive->divetrip) { | ||||
| 			lastdive = dive; | ||||
| 			continue; | ||||
| 		} | ||||
| 
 | ||||
| 		/* Only consider dives that have not been explicitly removed from
 | ||||
| 		 * a dive trip by the user.  */ | ||||
| 		if (dive->notrip) { | ||||
| 			lastdive = NULL; | ||||
| 			continue; | ||||
| 		} | ||||
| 
 | ||||
| 		/* We found a dive, let's see if we have to allocate a new trip */ | ||||
| 		if (!lastdive || dive->when >= lastdive->when + TRIP_THRESHOLD) { | ||||
| 			/* allocate new trip */ | ||||
| 			trip = create_trip_from_dive(dive); | ||||
| 			trip->autogen = true; | ||||
| 			*allocated = true; | ||||
| 		} else { | ||||
| 			/* use trip of previous dive */ | ||||
| 			trip = lastdive->divetrip; | ||||
| 			*allocated = false; | ||||
| 		} | ||||
| 
 | ||||
| 		// Now, find all dives that will be added to this trip
 | ||||
| 		lastdive = dive; | ||||
| 		*from = i; | ||||
| 		for (*to = *from + 1; *to < table->nr; (*to)++) { | ||||
| 			dive = table->dives[*to]; | ||||
| 			if (dive->divetrip || dive->notrip || | ||||
| 			    dive->when >= lastdive->when + TRIP_THRESHOLD) | ||||
| 				break; | ||||
| 			if (get_dive_location(dive) && !trip->location) | ||||
| 				trip->location = copy_string(get_dive_location(dive)); | ||||
| 			lastdive = dive; | ||||
| 		} | ||||
| 		return trip; | ||||
| 	} | ||||
| 
 | ||||
| 	/* Did not find anyhting - mark as end */ | ||||
| 	return NULL; | ||||
| } | ||||
| 
 | ||||
| /*
 | ||||
|  * 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. | ||||
|  | @ -1195,26 +927,6 @@ void deselect_dive(struct dive *dive) | |||
| 	} | ||||
| } | ||||
| 
 | ||||
| void deselect_dives_in_trip(struct dive_trip *trip) | ||||
| { | ||||
| 	if (!trip) | ||||
| 		return; | ||||
| 	for (int i = 0; i < trip->dives.nr; ++i) | ||||
| 		deselect_dive(trip->dives.dives[i]); | ||||
| } | ||||
| 
 | ||||
| void select_dives_in_trip(struct dive_trip *trip) | ||||
| { | ||||
| 	struct dive *dive; | ||||
| 	if (!trip) | ||||
| 		return; | ||||
| 	for (int i = 0; i < trip->dives.nr; ++i) { | ||||
| 		dive = trip->dives.dives[i]; | ||||
| 		if (!dive->hidden_by_filter) | ||||
| 			select_dive(dive); | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| void filter_dive(struct dive *d, bool shown) | ||||
| { | ||||
| 	if (!d) | ||||
|  | @ -1224,26 +936,6 @@ void filter_dive(struct dive *d, bool shown) | |||
| 		deselect_dive(d); | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| /* Out of two strings, copy the string that is not empty (if any). */ | ||||
| static char *copy_non_empty_string(const char *a, const char *b) | ||||
| { | ||||
| 	return copy_string(empty_string(b) ? a : b); | ||||
| } | ||||
| 
 | ||||
| /* This combines the information of two trips, generating a
 | ||||
|  * new trip. To support undo, we have to preserve the old trips. */ | ||||
| dive_trip_t *combine_trips(struct dive_trip *trip_a, struct dive_trip *trip_b) | ||||
| { | ||||
| 	dive_trip_t *trip; | ||||
| 
 | ||||
| 	trip = alloc_trip(); | ||||
| 	trip->location = copy_non_empty_string(trip_a->location, trip_b->location); | ||||
| 	trip->notes = copy_non_empty_string(trip_a->notes, trip_b->notes); | ||||
| 
 | ||||
| 	return trip; | ||||
| } | ||||
| 
 | ||||
| void mark_divelist_changed(bool changed) | ||||
| { | ||||
| 	if (dive_list_changed == changed) | ||||
|  | @ -1315,7 +1007,7 @@ static void merge_imported_dives(struct dive_table *table) | |||
| } | ||||
| 
 | ||||
| /*
 | ||||
|  * Clear a dive_table, trip_table and dive_site_table. Think about generating these with macros. | ||||
|  * Clear a dive_table and dive_site_table. Think about generating these with macros. | ||||
|  */ | ||||
| void clear_table(struct dive_table *table) | ||||
| { | ||||
|  | @ -1324,13 +1016,6 @@ void clear_table(struct dive_table *table) | |||
| 	table->nr = 0; | ||||
| } | ||||
| 
 | ||||
| void clear_trip_table(struct trip_table *table) | ||||
| { | ||||
| 	for (int i = 0; i < table->nr; i++) | ||||
| 		free_trip(table->trips[i]); | ||||
| 	table->nr = 0; | ||||
| } | ||||
| 
 | ||||
| void clear_dive_site_table(struct dive_site_table *ds_table) | ||||
| { | ||||
| 	for (int i = 0; i < ds_table->nr; i++) | ||||
|  | @ -1837,11 +1522,6 @@ bool dive_less_than(const struct dive *a, const struct dive *b) | |||
| 	return comp_dives(a, b) < 0; | ||||
| } | ||||
| 
 | ||||
| bool trip_less_than(const struct dive_trip *a, const struct dive_trip *b) | ||||
| { | ||||
| 	return comp_trips(a, b) < 0; | ||||
| } | ||||
| 
 | ||||
| /* When comparing a dive to a trip, use the first dive of the trip. */ | ||||
| static int comp_dive_to_trip(struct dive *a, struct dive_trip *b) | ||||
| { | ||||
|  | @ -1925,37 +1605,3 @@ struct dive *find_next_visible_dive(timestamp_t when) | |||
| 
 | ||||
| 	return NULL; | ||||
| } | ||||
| 
 | ||||
| static bool is_same_day(timestamp_t trip_when, timestamp_t dive_when) | ||||
| { | ||||
| 	static timestamp_t twhen = (timestamp_t) 0; | ||||
| 	static struct tm tmt; | ||||
| 	struct tm tmd; | ||||
| 
 | ||||
| 	utc_mkdate(dive_when, &tmd); | ||||
| 
 | ||||
| 	if (twhen != trip_when) { | ||||
| 		twhen = trip_when; | ||||
| 		utc_mkdate(twhen, &tmt); | ||||
| 	} | ||||
| 
 | ||||
| 	return (tmd.tm_mday == tmt.tm_mday) && (tmd.tm_mon == tmt.tm_mon) && (tmd.tm_year == tmt.tm_year); | ||||
| } | ||||
| 
 | ||||
| bool trip_is_single_day(const struct dive_trip *trip) | ||||
| { | ||||
| 	if (trip->dives.nr <= 1) | ||||
| 		return true; | ||||
| 	return is_same_day(trip->dives.dives[0]->when, | ||||
| 			   trip->dives.dives[trip->dives.nr - 1]->when); | ||||
| } | ||||
| 
 | ||||
| int trip_shown_dives(const struct dive_trip *trip) | ||||
| { | ||||
| 	int res = 0; | ||||
| 	for (int i = 0; i < trip->dives.nr; ++i) { | ||||
| 		if (!trip->dives.dives[i]->hidden_by_filter) | ||||
| 			res++; | ||||
| 	} | ||||
| 	return res; | ||||
| } | ||||
|  |  | |||
|  | @ -35,33 +35,23 @@ extern struct dive **grow_dive_table(struct dive_table *table); | |||
| extern int dive_table_get_insertion_index(struct dive_table *table, struct dive *dive); | ||||
| extern void add_to_dive_table(struct dive_table *table, int idx, struct dive *dive); | ||||
| extern void append_dive(struct dive *dive); | ||||
| extern void insert_dive(struct dive_table *table, struct dive *d); | ||||
| extern void get_dive_gas(const struct dive *dive, int *o2_p, int *he_p, int *o2low_p); | ||||
| extern int get_divenr(const struct dive *dive); | ||||
| extern struct dive_trip *unregister_dive_from_trip(struct dive *dive); | ||||
| extern int remove_dive(const struct dive *dive, struct dive_table *table); | ||||
| extern void remove_dive_from_trip(struct dive *dive, struct trip_table *trip_table_arg); | ||||
| extern dive_trip_t *alloc_trip(void); | ||||
| extern dive_trip_t *create_trip_from_dive(struct dive *dive); | ||||
| extern dive_trip_t *create_and_hookup_trip_from_dive(struct dive *dive, struct trip_table *trip_table_arg); | ||||
| extern dive_trip_t *get_dives_to_autogroup(struct dive_table *table, int start, int *from, int *to, bool *allocated); | ||||
| extern dive_trip_t *get_trip_for_new_dive(struct dive *new_dive, bool *allocated); | ||||
| extern bool consecutive_selected(); | ||||
| extern void select_dive(struct dive *dive); | ||||
| extern void deselect_dive(struct dive *dive); | ||||
| extern void select_dives_in_trip(struct dive_trip *trip); | ||||
| extern void deselect_dives_in_trip(struct dive_trip *trip); | ||||
| extern void filter_dive(struct dive *d, bool shown); | ||||
| extern dive_trip_t *combine_trips(struct dive_trip *trip_a, struct dive_trip *trip_b); | ||||
| extern struct dive *first_selected_dive(); | ||||
| extern struct dive *last_selected_dive(); | ||||
| extern bool is_trip_before_after(const struct dive *dive, bool before); | ||||
| extern int get_dive_nr_at_idx(int idx); | ||||
| extern void set_dive_nr_for_current_dive(); | ||||
| extern timestamp_t get_surface_interval(timestamp_t when); | ||||
| extern void delete_dive_from_table(struct dive_table *table, int idx); | ||||
| extern struct dive *find_next_visible_dive(timestamp_t when); | ||||
| extern bool trip_is_single_day(const struct dive_trip *trip); | ||||
| extern int trip_shown_dives(const struct dive_trip *trip); | ||||
| 
 | ||||
| extern int comp_dives(const struct dive *a, const struct dive *b); | ||||
| 
 | ||||
| int get_min_datafile_version(); | ||||
| void reset_min_datafile_version(); | ||||
|  | @ -69,13 +59,11 @@ void report_datafile_version(int version); | |||
| int get_dive_id_closest_to(timestamp_t when); | ||||
| void clear_dive_file_data(); | ||||
| void clear_table(struct dive_table *table); | ||||
| void clear_trip_table(struct trip_table *table); | ||||
| 
 | ||||
| typedef enum {PO2VAL, SINGLE_EXP, SINGLE_SLOPE, DAILY_EXP, DAILY_SLOPE, NO_COLUMNS} cns_table_headers; | ||||
| 
 | ||||
| #ifdef DEBUG_TRIP | ||||
| extern void dump_selection(void); | ||||
| extern void dump_trip_list(void); | ||||
| #endif | ||||
| 
 | ||||
| #ifdef __cplusplus | ||||
|  |  | |||
|  | @ -16,8 +16,8 @@ | |||
| #include "gettext.h" | ||||
| 
 | ||||
| #include "divesite.h" | ||||
| #include "trip.h" | ||||
| #include "subsurface-string.h" | ||||
| #include "divelist.h" | ||||
| #include "device.h" | ||||
| #include "membuffer.h" | ||||
| #include "git-access.h" | ||||
|  |  | |||
|  | @ -25,7 +25,7 @@ | |||
| #include "divesite.h" | ||||
| #include "subsurface-string.h" | ||||
| #include "parse.h" | ||||
| #include "divelist.h" | ||||
| #include "trip.h" | ||||
| #include "device.h" | ||||
| #include "membuffer.h" | ||||
| #include "qthelper.h" | ||||
|  |  | |||
|  | @ -10,7 +10,7 @@ | |||
| #include "divesite.h" | ||||
| #include "subsurface-string.h" | ||||
| #include "parse.h" | ||||
| #include "divelist.h" | ||||
| #include "trip.h" | ||||
| #include "device.h" | ||||
| #include "gettext.h" | ||||
| 
 | ||||
|  |  | |||
|  | @ -46,7 +46,7 @@ struct parser_state { | |||
| 	struct dive *cur_dive;			/* owning */ | ||||
| 	struct dive_site *cur_dive_site;	/* owning */ | ||||
| 	location_t cur_location; | ||||
| 	dive_trip_t *cur_trip;			/* owning */ | ||||
| 	struct dive_trip *cur_trip;		/* owning */ | ||||
| 	struct sample *cur_sample;		/* non-owning */ | ||||
| 	struct picture *cur_picture;		/* owning */ | ||||
| 	char *country, *city;			/* owning */ | ||||
|  |  | |||
|  | @ -18,6 +18,7 @@ | |||
| #include "exif.h" | ||||
| #include "file.h" | ||||
| #include "tag.h" | ||||
| #include "trip.h" | ||||
| #include "imagedownloader.h" | ||||
| #include <QFile> | ||||
| #include <QRegExp> | ||||
|  |  | |||
|  | @ -24,7 +24,7 @@ enum inertgas {N2, HE}; | |||
| QString weight_string(int weight_in_grams); | ||||
| QString distance_string(int distanceInMeters); | ||||
| bool gpsHasChanged(struct dive *dive, struct dive *master, const QString &gps_text, bool *parsed_out = 0); | ||||
| QList<int> getDivesInTrip(dive_trip_t *trip); | ||||
| QList<int> getDivesInTrip(struct dive_trip *trip); | ||||
| QString get_gas_string(struct gasmix gas); | ||||
| QString get_divepoint_gas_string(struct dive *d, const divedatapoint& dp); | ||||
| QString get_taglist_string(struct tag_entry *tag_list); | ||||
|  |  | |||
|  | @ -19,7 +19,7 @@ | |||
| 
 | ||||
| #include "divesite.h" | ||||
| #include "subsurface-string.h" | ||||
| #include "divelist.h" | ||||
| #include "trip.h" | ||||
| #include "device.h" | ||||
| #include "membuffer.h" | ||||
| #include "git-access.h" | ||||
|  |  | |||
|  | @ -9,6 +9,7 @@ | |||
| #include "gettext.h" | ||||
| #include "divesite.h" | ||||
| #include "tag.h" | ||||
| #include "trip.h" | ||||
| #include <stdio.h> | ||||
| 
 | ||||
| void write_attribute(struct membuffer *b, const char *att_name, const char *value, const char *separator) | ||||
|  |  | |||
|  | @ -15,7 +15,7 @@ | |||
| 
 | ||||
| #include "divesite.h" | ||||
| #include "subsurface-string.h" | ||||
| #include "divelist.h" | ||||
| #include "trip.h" | ||||
| #include "device.h" | ||||
| #include "membuffer.h" | ||||
| #include "strndup.h" | ||||
|  |  | |||
|  | @ -12,7 +12,7 @@ | |||
| 
 | ||||
| #include "dive.h" | ||||
| #include "display.h" | ||||
| #include "divelist.h" | ||||
| #include "trip.h" | ||||
| #include "statistics.h" | ||||
| #include "units.h" | ||||
| 
 | ||||
|  |  | |||
|  | @ -6,6 +6,7 @@ | |||
| 
 | ||||
| #include "core/qthelper.h" | ||||
| #include "core/divesite.h" | ||||
| #include "core/trip.h" | ||||
| #include "core/subsurface-string.h" | ||||
| #include "qt-models/tankinfomodel.h" | ||||
| 
 | ||||
|  |  | |||
							
								
								
									
										353
									
								
								core/trip.c
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										353
									
								
								core/trip.c
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,353 @@ | |||
| // SPDX-License-Identifier: GPL-2.0
 | ||||
| 
 | ||||
| #include "trip.h" | ||||
| #include "subsurface-string.h" | ||||
| #include "table.h" | ||||
| 
 | ||||
| struct trip_table trip_table; | ||||
| 
 | ||||
| #ifdef DEBUG_TRIP | ||||
| void dump_trip_list(void) | ||||
| { | ||||
| 	dive_trip_t *trip; | ||||
| 	int i = 0; | ||||
| 	timestamp_t last_time = 0; | ||||
| 
 | ||||
| 	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\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 + 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); | ||||
| 	} | ||||
| 	printf("-----\n"); | ||||
| } | ||||
| #endif | ||||
| 
 | ||||
| /* free resources associated with a trip structure */ | ||||
| void free_trip(dive_trip_t *trip) | ||||
| { | ||||
| 	if (trip) { | ||||
| 		free(trip->location); | ||||
| 		free(trip->notes); | ||||
| 		free(trip->dives.dives); | ||||
| 		free(trip); | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| /* Trip table functions */ | ||||
| static MAKE_GET_IDX(trip_table, struct dive_trip *, trips) | ||||
| static MAKE_GROW_TABLE(trip_table, struct dive_trip *, trips) | ||||
| static MAKE_GET_INSERTION_INDEX(trip_table, struct dive_trip *, trips, trip_less_than) | ||||
| static MAKE_ADD_TO(trip_table, struct dive_trip *, trips) | ||||
| static MAKE_REMOVE_FROM(trip_table, trips) | ||||
| MAKE_SORT(trip_table, struct dive_trip *, trips, comp_trips) | ||||
| MAKE_REMOVE(trip_table, struct dive_trip *, trip) | ||||
| 
 | ||||
| timestamp_t trip_date(const struct dive_trip *trip) | ||||
| { | ||||
| 	if (!trip || trip->dives.nr == 0) | ||||
| 		return 0; | ||||
| 	return trip->dives.dives[0]->when; | ||||
| } | ||||
| 
 | ||||
| timestamp_t trip_enddate(const struct dive_trip *trip) | ||||
| { | ||||
| 	if (!trip || trip->dives.nr == 0) | ||||
| 		return 0; | ||||
| 	return dive_endtime(trip->dives.dives[trip->dives.nr - 1]); | ||||
| } | ||||
| 
 | ||||
| /* check if we have a trip right before / after this dive */ | ||||
| bool is_trip_before_after(const struct dive *dive, bool before) | ||||
| { | ||||
| 	int idx = get_idx_by_uniq_id(dive->id); | ||||
| 	if (before) { | ||||
| 		if (idx > 0 && get_dive(idx - 1)->divetrip) | ||||
| 			return true; | ||||
| 	} else { | ||||
| 		if (idx < dive_table.nr - 1 && get_dive(idx + 1)->divetrip) | ||||
| 			return true; | ||||
| 	} | ||||
| 	return false; | ||||
| } | ||||
| 
 | ||||
| /* Add dive to a trip. Caller is responsible for removing dive
 | ||||
|  * from trip beforehand. */ | ||||
| void add_dive_to_trip(struct dive *dive, dive_trip_t *trip) | ||||
| { | ||||
| 	if (dive->divetrip == trip) | ||||
| 		return; | ||||
| 	if (dive->divetrip) | ||||
| 		fprintf(stderr, "Warning: adding dive to trip that has trip set\n"); | ||||
| 	insert_dive(&trip->dives, dive); | ||||
| 	dive->divetrip = trip; | ||||
| } | ||||
| 
 | ||||
| /* 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 | ||||
|  * for removing the trip, if the trip->dives.nr went to 0. | ||||
|  */ | ||||
| struct dive_trip *unregister_dive_from_trip(struct dive *dive) | ||||
| { | ||||
| 	dive_trip_t *trip = dive->divetrip; | ||||
| 
 | ||||
| 	if (!trip) | ||||
| 		return NULL; | ||||
| 
 | ||||
| 	remove_dive(dive, &trip->dives); | ||||
| 	dive->divetrip = NULL; | ||||
| 	return trip; | ||||
| } | ||||
| 
 | ||||
| static void delete_trip(dive_trip_t *trip, struct trip_table *trip_table_arg) | ||||
| { | ||||
| 	remove_trip(trip, trip_table_arg); | ||||
| 	free_trip(trip); | ||||
| } | ||||
| 
 | ||||
| void remove_dive_from_trip(struct dive *dive, struct trip_table *trip_table_arg) | ||||
| { | ||||
| 	struct dive_trip *trip = unregister_dive_from_trip(dive); | ||||
| 	if (trip && trip->dives.nr == 0) | ||||
| 		delete_trip(trip, trip_table_arg); | ||||
| } | ||||
| 
 | ||||
| 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, struct trip_table *trip_table_arg) | ||||
| { | ||||
| 	int idx = trip_table_get_insertion_index(trip_table_arg, dive_trip); | ||||
| 	add_to_trip_table(trip_table_arg, idx, dive_trip); | ||||
| #ifdef DEBUG_TRIP | ||||
| 	dump_trip_list(); | ||||
| #endif | ||||
| } | ||||
| 
 | ||||
| dive_trip_t *create_trip_from_dive(struct dive *dive) | ||||
| { | ||||
| 	dive_trip_t *trip; | ||||
| 
 | ||||
| 	trip = alloc_trip(); | ||||
| 	trip->location = copy_string(get_dive_location(dive)); | ||||
| 
 | ||||
| 	return trip; | ||||
| } | ||||
| 
 | ||||
| dive_trip_t *create_and_hookup_trip_from_dive(struct dive *dive, struct trip_table *trip_table_arg) | ||||
| { | ||||
| 	dive_trip_t *dive_trip = alloc_trip(); | ||||
| 
 | ||||
| 	dive_trip = create_trip_from_dive(dive); | ||||
| 
 | ||||
| 	add_dive_to_trip(dive, dive_trip); | ||||
| 	insert_trip(dive_trip, trip_table_arg); | ||||
| 	return dive_trip; | ||||
| } | ||||
| 
 | ||||
| /* random threshold: three days without diving -> new trip
 | ||||
|  * this works very well for people who usually dive as part of a trip and don't | ||||
|  * regularly dive at a local facility; this is why trips are an optional feature */ | ||||
| #define TRIP_THRESHOLD 3600 * 24 * 3 | ||||
| 
 | ||||
| /*
 | ||||
|  * 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 | ||||
|  * if a new trip was allocated. | ||||
|  */ | ||||
| dive_trip_t *get_trip_for_new_dive(struct dive *new_dive, bool *allocated) | ||||
| { | ||||
| 	struct dive *d; | ||||
| 	dive_trip_t *trip; | ||||
| 	int i; | ||||
| 
 | ||||
| 	/* Find dive that is within TRIP_THRESHOLD of current dive */ | ||||
| 	for_each_dive(i, d) { | ||||
| 		/* Check if we're past the range of possible dives */ | ||||
| 		if (d->when >= new_dive->when + TRIP_THRESHOLD) | ||||
| 			break; | ||||
| 
 | ||||
| 		if (d->when + TRIP_THRESHOLD >= new_dive->when && d->divetrip) { | ||||
| 			/* Found a dive with trip in the range */ | ||||
| 			*allocated = false; | ||||
| 			return d->divetrip; | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	/* Didn't find a trip -> allocate a new one */ | ||||
| 	trip = create_trip_from_dive(new_dive); | ||||
| 	trip->autogen = true; | ||||
| 	*allocated = true; | ||||
| 	return trip; | ||||
| } | ||||
| 
 | ||||
| /*
 | ||||
|  * Collect dives for auto-grouping. Pass in first dive which should be checked. | ||||
|  * Returns range of dives that should be autogrouped and trip it should be | ||||
|  * associated to. If the returned trip was newly allocated, the last bool | ||||
|  * is set to true. Caller still has to register it in the system. Note | ||||
|  * whereas this looks complicated - it is needed by the undo-system, which | ||||
|  * manually injects the new trips. If there are no dives to be autogrouped, | ||||
|  * return NULL. | ||||
|  */ | ||||
| dive_trip_t *get_dives_to_autogroup(struct dive_table *table, int start, int *from, int *to, bool *allocated) | ||||
| { | ||||
| 	int i; | ||||
| 	struct dive *lastdive = NULL; | ||||
| 
 | ||||
| 	/* Find first dive that should be merged and remember any previous
 | ||||
| 	 * dive that could be merged into. | ||||
| 	 */ | ||||
| 	for (i = start; i < table->nr; i++) { | ||||
| 		struct dive *dive = table->dives[i]; | ||||
| 		dive_trip_t *trip; | ||||
| 
 | ||||
| 		if (dive->divetrip) { | ||||
| 			lastdive = dive; | ||||
| 			continue; | ||||
| 		} | ||||
| 
 | ||||
| 		/* Only consider dives that have not been explicitly removed from
 | ||||
| 		 * a dive trip by the user.  */ | ||||
| 		if (dive->notrip) { | ||||
| 			lastdive = NULL; | ||||
| 			continue; | ||||
| 		} | ||||
| 
 | ||||
| 		/* We found a dive, let's see if we have to allocate a new trip */ | ||||
| 		if (!lastdive || dive->when >= lastdive->when + TRIP_THRESHOLD) { | ||||
| 			/* allocate new trip */ | ||||
| 			trip = create_trip_from_dive(dive); | ||||
| 			trip->autogen = true; | ||||
| 			*allocated = true; | ||||
| 		} else { | ||||
| 			/* use trip of previous dive */ | ||||
| 			trip = lastdive->divetrip; | ||||
| 			*allocated = false; | ||||
| 		} | ||||
| 
 | ||||
| 		// Now, find all dives that will be added to this trip
 | ||||
| 		lastdive = dive; | ||||
| 		*from = i; | ||||
| 		for (*to = *from + 1; *to < table->nr; (*to)++) { | ||||
| 			dive = table->dives[*to]; | ||||
| 			if (dive->divetrip || dive->notrip || | ||||
| 			    dive->when >= lastdive->when + TRIP_THRESHOLD) | ||||
| 				break; | ||||
| 			if (get_dive_location(dive) && !trip->location) | ||||
| 				trip->location = copy_string(get_dive_location(dive)); | ||||
| 			lastdive = dive; | ||||
| 		} | ||||
| 		return trip; | ||||
| 	} | ||||
| 
 | ||||
| 	/* Did not find anyhting - mark as end */ | ||||
| 	return NULL; | ||||
| } | ||||
| 
 | ||||
| void deselect_dives_in_trip(struct dive_trip *trip) | ||||
| { | ||||
| 	if (!trip) | ||||
| 		return; | ||||
| 	for (int i = 0; i < trip->dives.nr; ++i) | ||||
| 		deselect_dive(trip->dives.dives[i]); | ||||
| } | ||||
| 
 | ||||
| void select_dives_in_trip(struct dive_trip *trip) | ||||
| { | ||||
| 	struct dive *dive; | ||||
| 	if (!trip) | ||||
| 		return; | ||||
| 	for (int i = 0; i < trip->dives.nr; ++i) { | ||||
| 		dive = trip->dives.dives[i]; | ||||
| 		if (!dive->hidden_by_filter) | ||||
| 			select_dive(dive); | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| /* Out of two strings, copy the string that is not empty (if any). */ | ||||
| static char *copy_non_empty_string(const char *a, const char *b) | ||||
| { | ||||
| 	return copy_string(empty_string(b) ? a : b); | ||||
| } | ||||
| 
 | ||||
| /* This combines the information of two trips, generating a
 | ||||
|  * new trip. To support undo, we have to preserve the old trips. */ | ||||
| dive_trip_t *combine_trips(struct dive_trip *trip_a, struct dive_trip *trip_b) | ||||
| { | ||||
| 	dive_trip_t *trip; | ||||
| 
 | ||||
| 	trip = alloc_trip(); | ||||
| 	trip->location = copy_non_empty_string(trip_a->location, trip_b->location); | ||||
| 	trip->notes = copy_non_empty_string(trip_a->notes, trip_b->notes); | ||||
| 
 | ||||
| 	return trip; | ||||
| } | ||||
| 
 | ||||
| void clear_trip_table(struct trip_table *table) | ||||
| { | ||||
| 	for (int i = 0; i < table->nr; i++) | ||||
| 		free_trip(table->trips[i]); | ||||
| 	table->nr = 0; | ||||
| } | ||||
| 
 | ||||
| /* Trips are compared according to the first dive in the trip. */ | ||||
| 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; | ||||
| } | ||||
| 
 | ||||
| static bool is_same_day(timestamp_t trip_when, timestamp_t dive_when) | ||||
| { | ||||
| 	static timestamp_t twhen = (timestamp_t) 0; | ||||
| 	static struct tm tmt; | ||||
| 	struct tm tmd; | ||||
| 
 | ||||
| 	utc_mkdate(dive_when, &tmd); | ||||
| 
 | ||||
| 	if (twhen != trip_when) { | ||||
| 		twhen = trip_when; | ||||
| 		utc_mkdate(twhen, &tmt); | ||||
| 	} | ||||
| 
 | ||||
| 	return (tmd.tm_mday == tmt.tm_mday) && (tmd.tm_mon == tmt.tm_mon) && (tmd.tm_year == tmt.tm_year); | ||||
| } | ||||
| 
 | ||||
| bool trip_is_single_day(const struct dive_trip *trip) | ||||
| { | ||||
| 	if (trip->dives.nr <= 1) | ||||
| 		return true; | ||||
| 	return is_same_day(trip->dives.dives[0]->when, | ||||
| 			   trip->dives.dives[trip->dives.nr - 1]->when); | ||||
| } | ||||
| 
 | ||||
| int trip_shown_dives(const struct dive_trip *trip) | ||||
| { | ||||
| 	int res = 0; | ||||
| 	for (int i = 0; i < trip->dives.nr; ++i) { | ||||
| 		if (!trip->dives.dives[i]->hidden_by_filter) | ||||
| 			res++; | ||||
| 	} | ||||
| 	return res; | ||||
| } | ||||
							
								
								
									
										72
									
								
								core/trip.h
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										72
									
								
								core/trip.h
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,72 @@ | |||
| // SPDX-License-Identifier: GPL-2.0
 | ||||
| #ifndef TRIP_H | ||||
| #define TRIP_H | ||||
| 
 | ||||
| #include "divelist.h" | ||||
| 
 | ||||
| #ifdef __cplusplus | ||||
| extern "C" { | ||||
| #endif | ||||
| 
 | ||||
| typedef struct dive_trip | ||||
| { | ||||
| 	char *location; | ||||
| 	char *notes; | ||||
| 	struct dive_table dives; | ||||
| 	/* Used by the io-routines to mark trips that have already been written. */ | ||||
| 	bool saved; | ||||
| 	bool autogen; | ||||
| } dive_trip_t; | ||||
| 
 | ||||
| typedef struct trip_table { | ||||
| 	int nr, allocated; | ||||
| 	struct dive_trip **trips; | ||||
| } trip_table_t; | ||||
| 
 | ||||
| extern void add_dive_to_trip(struct dive *, dive_trip_t *); | ||||
| extern struct dive_trip *unregister_dive_from_trip(struct dive *dive); | ||||
| extern void remove_dive_from_trip(struct dive *dive, struct trip_table *trip_table_arg); | ||||
| 
 | ||||
| extern void insert_trip(dive_trip_t *trip, struct trip_table *trip_table_arg); | ||||
| extern int remove_trip(const dive_trip_t *trip, struct trip_table *trip_table_arg); | ||||
| extern void free_trip(dive_trip_t *trip); | ||||
| extern timestamp_t trip_date(const struct dive_trip *trip); | ||||
| extern timestamp_t trip_enddate(const struct dive_trip *trip); | ||||
| 
 | ||||
| extern bool trip_less_than(const struct dive_trip *a, const struct dive_trip *b); | ||||
| extern int comp_trips(const struct dive_trip *a, const struct dive_trip *b); | ||||
| extern void sort_trip_table(struct trip_table *table); | ||||
| 
 | ||||
| extern dive_trip_t *alloc_trip(void); | ||||
| extern dive_trip_t *create_trip_from_dive(struct dive *dive); | ||||
| extern dive_trip_t *create_and_hookup_trip_from_dive(struct dive *dive, struct trip_table *trip_table_arg); | ||||
| extern dive_trip_t *get_dives_to_autogroup(struct dive_table *table, int start, int *from, int *to, bool *allocated); | ||||
| extern dive_trip_t *get_trip_for_new_dive(struct dive *new_dive, bool *allocated); | ||||
| 
 | ||||
| extern void select_dives_in_trip(struct dive_trip *trip); | ||||
| extern void deselect_dives_in_trip(struct dive_trip *trip); | ||||
| 
 | ||||
| extern dive_trip_t *combine_trips(struct dive_trip *trip_a, struct dive_trip *trip_b); | ||||
| extern bool is_trip_before_after(const struct dive *dive, bool before); | ||||
| extern bool trip_is_single_day(const struct dive_trip *trip); | ||||
| extern int trip_shown_dives(const struct dive_trip *trip); | ||||
| 
 | ||||
| void clear_trip_table(struct trip_table *table); | ||||
| 
 | ||||
| #ifdef DEBUG_TRIP | ||||
| extern void dump_trip_list(void); | ||||
| #endif | ||||
| 
 | ||||
| extern struct trip_table trip_table; | ||||
| #ifdef __cplusplus | ||||
| } | ||||
| 
 | ||||
| /* Make pointers to dive_trip and trip_table "Qt metatypes" so that they can be
 | ||||
|  * passed through QVariants and through QML. See comment in dive.h. */ | ||||
| #include <QObject> | ||||
| Q_DECLARE_METATYPE(struct dive_trip *); | ||||
| Q_DECLARE_METATYPE(trip_table_t *); | ||||
| 
 | ||||
| #endif | ||||
| 
 | ||||
| #endif | ||||
|  | @ -5,6 +5,7 @@ | |||
| #define COMMAND_BASE_H | ||||
| 
 | ||||
| #include "core/divesite.h" | ||||
| #include "core/trip.h" | ||||
| 
 | ||||
| #include <QUndoCommand> | ||||
| #include <QCoreApplication>	// For Q_DECLARE_TR_FUNCTIONS | ||||
|  |  | |||
|  | @ -20,6 +20,7 @@ | |||
| #include <QMessageBox> | ||||
| #include <QHeaderView> | ||||
| #include "core/qthelper.h" | ||||
| #include "core/trip.h" | ||||
| #include "desktop-widgets/command.h" | ||||
| #include "desktop-widgets/divelistview.h" | ||||
| #include "qt-models/divepicturemodel.h" | ||||
|  |  | |||
|  | @ -39,7 +39,7 @@ public: | |||
| 	void rememberSelection(); | ||||
| 	void restoreSelection(); | ||||
| 	void contextMenuEvent(QContextMenuEvent *event); | ||||
| 	QList<dive_trip_t *> selectedTrips(); | ||||
| 	QList<dive_trip *> selectedTrips(); | ||||
| 	static QString lastUsedImageDir(); | ||||
| 	static void updateLastUsedImageDir(const QString &s); | ||||
| public | ||||
|  | @ -78,7 +78,7 @@ private: | |||
| 	QVector<int> initialColumnWidths; | ||||
| 
 | ||||
| 	/* if dive_trip_t is null, there's no problem. */ | ||||
| 	QMultiHash<dive_trip_t *, int> selectedDives; | ||||
| 	QMultiHash<dive_trip *, int> selectedDives; | ||||
| 	void resetModel();	// Call after model changed
 | ||||
| 	void merge_trip(const QModelIndex &a, const int offset); | ||||
| 	void setColumnWidths(); | ||||
|  | @ -86,7 +86,7 @@ private: | |||
| 	void backupExpandedRows(); | ||||
| 	void restoreExpandedRows(); | ||||
| 	int lastVisibleColumn(); | ||||
| 	void selectTrip(dive_trip_t *trip); | ||||
| 	void selectTrip(dive_trip *trip); | ||||
| 	void updateLastImageTimeOffset(int offset); | ||||
| 	int lastImageTimeOffset(); | ||||
| 	void addToTrip(int delta); | ||||
|  |  | |||
|  | @ -12,6 +12,7 @@ | |||
| #include <QPainter> | ||||
| #include "core/qthelper.h" | ||||
| #include "core/divesite.h" | ||||
| #include "core/trip.h" | ||||
| #include "core/import-csv.h" | ||||
| 
 | ||||
| static QString subsurface_mimedata = "subsurface/csvcolumns"; | ||||
|  |  | |||
|  | @ -27,6 +27,7 @@ | |||
| #include "core/planner.h" | ||||
| #include "core/qthelper.h" | ||||
| #include "core/subsurface-string.h" | ||||
| #include "core/trip.h" | ||||
| #include "core/version.h" | ||||
| #include "core/windowtitleupdate.h" | ||||
| 
 | ||||
|  |  | |||
|  | @ -12,6 +12,7 @@ | |||
| #include "mainwindow.h" | ||||
| #include "divelistview.h" | ||||
| #include "command.h" | ||||
| #include "core/trip.h" // TODO: Needed because divesChanged uses a trip parameter -> remove that!
 | ||||
| 
 | ||||
| static const QUrl urlMapWidget = QUrl(QStringLiteral("qrc:/qml/MapWidget.qml")); | ||||
| static const QUrl urlMapWidgetError = QUrl(QStringLiteral("qrc:/qml/MapWidgetError.qml")); | ||||
|  |  | |||
|  | @ -6,7 +6,7 @@ | |||
| #include "desktop-widgets/mainwindow.h" | ||||
| #include "desktop-widgets/command.h" | ||||
| #include "desktop-widgets/usersurvey.h" | ||||
| #include "core/divelist.h" | ||||
| #include "core/trip.h" | ||||
| #include "core/file.h" | ||||
| #include "desktop-widgets/mapwidget.h" | ||||
| #include "desktop-widgets/tab-widgets/maintab.h" | ||||
|  |  | |||
|  | @ -5,6 +5,7 @@ | |||
| #include "core/units.h" | ||||
| #include "core/dive.h" | ||||
| #include "desktop-widgets/command.h" | ||||
| #include "core/trip.h" // TODO: Needed because divesChanged uses a trip parameter -> remove that!
 | ||||
| 
 | ||||
| #include <core/qthelper.h> | ||||
| #include <core/statistics.h> | ||||
|  |  | |||
|  | @ -10,6 +10,7 @@ | |||
| #include "desktop-widgets/mapwidget.h" | ||||
| #include "core/qthelper.h" | ||||
| #include "core/statistics.h" | ||||
| #include "core/trip.h" | ||||
| #include "qt-models/diveplannermodel.h" | ||||
| #include "desktop-widgets/divelistview.h" | ||||
| #include "core/display.h" | ||||
|  |  | |||
|  | @ -91,7 +91,7 @@ private: | |||
| 	bool lastSelectedDive; | ||||
| 	int lastTabSelectedDive; | ||||
| 	int lastTabSelectedDiveTrip; | ||||
| 	dive_trip_t *currentTrip; | ||||
| 	dive_trip *currentTrip; | ||||
| 	QList<TabBase*> extraWidgets; | ||||
| 	void divesEdited(int num); // Opens a warning window if more than one dive was edited
 | ||||
| }; | ||||
|  |  | |||
|  | @ -10,6 +10,7 @@ | |||
| #include "core/qthelper.h" | ||||
| #include "core/file.h" | ||||
| #include "core/divesite.h" | ||||
| #include "core/trip.h" | ||||
| #include "core/save-html.h" | ||||
| #include <stdio.h> | ||||
| #include "git2.h" | ||||
|  |  | |||
|  | @ -24,7 +24,7 @@ | |||
| #include "qt-models/gpslistmodel.h" | ||||
| #include "qt-models/completionmodels.h" | ||||
| #include "qt-models/messagehandlermodel.h" | ||||
| #include "core/divelist.h" | ||||
| #include "qt-models/tankinfomodel.h" | ||||
| #include "core/device.h" | ||||
| #include "core/file.h" | ||||
| #include "core/qthelper.h" | ||||
|  | @ -32,7 +32,6 @@ | |||
| #include "core/git-access.h" | ||||
| #include "core/cloudstorage.h" | ||||
| #include "core/membuffer.h" | ||||
| #include "qt-models/tankinfomodel.h" | ||||
| #include "core/downloadfromdcthread.h" | ||||
| #include "core/subsurface-string.h" | ||||
| #include "core/pref.h" | ||||
|  | @ -42,6 +41,7 @@ | |||
| #include "core/settings/qPrefTechnicalDetails.h" | ||||
| #include "core/settings/qPrefPartialPressureGas.h" | ||||
| #include "core/settings/qPrefUnit.h" | ||||
| #include "core/trip.h" | ||||
| 
 | ||||
| QMLManager *QMLManager::m_instance = NULL; | ||||
| bool noCloudToCloud = false; | ||||
|  |  | |||
|  | @ -73,6 +73,7 @@ SOURCES += ../../subsurface-mobile-main.cpp \ | |||
| 	../../core/tag.c \ | ||||
| 	../../core/taxonomy.c \ | ||||
| 	../../core/time.c \ | ||||
| 	../../core/trip.c \ | ||||
| 	../../core/uemis.c \ | ||||
| 	../../core/btdiscovery.cpp \ | ||||
| 	../../core/connectionlistmodel.cpp \ | ||||
|  |  | |||
|  | @ -7,6 +7,7 @@ | |||
| #include "qt-models/diveplannermodel.h" | ||||
| #include "core/gettextfromc.h" | ||||
| #include "core/subsurface-qt/DiveListNotifier.h" | ||||
| #include "core/trip.h" // TODO: Needed because cylindersReset uses a trip parameter -> remove that!
 | ||||
| 
 | ||||
| CylindersModel::CylindersModel(QObject *parent) : | ||||
| 	CleanerTableModel(parent), | ||||
|  |  | |||
|  | @ -1,6 +1,7 @@ | |||
| // SPDX-License-Identifier: GPL-2.0
 | ||||
| #include "qt-models/divelistmodel.h" | ||||
| #include "core/qthelper.h" | ||||
| #include "core/trip.h" | ||||
| #include "core/settings/qPrefGeneral.h" | ||||
| #include <QDateTime> | ||||
| 
 | ||||
|  |  | |||
|  | @ -3,7 +3,7 @@ | |||
| #include "qt-models/filtermodels.h" | ||||
| #include "core/gettextfromc.h" | ||||
| #include "core/metrics.h" | ||||
| #include "core/divelist.h" | ||||
| #include "core/trip.h" | ||||
| #include "core/qthelper.h" | ||||
| #include "core/subsurface-string.h" | ||||
| #include "core/tag.h" | ||||
|  |  | |||
|  | @ -4,6 +4,7 @@ | |||
| #include "core/display.h" | ||||
| #include "core/qthelper.h" | ||||
| #include "core/divesite.h" | ||||
| #include "core/trip.h" | ||||
| #include "core/subsurface-string.h" | ||||
| #include "core/subsurface-qt/DiveListNotifier.h" | ||||
| #include "qt-models/divetripmodel.h" | ||||
|  |  | |||
|  | @ -6,6 +6,7 @@ | |||
| #include "core/qthelper.h" | ||||
| #include "core/subsurface-qt/DiveListNotifier.h" | ||||
| #include "qt-models/weightsysteminfomodel.h" | ||||
| #include "core/trip.h" // TODO: Needed because weightsystemsReset uses a trip parameter -> remove that!
 | ||||
| 
 | ||||
| WeightModel::WeightModel(QObject *parent) : CleanerTableModel(parent), | ||||
| 	changed(false), | ||||
|  |  | |||
|  | @ -1,7 +1,7 @@ | |||
| // SPDX-License-Identifier: GPL-2.0
 | ||||
| #include "testAirPressure.h" | ||||
| #include "core/divesite.h" | ||||
| #include "core/divelist.h" | ||||
| #include "core/trip.h" | ||||
| #include "core/file.h" | ||||
| #include "core/dive.h" | ||||
| #include <QString> | ||||
|  |  | |||
|  | @ -2,6 +2,7 @@ | |||
| #include "testdivesiteduplication.h" | ||||
| #include "core/dive.h" | ||||
| #include "core/divesite.h" | ||||
| #include "core/trip.h" | ||||
| #include "core/file.h" | ||||
| 
 | ||||
| void TestDiveSiteDuplication::testReadV2() | ||||
|  |  | |||
|  | @ -3,12 +3,12 @@ | |||
| #include "git2.h" | ||||
| 
 | ||||
| #include "core/divesite.h" | ||||
| #include "core/divelist.h" | ||||
| #include "core/file.h" | ||||
| #include "core/qthelper.h" | ||||
| #include "core/subsurfacestartup.h" | ||||
| #include "core/settings/qPrefProxy.h" | ||||
| #include "core/settings/qPrefCloudStorage.h" | ||||
| #include "core/trip.h" | ||||
| 
 | ||||
| #include <QDir> | ||||
| #include <QTextStream> | ||||
|  |  | |||
|  | @ -1,8 +1,8 @@ | |||
| // SPDX-License-Identifier: GPL-2.0
 | ||||
| #include "testmerge.h" | ||||
| #include "core/divesite.h" | ||||
| #include "core/divelist.h" | ||||
| #include "core/file.h" | ||||
| #include "core/trip.h" | ||||
| #include <QTextStream> | ||||
| 
 | ||||
| void TestMerge::initTestCase() | ||||
|  |  | |||
|  | @ -1,7 +1,7 @@ | |||
| // SPDX-License-Identifier: GPL-2.0
 | ||||
| #include "testparse.h" | ||||
| #include "core/divesite.h" | ||||
| #include "core/divelist.h" | ||||
| #include "core/trip.h" | ||||
| #include "core/file.h" | ||||
| #include "core/import-csv.h" | ||||
| #include "core/parse.h" | ||||
|  |  | |||
|  | @ -1,7 +1,7 @@ | |||
| // SPDX-License-Identifier: GPL-2.0
 | ||||
| #include "testparseperformance.h" | ||||
| #include "core/divesite.h" | ||||
| #include "core/divelist.h" | ||||
| #include "core/trip.h" | ||||
| #include "core/file.h" | ||||
| #include "core/git-access.h" | ||||
| #include "core/settings/qPrefProxy.h" | ||||
|  |  | |||
|  | @ -1,7 +1,7 @@ | |||
| // SPDX-License-Identifier: GPL-2.0
 | ||||
| #include "testpicture.h" | ||||
| #include "core/divesite.h" | ||||
| #include "core/divelist.h" | ||||
| #include "core/trip.h" | ||||
| #include "core/file.h" | ||||
| #include <QString> | ||||
| #include <core/qthelper.h> | ||||
|  |  | |||
|  | @ -1,6 +1,7 @@ | |||
| // SPDX-License-Identifier: GPL-2.0
 | ||||
| #include "testprofile.h" | ||||
| #include "core/divesite.h" | ||||
| #include "core/trip.h" | ||||
| #include "core/file.h" | ||||
| 
 | ||||
| void TestProfile::testRedCeiling() | ||||
|  |  | |||
|  | @ -1,7 +1,7 @@ | |||
| // SPDX-License-Identifier: GPL-2.0
 | ||||
| #include "testrenumber.h" | ||||
| #include "core/divesite.h" | ||||
| #include "core/divelist.h" | ||||
| #include "core/trip.h" | ||||
| #include "core/file.h" | ||||
| #include <QTextStream> | ||||
| 
 | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue