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

@ -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;