core: turn dive-trip location and notes into std::string

Simpler memory management.

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
This commit is contained in:
Berthold Stoeger 2024-05-31 17:15:47 +02:00 committed by bstoeger
parent 2fd226964c
commit 3ee41328f9
29 changed files with 157 additions and 179 deletions

View file

@ -206,7 +206,6 @@ HEADERS += \
core/extradata.h \
core/git-access.h \
core/globals.h \
core/owning_ptrs.h \
core/pref.h \
core/profile.h \
core/qthelper.h \

View file

@ -7,7 +7,6 @@
#include "core/divesite.h"
#include "core/trip.h"
#include "core/dive.h"
#include "core/owning_ptrs.h"
#include <QUndoCommand>
#include <QCoreApplication> // For Q_DECLARE_TR_FUNCTIONS
@ -106,9 +105,8 @@
// 1) Dive 2 was deleted with the "add dive 2" command, because that was the owner.
// 2) Dive 1 was not deleted, because it is owned by the backend.
//
// To take ownership of dives/trips, the OnwingDivePtr and OwningTripPtr types are used. These
// are simply derived from std::unique_ptr and therefore use well-established semantics.
// Expressed in C-terms: std::unique_ptr<T> is exactly the same as T* with the following
// To take ownership of dives/trips, std::unique_ptr<>s are used.
// Expressed in C-terms: std::unique_ptr<T> is the same as T* with the following
// twists:
// 1) default-initialized to NULL.
// 2) if it goes out of scope (local scope or containing object destroyed), it does:
@ -122,8 +120,8 @@
// move-semantics and Qt's containers are incompatible, owing to COW semantics.
//
// Usage:
// OwningDivePtr dPtr; // Initialize to null-state: not owning any dive.
// OwningDivePtr dPtr(dive); // Take ownership of dive (which is of type struct dive *).
// std::unique_ptr<dive> dPtr; // Initialize to null-state: not owning any dive.
// std::unique_ptr<dive> dPtr(dive); // Take ownership of dive (which is of type struct dive *).
// // If dPtr goes out of scope, the dive will be freed with free_dive().
// struct dive *d = dPtr.release(); // Give up ownership of dive. dPtr is reset to null.
// struct dive *d = d.get(); // Get pointer dive, but don't release ownership.
@ -131,10 +129,10 @@
// dPtr.reset(); // Delete currently owned dive and reset to null.
// dPtr2 = dPtr1; // Fails to compile.
// dPtr2 = std::move(dPtr1); // dPtr2 takes ownership, dPtr1 is reset to null.
// OwningDivePtr fun();
// std::unique_ptr<dive> fun();
// dPtr1 = fun(); // Compiles. Simply put: the compiler knows that the result of fun() will
// // be trashed and therefore can be moved-from.
// std::vector<OwningDivePtr> v: // Define an empty vector of owning pointers.
// std::vector<std::unique_ptr<dive>> v: // Define an empty vector of owning pointers.
// v.emplace_back(dive); // Take ownership of dive and add at end of vector
// // If the vector goes out of scope, all dives will be freed with free_dive().
// v.clear(v); // Reset the vector to zero length. If the elements weren't release()d,

View file

@ -25,7 +25,7 @@ static void remove_trip_from_backend(dive_trip *trip)
// If the trip the dive belongs to becomes empty, it is removed and added to the tripsToAdd vector.
// It is crucial that dives are added in reverse order of deletion, so that the indices are correctly
// set and that the trips are added before they are used!
DiveToAdd DiveListBase::removeDive(struct dive *d, std::vector<OwningTripPtr> &tripsToAdd)
DiveToAdd DiveListBase::removeDive(struct dive *d, std::vector<std::unique_ptr<dive_trip>> &tripsToAdd)
{
// If the dive was the current dive, reset the current dive. The calling
// command is responsible of finding a new dive.
@ -124,7 +124,7 @@ void processByTrip(std::vector<std::pair<dive_trip *, dive *>> &dives, Function
DivesAndTripsToAdd DiveListBase::removeDives(DivesAndSitesToRemove &divesAndSitesToDelete)
{
std::vector<DiveToAdd> divesToAdd;
std::vector<OwningTripPtr> tripsToAdd;
std::vector<std::unique_ptr<dive_trip>> tripsToAdd;
std::vector<std::unique_ptr<dive_site>> sitesToAdd;
divesToAdd.reserve(divesAndSitesToDelete.dives.size());
sitesToAdd.reserve(divesAndSitesToDelete.sites.size());
@ -159,7 +159,7 @@ DivesAndTripsToAdd DiveListBase::removeDives(DivesAndSitesToRemove &divesAndSite
processByTrip(dives, [&](dive_trip *trip, const QVector<dive *> &divesInTrip) {
// Check if this trip is supposed to be deleted, by checking if it was marked as "add it".
bool deleteTrip = trip &&
std::find_if(tripsToAdd.begin(), tripsToAdd.end(), [trip](const OwningTripPtr &ptr)
std::find_if(tripsToAdd.begin(), tripsToAdd.end(), [trip](const std::unique_ptr<dive_trip> &ptr)
{ return ptr.get() == trip; }) != tripsToAdd.end();
emit diveListNotifier.divesDeleted(trip, deleteTrip, divesInTrip);
});
@ -209,7 +209,7 @@ DivesAndSitesToRemove DiveListBase::addDives(DivesAndTripsToAdd &toAdd)
// Remember the pointers so that we can later check if a trip was newly added
std::vector<dive_trip *> addedTrips;
addedTrips.reserve(toAdd.trips.size());
for (OwningTripPtr &trip: toAdd.trips) {
for (std::unique_ptr<dive_trip> &trip: toAdd.trips) {
addedTrips.push_back(trip.get());
insert_trip(trip.release(), divelog.trips.get()); // Return ownership to backend
}
@ -260,14 +260,14 @@ static void renumberDives(QVector<QPair<dive *, int>> &divesToRenumber)
// passed-in structure. This means that calling the function twice on the same
// object is a no-op concerning the dive. If the old trip was deleted from the
// core, an owning pointer to the removed trip is returned, otherwise a null pointer.
static OwningTripPtr moveDiveToTrip(DiveToTrip &diveToTrip)
static std::unique_ptr<dive_trip> moveDiveToTrip(DiveToTrip &diveToTrip)
{
// Firstly, check if we move to the same trip and bail if this is a no-op.
if (diveToTrip.trip == diveToTrip.dive->divetrip)
return {};
// Remove from old trip
OwningTripPtr res;
std::unique_ptr<dive_trip> res;
// Remove dive from trip - if this is the last dive in the trip, remove the whole trip.
dive_trip *trip = unregister_dive_from_trip(diveToTrip.dive);
@ -298,7 +298,7 @@ static void moveDivesBetweenTrips(DivesToTrip &dives)
createdTrips.reserve(dives.tripsToAdd.size());
// First, bring back the trip(s)
for (OwningTripPtr &trip: dives.tripsToAdd) {
for (std::unique_ptr<dive_trip> &trip: dives.tripsToAdd) {
dive_trip *t = trip.release(); // Give up ownership
createdTrips.push_back(t);
insert_trip(t, divelog.trips.get()); // Return ownership to backend
@ -306,7 +306,7 @@ static void moveDivesBetweenTrips(DivesToTrip &dives)
dives.tripsToAdd.clear();
for (DiveToTrip &dive: dives.divesToMove) {
OwningTripPtr tripToAdd = moveDiveToTrip(dive);
std::unique_ptr<dive_trip> tripToAdd = moveDiveToTrip(dive);
// register trips that we'll have to readd
if (tripToAdd)
dives.tripsToAdd.push_back(std::move(tripToAdd));
@ -350,7 +350,7 @@ static void moveDivesBetweenTrips(DivesToTrip &dives)
std::find_if(divesMoved.begin() + j, divesMoved.end(), // Is this the last occurence of "from"?
[from](const DiveMoved &entry) { return entry.from == from; }) == divesMoved.end() &&
std::find_if(dives.tripsToAdd.begin(), dives.tripsToAdd.end(), // Is "from" in tripsToAdd?
[from](const OwningTripPtr &trip) { return trip.get() == from; }) != dives.tripsToAdd.end();
[from](const std::unique_ptr<dive_trip> &trip) { return trip.get() == from; }) != dives.tripsToAdd.end();
// Check if the to-trip has to be created. For this purpose, we saved an array of trips to be created.
bool createTo = false;
if (to) {
@ -417,7 +417,7 @@ AddDive::AddDive(dive *d, bool autogroup, bool newNumber)
// on dive-addition.
// If we alloc a new-trip for autogrouping, get an owning pointer to it.
OwningTripPtr allocTrip;
std::unique_ptr<dive_trip> allocTrip;
dive_trip *trip = divePtr->divetrip;
dive_site *site = divePtr->dive_site;
// We have to delete the pointers to trip and site, because this would prevent the core from adding to the

View file

@ -23,7 +23,7 @@ struct DiveToAdd {
// Multiple trips, dives and dive sites that have to be added for a command
struct DivesAndTripsToAdd {
std::vector<DiveToAdd> dives;
std::vector<OwningTripPtr> trips;
std::vector<std::unique_ptr<dive_trip>> trips;
std::vector<std::unique_ptr<dive_site>> sites;
};
@ -48,7 +48,7 @@ struct DiveToTrip
struct DivesToTrip
{
std::vector<DiveToTrip> divesToMove; // If dive_trip is null, remove from trip
std::vector<OwningTripPtr> tripsToAdd;
std::vector<std::unique_ptr<dive_trip>> tripsToAdd;
};
// All divelist commands derive from a common base class. It keeps track
@ -58,7 +58,7 @@ struct DivesToTrip
class DiveListBase : public Base {
protected:
// These are helper functions to add / remove dive from the C-core structures.
DiveToAdd removeDive(struct dive *d, std::vector<OwningTripPtr> &tripsToAdd);
DiveToAdd removeDive(struct dive *d, std::vector<std::unique_ptr<dive_trip>> &tripsToAdd);
dive *addDive(DiveToAdd &d);
DivesAndTripsToAdd removeDives(DivesAndSitesToRemove &divesAndSitesToDelete);
DivesAndSitesToRemove addDives(DivesAndTripsToAdd &toAdd);
@ -133,7 +133,7 @@ private:
// For redo
DivesAndSitesToRemove divesToDelete;
std::vector<OwningTripPtr> tripsToAdd;
std::vector<std::unique_ptr<dive_trip>> tripsToAdd;
DivesAndTripsToAdd divesToAdd;
};

View file

@ -41,13 +41,12 @@ void EditTripBase::redo()
// ***** Location *****
void EditTripLocation::set(dive_trip *t, const QString &s) const
{
free(t->location);
t->location = copy_qstring(s);
t->location = s.toStdString();
}
QString EditTripLocation::data(dive_trip *t) const
{
return QString(t->location);
return QString::fromStdString(t->location);
}
QString EditTripLocation::fieldName() const
@ -63,13 +62,12 @@ TripField EditTripLocation::fieldId() const
// ***** Notes *****
void EditTripNotes::set(dive_trip *t, const QString &s) const
{
free(t->notes);
t->notes = copy_qstring(s);
t->notes = s.toStdString();
}
QString EditTripNotes::data(dive_trip *t) const
{
return QString(t->notes);
return QString::fromStdString(t->notes);
}
QString EditTripNotes::fieldName() const

View file

@ -30,7 +30,7 @@ protected:
void redo() override;
// Get and set functions to be overriden by sub-classes.
virtual void set(struct dive_trip *t, const QString &) const = 0;
virtual void set(dive_trip *t, const QString &) const = 0;
virtual QString data(struct dive_trip *t) const = 0;
virtual QString fieldName() const = 0; // Name of the field, used to create the undo menu-entry
virtual TripField fieldId() const = 0;

View file

@ -131,7 +131,6 @@ set(SUBSURFACE_CORE_LIB_SRCS
metrics.cpp
metrics.h
ostctools.cpp
owning_ptrs.h
parse-gpx.cpp
parse-xml.cpp
parse.cpp

View file

@ -1752,7 +1752,7 @@ static void merge_temperatures(struct dive *res, const struct dive *a, const str
*/
static struct dive_trip *get_preferred_trip(const struct dive *a, const struct dive *b)
{
dive_trip_t *atrip, *btrip;
dive_trip *atrip, *btrip;
/* If only one dive has a trip, choose that */
atrip = a->divetrip;
@ -1769,13 +1769,13 @@ static struct dive_trip *get_preferred_trip(const struct dive *a, const struct d
return atrip;
/* Otherwise, look at the trip data and pick the "better" one */
if (!atrip->location)
if (atrip->location.empty())
return btrip;
if (!btrip->location)
if (btrip->location.empty())
return atrip;
if (!atrip->notes)
if (atrip->notes.empty())
return btrip;
if (!btrip->notes)
if (btrip->notes.empty())
return atrip;
/*

View file

@ -693,7 +693,7 @@ void insert_dive(struct dive_table *table, struct dive *d)
static void autogroup_dives(struct dive_table *table, struct trip_table *trip_table_arg)
{
int from, to;
dive_trip_t *trip;
dive_trip *trip;
int i, j;
bool alloc;
@ -1003,10 +1003,10 @@ void add_imported_dives(struct divelog *import_log, int flags)
* Returns true if trip was merged. In this case, the trip will be
* freed.
*/
bool try_to_merge_trip(struct dive_trip *trip_import, struct dive_table *import_table, bool prefer_imported,
/* output parameters: */
struct dive_table *dives_to_add, struct dive_table *dives_to_remove,
bool *sequence_changed, int *start_renumbering_at)
static bool try_to_merge_trip(dive_trip *trip_import, struct dive_table *import_table, bool prefer_imported,
/* output parameters: */
struct dive_table *dives_to_add, struct dive_table *dives_to_remove,
bool *sequence_changed, int *start_renumbering_at)
{
int i;
struct dive_trip *trip_old;
@ -1066,7 +1066,7 @@ void process_imported_dives(struct divelog *import_log, int flags,
device_table &devices_to_add)
{
int i, j, nr, start_renumbering_at = 0;
struct dive_trip *trip_import, *new_trip;
dive_trip *new_trip;
bool sequence_changed = false;
bool new_dive_has_number = false;
bool last_old_dive_is_numbered;
@ -1141,7 +1141,7 @@ void process_imported_dives(struct divelog *import_log, int flags,
* will be imported so do a simple n*m loop until someone complains.
*/
for (i = 0; i < import_log->trips->nr; i++) {
trip_import = import_log->trips->trips[i];
dive_trip *trip_import = import_log->trips->trips[i];
if ((flags & IMPORT_MERGE_ALL_TRIPS) || trip_import->autogen) {
if (try_to_merge_trip(trip_import, import_log->dives.get(), flags & IMPORT_PREFER_IMPORTED, dives_to_add, dives_to_remove,
&sequence_changed, &start_renumbering_at))

View file

@ -837,7 +837,7 @@ static bool has_locations(const filter_constraint &c, const struct dive *d)
{
QStringList diveLocations;
if (d->divetrip)
diveLocations.push_back(QString(d->divetrip->location).trimmed());
diveLocations.push_back(QString::fromStdString(d->divetrip->location).trimmed());
if (d->dive_site)
diveLocations.push_back(QString::fromStdString(d->dive_site->name).trimmed());

View file

@ -139,7 +139,7 @@ static std::vector<QString> getWords(const dive *d)
}
// TODO: We should index trips separately!
if (d->divetrip)
tokenize(d->divetrip->location, res);
tokenize(QString::fromStdString(d->divetrip->location), res);
return res;
}

View file

@ -38,7 +38,7 @@ struct git_parser_state {
git_repository *repo = nullptr;
struct divecomputer *active_dc = nullptr;
std::unique_ptr<dive> active_dive;
dive_trip_t *active_trip = nullptr;
std::unique_ptr<dive_trip> active_trip;
std::string fulltext_mode;
std::string fulltext_query;
std::string filter_constraint_type;
@ -889,10 +889,10 @@ static void parse_trip_time(char *, struct git_parser_state *)
{ }
static void parse_trip_location(char *, struct git_parser_state *state)
{ state->active_trip->location = get_first_converted_string_c(state); }
{ state->active_trip->location = get_first_converted_string(state); }
static void parse_trip_notes(char *, struct git_parser_state *state)
{ state->active_trip->notes = get_first_converted_string_c(state); }
{ state->active_trip->notes = get_first_converted_string(state); }
static void parse_settings_autogroup(char *, struct git_parser_state *state)
{
@ -1381,12 +1381,10 @@ static void for_each_line(git_blob *blob, line_fn_t *fn, struct git_parser_state
static void finish_active_trip(struct git_parser_state *state)
{
dive_trip_t *trip = state->active_trip;
auto &trip = state->active_trip;
if (trip) {
state->active_trip = NULL;
insert_trip(trip, state->log->trips.get());
}
if (trip)
insert_trip(trip.release(), state->log->trips.get());
}
static void finish_active_dive(struct git_parser_state *state)
@ -1403,7 +1401,7 @@ static void create_new_dive(timestamp_t when, struct git_parser_state *state)
state->active_dive->when = when;
if (state->active_trip)
add_dive_to_trip(state->active_dive.get(), state->active_trip);
add_dive_to_trip(state->active_dive.get(), state->active_trip.get());
}
static bool validate_date(int yyyy, int mm, int dd)
@ -1433,7 +1431,7 @@ static int dive_trip_directory(const char *root, const char *name, struct git_pa
if (!validate_date(yyyy, mm, dd))
return GIT_WALK_SKIP;
finish_active_trip(state);
state->active_trip = alloc_trip();
state->active_trip = std::make_unique<dive_trip>();
return GIT_WALK_OK;
}
@ -1785,7 +1783,7 @@ static int parse_filter_preset(struct git_parser_state *state, const git_tree_en
static int walk_tree_file(const char *root, const git_tree_entry *entry, struct git_parser_state *state)
{
auto &dive = state->active_dive;
dive_trip_t *trip = state->active_trip;
auto &trip = state->active_trip;
const char *name = git_tree_entry_name(entry);
if (verbose > 1)
report_info("git load handling file %s\n", name);
@ -1815,7 +1813,7 @@ static int walk_tree_file(const char *root, const git_tree_entry *entry, struct
return parse_settings_entry(state, entry);
break;
}
report_error("Unknown file %s%s (%p %p)", root, name, dive.get(), trip);
report_error("Unknown file %s%s (%p %p)", root, name, dive.get(), trip.get());
return GIT_WALK_SKIP;
}

View file

@ -13,7 +13,6 @@
#include "file.h"
#include "format.h"
#include "libdivecomputer.h"
#include "owning_ptrs.h"
/*
* Fills a device_data_t structure with known dc data and a descriptor.

View file

@ -9,16 +9,4 @@
#include <memory>
#include <cstdlib>
struct dive_trip;
void free_trip(struct dive_trip *);
// Classes used to automatically call the appropriate free_*() function for owning pointers that go out of scope.
struct TripDeleter {
void operator()(dive_trip *t) { free_trip(t); }
};
// Owning pointers to dive, dive_trip, dive_site and event objects.
using OwningTripPtr = std::unique_ptr<dive_trip, TripDeleter>;
#endif

View file

@ -1385,13 +1385,13 @@ static void try_to_fill_dive(struct dive *dive, const char *name, char *buf, str
}
/* We're in the top-level trip xml. Try to convert whatever value to a trip value */
static void try_to_fill_trip(dive_trip_t *dive_trip, const char *name, char *buf, struct parser_state *state)
static void try_to_fill_trip(dive_trip *dive_trip, const char *name, char *buf, struct parser_state *state)
{
start_match("trip", name, buf);
if (MATCH("location", utf8_string, &dive_trip->location))
if (MATCH("location", utf8_string_std, &dive_trip->location))
return;
if (MATCH("notes", utf8_string, &dive_trip->notes))
if (MATCH("notes", utf8_string_std, &dive_trip->notes))
return;
nonmatch("trip", name, buf);
@ -1528,7 +1528,7 @@ static bool entry(const char *name, char *buf, struct parser_state *state)
return true;
}
if (state->cur_trip) {
try_to_fill_trip(state->cur_trip, name, buf, state);
try_to_fill_trip(state->cur_trip.get(), name, buf, state);
return true;
}
return true;

View file

@ -19,14 +19,8 @@
#include "device.h"
#include "gettext.h"
parser_state::parser_state()
{
}
parser_state::~parser_state()
{
free_trip(cur_trip);
}
parser_state::parser_state() = default;
parser_state::~parser_state() = default;
/*
* If we don't have an explicit dive computer,
@ -275,7 +269,7 @@ void dive_end(struct parser_state *state)
return;
if (is_dive(state)) {
if (state->cur_trip)
add_dive_to_trip(state->cur_dive.get(), state->cur_trip);
add_dive_to_trip(state->cur_dive.get(), state->cur_trip.get());
record_dive_to_table(state->cur_dive.release(), state->log->dives.get());
}
state->cur_dive.reset();
@ -289,7 +283,7 @@ void trip_start(struct parser_state *state)
if (state->cur_trip)
return;
dive_end(state);
state->cur_trip = alloc_trip();
state->cur_trip = std::make_unique<dive_trip>();
memset(&state->cur_tm, 0, sizeof(state->cur_tm));
}
@ -297,8 +291,7 @@ void trip_end(struct parser_state *state)
{
if (!state->cur_trip)
return;
insert_trip(state->cur_trip, state->log->trips.get());
state->cur_trip = NULL;
insert_trip(state->cur_trip.release(), state->log->trips.get());
}
void picture_start(struct parser_state *state)

View file

@ -59,7 +59,7 @@ struct parser_state {
std::unique_ptr<dive> cur_dive; /* owning */
std::unique_ptr<dive_site> cur_dive_site; /* owning */
location_t cur_location;
struct dive_trip *cur_trip = nullptr; /* owning */
std::unique_ptr<dive_trip> cur_trip; /* owning */
struct sample *cur_sample = nullptr; /* non-owning */
struct picture cur_picture; /* owning */
std::unique_ptr<filter_preset> cur_filter; /* owning */

View file

@ -706,11 +706,12 @@ static int save_one_dive(git_repository *repo, struct dir *tree, struct dive *di
* similar.
*/
#define MAXTRIPNAME 15
static void create_trip_name(dive_trip_t *trip, struct membuffer *name, struct tm *tm)
static void create_trip_name(dive_trip *trip, struct membuffer *name, struct tm *tm)
{
put_format(name, "%02u-", tm->tm_mday);
if (trip->location) {
char ascii_loc[MAXTRIPNAME+1], *p = trip->location;
if (!trip->location.empty()) {
char ascii_loc[MAXTRIPNAME+1];
const char *p = trip->location.c_str();
int i;
for (i = 0; i < MAXTRIPNAME; ) {
@ -740,7 +741,7 @@ static void create_trip_name(dive_trip_t *trip, struct membuffer *name, struct t
put_string(name, "trip");
}
static int save_trip_description(git_repository *repo, struct dir *dir, dive_trip_t *trip, struct tm *tm)
static int save_trip_description(git_repository *repo, struct dir *dir, dive_trip *trip, struct tm *tm)
{
int ret;
git_oid blob_id;
@ -751,8 +752,8 @@ static int save_trip_description(git_repository *repo, struct dir *dir, dive_tri
put_format(&desc, "time %02u:%02u:%02u\n",
tm->tm_hour, tm->tm_min, tm->tm_sec);
show_utf8(&desc, "location ", trip->location, "\n");
show_utf8(&desc, "notes ", trip->notes, "\n");
show_utf8(&desc, "location ", trip->location.c_str(), "\n");
show_utf8(&desc, "notes ", trip->notes.c_str(), "\n");
ret = git_blob_create_frombuffer(&blob_id, repo, desc.buffer, desc.len);
if (ret)
@ -779,7 +780,7 @@ static void verify_shared_date(timestamp_t when, struct tm *tm)
#define MIN_TIMESTAMP (0)
#define MAX_TIMESTAMP (0x7fffffffffffffff)
static int save_one_trip(git_repository *repo, struct dir *tree, dive_trip_t *trip, struct tm *tm, bool cached_ok)
static int save_one_trip(git_repository *repo, struct dir *tree, dive_trip *trip, struct tm *tm, bool cached_ok)
{
int i;
struct dive *dive;
@ -982,7 +983,7 @@ static int create_git_tree(git_repository *repo, struct dir *root, bool select_o
{
int i;
struct dive *dive;
dive_trip_t *trip;
dive_trip *trip;
git_storage_update_progress(translate("gettextFromC", "Start saving data"));
save_settings(repo, root);
@ -1104,7 +1105,7 @@ static void create_commit_message(struct membuffer *msg, bool create_empty)
} else if (!changes_made.empty()) {
put_format(msg, "Changes made: \n\n%s\n", changes_made.c_str());
} else if (dive) {
dive_trip_t *trip = dive->divetrip;
dive_trip *trip = dive->divetrip;
std::string location = get_dive_location(dive);
if (location.empty())
location = "no location";
@ -1114,8 +1115,8 @@ static void create_commit_message(struct membuffer *msg, bool create_empty)
nr = dive->number;
put_format(msg, "dive %d: %s", nr, location.c_str());
if (trip && !empty_string(trip->location) && location != trip->location)
put_format(msg, " (%s)", trip->location);
if (trip && !trip->location.empty() && location != trip->location)
put_format(msg, " (%s)", trip->location.c_str());
put_format(msg, "\n");
for (auto &dc: dive->dcs) {
if (!dc.model.empty()) {

View file

@ -405,7 +405,7 @@ static void write_no_trip(struct membuffer *b, int *dive_no, bool selected_only,
put_format(b, "]}\n\n");
}
static void write_trip(struct membuffer *b, dive_trip_t *trip, int *dive_no, bool selected_only, const char *photos_dir, const bool list_only, char *sep)
static void write_trip(struct membuffer *b, dive_trip *trip, int *dive_no, bool selected_only, const char *photos_dir, const bool list_only, char *sep)
{
const struct dive *dive;
const char *separator = "";
@ -421,7 +421,7 @@ static void write_trip(struct membuffer *b, dive_trip_t *trip, int *dive_no, boo
found_sel_dive = 1;
put_format(b, "%c {", *sep);
(*sep) = ',';
write_attribute(b, "name", trip->location, ", ");
write_attribute(b, "name", trip->location.c_str(), ", ");
put_format(b, "\"dives\":[");
}
put_string(b, separator);
@ -438,7 +438,7 @@ static void write_trips(struct membuffer *b, const char *photos_dir, bool select
{
int i, dive_no = 0;
const struct dive *dive;
dive_trip_t *trip;
dive_trip *trip;
char sep_ = ' ';
char *sep = &sep_;

View file

@ -543,16 +543,16 @@ int save_dive(FILE *f, struct dive *dive, bool anonymize)
return 0;
}
static void save_trip(struct membuffer *b, dive_trip_t *trip, bool anonymize)
static void save_trip(struct membuffer *b, dive_trip *trip, bool anonymize)
{
int i;
struct dive *dive;
put_format(b, "<trip");
show_date(b, trip_date(trip));
show_utf8(b, trip->location, " location=\'", "\'", 1);
show_utf8(b, trip->location.c_str(), " location=\'", "\'", 1);
put_format(b, ">\n");
show_utf8(b, trip->notes, "<notes>", "</notes>\n", 0);
show_utf8(b, trip->notes.c_str(), "<notes>", "</notes>\n", 0);
/*
* Incredibly cheesy: we want to save the dives sorted, and they
@ -642,7 +642,7 @@ static void save_dives_buffer(struct membuffer *b, bool select_only, bool anonym
{
int i;
struct dive *dive;
dive_trip_t *trip;
dive_trip *trip;
put_format(b, "<divelog program='subsurface' version='%d'>\n<settings>\n", DATAFORMAT_VERSION);

View file

@ -97,7 +97,7 @@ stats_summary calculate_stats_summary(bool selected_only)
int current_year = -1;
int current_month = 0;
int prev_month = 0, prev_year = 0;
dive_trip_t *trip_ptr = nullptr;
dive_trip *trip_ptr = nullptr;
stats_summary out;

View file

@ -309,7 +309,7 @@ QString formatTripTitle(const dive_trip *trip)
QDateTime localTime = timestampToDateTime(when);
QString prefix = !empty_string(trip->location) ? QString(trip->location) + ", " : QString();
QString prefix = !trip->location.empty() ? QString::fromStdString(trip->location) + ", " : QString();
if (getday)
return prefix + loc.toString(localTime, prefs.date_format);
else

View file

@ -12,7 +12,7 @@
#ifdef DEBUG_TRIP
void dump_trip_list()
{
dive_trip_t *trip;
dive_trip *trip;
int i = 0;
timestamp_t last_time = 0;
@ -24,7 +24,7 @@ void dump_trip_list()
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,
i + 1, trip->location.c_str(),
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);
@ -33,15 +33,19 @@ void dump_trip_list()
}
#endif
/* free resources associated with a trip structure */
void free_trip(dive_trip_t *trip)
dive_trip::dive_trip() : id(dive_getUniqID())
{
if (trip) {
free(trip->location);
free(trip->notes);
free(trip->dives.dives);
free(trip);
}
}
dive_trip::~dive_trip()
{
free(dives.dives);
}
/* free resources associated with a trip structure */
void free_trip(dive_trip *trip)
{
delete trip;
}
/* Trip table functions */
@ -87,7 +91,7 @@ bool is_trip_before_after(const struct dive *dive, bool before)
/* 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)
void add_dive_to_trip(struct dive *dive, dive_trip *trip)
{
if (dive->divetrip == trip)
return;
@ -103,7 +107,7 @@ void add_dive_to_trip(struct dive *dive, dive_trip_t *trip)
*/
struct dive_trip *unregister_dive_from_trip(struct dive *dive)
{
dive_trip_t *trip = dive->divetrip;
dive_trip *trip = dive->divetrip;
if (!trip)
return NULL;
@ -113,7 +117,7 @@ struct dive_trip *unregister_dive_from_trip(struct dive *dive)
return trip;
}
static void delete_trip(dive_trip_t *trip, struct trip_table *trip_table_arg)
static void delete_trip(dive_trip *trip, struct trip_table *trip_table_arg)
{
remove_trip(trip, trip_table_arg);
free_trip(trip);
@ -126,15 +130,13 @@ void remove_dive_from_trip(struct dive *dive, struct trip_table *trip_table_arg)
delete_trip(trip, trip_table_arg);
}
dive_trip_t *alloc_trip()
dive_trip *alloc_trip()
{
dive_trip_t *res = (dive_trip_t *)calloc(1, sizeof(dive_trip_t));
res->id = dive_getUniqID();
return res;
return new dive_trip;
}
/* insert the trip into the trip table */
void insert_trip(dive_trip_t *dive_trip, struct trip_table *trip_table_arg)
void insert_trip(struct dive_trip *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);
@ -143,12 +145,12 @@ void insert_trip(dive_trip_t *dive_trip, struct trip_table *trip_table_arg)
#endif
}
dive_trip_t *create_trip_from_dive(struct dive *dive)
dive_trip *create_trip_from_dive(struct dive *dive)
{
dive_trip_t *trip;
dive_trip *trip;
trip = alloc_trip();
trip->location = copy_string(get_dive_location(dive).c_str());
trip->location = get_dive_location(dive);
return trip;
}
@ -163,10 +165,10 @@ dive_trip_t *create_trip_from_dive(struct dive *dive)
* 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)
dive_trip *get_trip_for_new_dive(struct dive *new_dive, bool *allocated)
{
struct dive *d;
dive_trip_t *trip;
dive_trip *trip;
int i;
/* Find dive that is within TRIP_THRESHOLD of current dive */
@ -190,7 +192,7 @@ dive_trip_t *get_trip_for_new_dive(struct dive *new_dive, bool *allocated)
}
/* lookup of trip in main trip_table based on its id */
dive_trip_t *get_trip_by_uniq_id(int tripId)
dive_trip *get_trip_by_uniq_id(int tripId)
{
for (int i = 0; i < divelog.trips->nr; i++) {
if (divelog.trips->trips[i]->id == tripId)
@ -221,7 +223,7 @@ bool trips_overlap(const struct dive_trip *t1, const struct dive_trip *t2)
* 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)
dive_trip *get_dives_to_autogroup(struct dive_table *table, int start, int *from, int *to, bool *allocated)
{
int i;
struct dive *lastdive = NULL;
@ -231,7 +233,7 @@ dive_trip_t *get_dives_to_autogroup(struct dive_table *table, int start, int *fr
*/
for (i = start; i < table->nr; i++) {
struct dive *dive = table->dives[i];
dive_trip_t *trip;
dive_trip *trip;
if (dive->divetrip) {
lastdive = dive;
@ -265,9 +267,8 @@ dive_trip_t *get_dives_to_autogroup(struct dive_table *table, int start, int *fr
if (dive->divetrip || dive->notrip ||
dive->when >= lastdive->when + TRIP_THRESHOLD)
break;
std::string location = get_dive_location(dive);
if (!location.empty() && !trip->location)
trip->location = copy_string(get_dive_location(dive).c_str());
if (trip->location.empty())
trip->location = get_dive_location(dive);
lastdive = dive;
}
return trip;
@ -277,21 +278,21 @@ dive_trip_t *get_dives_to_autogroup(struct dive_table *table, int start, int *fr
return NULL;
}
/* 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)
/* Out of two strings, get the string that is not empty (if any). */
static std::string non_empty_string(const std::string &a, const std::string &b)
{
return copy_string(empty_string(b) ? a : b);
return b.empty() ? 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 *combine_trips(struct dive_trip *trip_a, struct dive_trip *trip_b)
{
dive_trip_t *trip;
dive_trip *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);
trip->location = non_empty_string(trip_a->location, trip_b->location);
trip->notes = non_empty_string(trip_a->notes, trip_b->notes);
return trip;
}

View file

@ -4,17 +4,22 @@
#include "divelist.h"
typedef struct dive_trip
#include <string>
struct dive_trip
{
char *location;
char *notes;
struct dive_table dives;
std::string location;
std::string notes;
struct dive_table dives = {};
int id; /* unique ID for this trip: used to pass trips through QML. */
/* Used by the io-routines to mark trips that have already been written. */
bool saved;
bool autogen;
bool selected;
} dive_trip_t;
bool saved = false;
bool autogen = false;
bool selected = false;
dive_trip();
~dive_trip();
};
typedef struct trip_table {
int nr, allocated;
@ -23,13 +28,13 @@ typedef struct trip_table {
static const trip_table_t empty_trip_table = { 0, 0, (struct dive_trip **)0 };
extern void add_dive_to_trip(struct dive *, dive_trip_t *);
extern void add_dive_to_trip(struct dive *, dive_trip *);
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 void insert_trip(dive_trip *trip, struct trip_table *trip_table_arg);
extern int remove_trip(const dive_trip *trip, struct trip_table *trip_table_arg);
extern void free_trip(dive_trip *trip);
extern timestamp_t trip_date(const struct dive_trip *trip);
extern timestamp_t trip_enddate(const struct dive_trip *trip);
@ -37,14 +42,14 @@ 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();
extern dive_trip_t *create_trip_from_dive(struct dive *dive);
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 dive_trip_t *get_trip_by_uniq_id(int tripId);
extern dive_trip *alloc_trip();
extern dive_trip *create_trip_from_dive(struct dive *dive);
extern dive_trip *get_dives_to_autogroup(struct dive_table *table, int start, int *from, int *to, bool *allocated);
extern dive_trip *get_trip_for_new_dive(struct dive *new_dive, bool *allocated);
extern dive_trip *get_trip_by_uniq_id(int tripId);
extern bool trips_overlap(const struct dive_trip *t1, const struct dive_trip *t2);
extern dive_trip_t *combine_trips(struct dive_trip *trip_a, struct dive_trip *trip_b);
extern dive_trip *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);

View file

@ -620,8 +620,8 @@ void DiveListView::merge_trip(const QModelIndex &a, int offset)
int i = a.row() + offset;
QModelIndex b = a.sibling(i, 0);
dive_trip_t *trip_a = a.data(DiveTripModelBase::TRIP_ROLE).value<dive_trip *>();
dive_trip_t *trip_b = b.data(DiveTripModelBase::TRIP_ROLE).value<dive_trip *>();
dive_trip *trip_a = a.data(DiveTripModelBase::TRIP_ROLE).value<dive_trip *>();
dive_trip *trip_b = b.data(DiveTripModelBase::TRIP_ROLE).value<dive_trip *>();
if (trip_a == trip_b || !trip_a || !trip_b)
return;
Command::mergeTrips(trip_a, trip_b);
@ -666,7 +666,7 @@ void DiveListView::addToTrip(int delta)
struct dive *d = contextMenuIndex.data(DiveTripModelBase::DIVE_ROLE).value<struct dive *>();
int nr = selectionModel()->selectedRows().count();
QModelIndex t;
dive_trip_t *trip = NULL;
dive_trip *trip = NULL;
// now look for the trip to add to, for this, loop over the selected dives and
// check if its sibling is a trip.
@ -708,7 +708,7 @@ void DiveListView::contextMenuEvent(QContextMenuEvent *event)
// let's remember where we are
contextMenuIndex = indexAt(event->pos());
struct dive *d = contextMenuIndex.data(DiveTripModelBase::DIVE_ROLE).value<struct dive *>();
dive_trip_t *trip = contextMenuIndex.data(DiveTripModelBase::TRIP_ROLE).value<dive_trip *>();
dive_trip *trip = contextMenuIndex.data(DiveTripModelBase::TRIP_ROLE).value<dive_trip *>();
QMenu popup(this);
if (currentLayout == DiveTripModelBase::TREE) {
// verify if there is a node that`s not expanded.

View file

@ -5,7 +5,6 @@
#define PROFILEWIDGET_H
#include "ui_profilewidget.h"
#include "core/owning_ptrs.h"
#include "core/subsurface-qt/divelistnotifier.h"
#include <vector>

View file

@ -140,9 +140,9 @@ void TabDiveNotes::tripChanged(dive_trip *trip, TripField field)
return;
if (field.notes)
ui.notes->setText(currentTrip->notes);
ui.notes->setText(QString::fromStdString(currentTrip->notes));
if (field.location)
ui.diveTripLocation->setText(currentTrip->location);
ui.diveTripLocation->setText(QString::fromStdString(currentTrip->location));
}
static bool isHtml(const QString &s)
@ -220,13 +220,13 @@ void TabDiveNotes::updateData(const std::vector<dive *> &, dive *currentDive, in
ui.editDiveSiteButton->hide();
// rename the remaining fields and fill data from selected trip
ui.LocationLabel->setText(tr("Trip location"));
ui.diveTripLocation->setText(currentTrip->location);
ui.diveTripLocation->setText(QString::fromStdString(currentTrip->location));
updateTripDate(currentTrip);
ui.locationTags->clear();
//TODO: Fix this.
//ui.location->setText(currentTrip->location);
//ui.location->setText(QString::fromStdSTring(currentTrip->location));
ui.NotesLabel->setText(tr("Trip notes"));
ui.notes->setText(currentTrip->notes);
ui.notes->setText(QString::fromStdString(currentTrip->notes));
ui.depth->setVisible(false);
ui.depthLabel->setVisible(false);
ui.duration->setVisible(false);

View file

@ -1369,17 +1369,17 @@ void QMLManager::commitChanges(QString diveId, QString number, QString date, QSt
void QMLManager::updateTripDetails(QString tripIdString, QString tripLocation, QString tripNotes)
{
int tripId = tripIdString.toInt();
dive_trip_t *trip = get_trip_by_uniq_id(tripId);
dive_trip *trip = get_trip_by_uniq_id(tripId);
if (!trip) {
report_info("updateTripData: cannot find trip for tripId %s", qPrintable(tripIdString));
return;
}
bool changed = false;
if (tripLocation != trip->location) {
if (tripLocation != trip->location.c_str()) {
changed = true;
Command::editTripLocation(trip, tripLocation);
}
if (tripNotes != trip->notes) {
if (tripNotes != trip->notes.c_str()) {
changed = true;
Command::editTripNotes(trip, tripNotes);
}
@ -1412,7 +1412,7 @@ void QMLManager::addTripForDive(int id)
return;
}
if (d->divetrip) {
appendTextToLog(QString("Asked to create trip for dive %1 with id %2 but it's already part of a trip with location %3.").arg(d->number).arg(id).arg(d->divetrip->location));
appendTextToLog(QString("Asked to create trip for dive %1 with id %2 but it's already part of a trip with location %3.").arg(d->number).arg(id).arg(d->divetrip->location.c_str()));
return;
}
QVector <dive *> dives;

View file

@ -81,7 +81,7 @@ QString DiveTripModelBase::tripTitle(const dive_trip *trip)
QString numDives = tr("(%n dive(s))", "", trip->dives.nr);
int shown = trip_shown_dives(trip);
QString shownDives = shown != trip->dives.nr ? QStringLiteral(" ") + tr("(%L1 shown)").arg(shown) : QString();
QString title(trip->location);
QString title = QString::fromStdString(trip->location);
if (title.isEmpty()) {
// so use the date range
@ -110,8 +110,8 @@ QVariant DiveTripModelBase::tripData(const dive_trip *trip, int column, int role
case MobileListModel::TripNrDivesRole: return trip->dives.nr;
case MobileListModel::TripShortDateRole: return tripShortDate(trip);
case MobileListModel::TripTitleRole: return tripTitle(trip);
case MobileListModel::TripLocationRole: return QString(trip->location);
case MobileListModel::TripNotesRole: return QString(trip->notes);
case MobileListModel::TripLocationRole: return QString::fromStdString(trip->location);
case MobileListModel::TripNotesRole: return QString::fromStdString(trip->notes);
}
#endif
// Set the font for all trips alike
@ -714,7 +714,7 @@ void DiveTripModelTree::populate()
update_cylinder_related_info(d);
if (d->hidden_by_filter)
continue;
dive_trip_t *trip = d->divetrip;
dive_trip *trip = d->divetrip;
// If this dive doesn't have a trip, add as top-level item.
if (!trip) {