Commit 8250ef7b authored by Valentin Platzgummer's avatar Valentin Platzgummer

measurement complex item loading almost finished

parent 1eccaa0c
......@@ -304,14 +304,16 @@ bool AreaData::load(const QJsonObject &obj, QString &errorString) {
if (JsonHelper::validateKeys(obj, keyInfo, e)) {
this->clear();
// iterate over json array
for (const auto &jsonArea : obj[areaListKey].toArray()) {
for (const auto valueRef : obj[areaListKey].toArray()) {
const auto jsonArea = valueRef.toObject();
// check if area type key is present
QList<JsonHelper::KeyValidateInfo> areaInfo = {
{GeoArea::areaTypeKey, QJsonValue::String, true},
};
if (!JsonHelper::validateKeys(jsonArea, areaInfo, e)) {
// load MeasurementArea
if (jsonArea[GeoArea::areaTypeKey] == MeasurementArea::name) {
if (jsonArea[GeoArea::areaTypeKey].toString() ==
MeasurementArea::name) {
auto area = getGeoArea<MeasurementArea *>(_areaList);
if (area == nullptr) {
auto area = new MeasurementArea(this);
......@@ -330,7 +332,8 @@ bool AreaData::load(const QJsonObject &obj, QString &errorString) {
}
}
// load SafeArea
else if (jsonArea[GeoArea::areaTypeKey] == SafeArea::name) {
else if (jsonArea[GeoArea::areaTypeKey].toString() ==
SafeArea::name) {
auto area = getGeoArea<SafeArea *>(_areaList);
if (area == nullptr) {
auto area = new SafeArea(this);
......@@ -352,7 +355,7 @@ bool AreaData::load(const QJsonObject &obj, QString &errorString) {
else {
returnValue = false;
errorString.append(tr("Unknown area type: ") +
jsonArea[GeoArea::areaTypeKey]);
jsonArea[GeoArea::areaTypeKey].toString());
}
}
// GeoArea::areaTypeKey missing
......@@ -397,7 +400,7 @@ bool AreaData::save(QJsonObject &obj) {
QJsonObject temp;
QJsonValue jsonOrigin;
JsonHelper::saveGeoCoordinate(_origin, true, jsonOrigin);
JsonHelper::saveGeoCoordinate(_origin, false, jsonOrigin);
temp[originKey] = jsonOrigin;
temp[initializedKey] = _initialized;
......
......@@ -19,12 +19,20 @@ template <> inline auto get<0>(const IntPoint &p) { return p.X; }
template <> inline auto get<1>(const IntPoint &p) { return p.Y; }
namespace routing {
namespace {
const QString generatorType = "CircularGenerator";
GeneratorBase *creator(QObject *parent) {
return new CircularGenerator(parent);
}
const char *distanceKey = "TransectDistance";
const char *deltaAlphaKey = "DeltaAlpha";
const char *minLengthKey = "MinLength";
const char *referenceKey = "ReferencePoint";
} // namespace
REGISTER_GENERATOR(generatorType, creator)
bool circularTransects(const snake::FPoint &reference,
......@@ -34,10 +42,6 @@ bool circularTransects(const snake::FPoint &reference,
snake::Length minLength, snake::Transects &transects);
const char *CircularGenerator::settingsGroup = "CircularGenerator";
const char *distanceKey = "TransectDistance";
const char *deltaAlphaKey = "DeltaAlpha";
const char *minLengthKey = "MinLength";
const char *referenceKey = "ReferencePoint";
CircularGenerator::CircularGenerator(QObject *parent)
: CircularGenerator(nullptr, parent) {}
......@@ -192,6 +196,8 @@ void CircularGenerator::setReference(const QGeoCoordinate &reference) {
bool CircularGenerator::save(QJsonObject &obj) const {
QJsonObject temp;
GeneratorBase::save(temp);
bool ok = false;
auto variant = _distance.rawValue();
auto val = variant.toDouble(&ok);
......@@ -237,6 +243,14 @@ bool CircularGenerator::save(QJsonObject &obj) const {
bool CircularGenerator::load(const QJsonObject &obj, QString &errorString) {
bool returnValue = true;
{
QString e;
if (!GeneratorBase::load(obj, e)) {
returnValue = false;
errorString.append(e);
}
}
// load distance
{
QString e;
......
......@@ -5,6 +5,7 @@
namespace routing {
const char *GeneratorBase::typeKey = "GeneratorType";
const char *GeneratorBase::nameKey = "Name";
GeneratorBase::GeneratorBase(QObject *parent)
: GeneratorBase(nullptr, parent) {}
......@@ -16,7 +17,24 @@ GeneratorBase::GeneratorBase(GeneratorBase::Data d, QObject *parent)
GeneratorBase::~GeneratorBase() {}
QString GeneratorBase::name() { return _name; }
bool GeneratorBase::save(QJsonObject &obj) const {
obj[typeKey] = type();
obj[name] = name();
return true;
}
bool GeneratorBase::load(const QJsonObject &obj, QString &errorString) {
if (obj.contains[nameKey] && obj[nameKey].isString()) {
setName(obj[nameKey].toString());
return true;
} else {
errorString.append(
tr("Not able to load generator name. Leaving name unchanged."));
return false;
}
}
QString GeneratorBase::name() const { return _name; }
void GeneratorBase::setName(const QString &name) {
if (_name != name) {
......
......@@ -27,16 +27,17 @@ public:
Q_PROPERTY(QString mapVisualQml READ mapVisualQml CONSTANT)
Q_PROPERTY(QString name READ name WRITE setName NOTIFY nameChanged)
virtual QString editorQml() = 0;
virtual QString mapVisualQml() = 0;
virtual QString editorQml() const = 0;
virtual QString mapVisualQml() const = 0;
virtual bool save(QJsonObject &obj) const = 0;
virtual bool load(const QJsonObject &obj, QString &errorString) = 0;
virtual bool save(QJsonObject &obj) const; // must be called if overridden
virtual bool load(const QJsonObject &obj,
QString &errorString); // must be called if overridden
QString name();
QString name() const;
void setName(const QString &name);
virtual QString abbreviation() = 0;
virtual QString type() = 0;
virtual QString abbreviation() const = 0;
virtual QString type() const = 0;
virtual bool get(Generator &generator) = 0;
......@@ -44,6 +45,7 @@ public:
void setData(Data d);
static const char *typeKey;
static const char *nameKey;
signals:
void generatorChanged();
......
......@@ -12,10 +12,17 @@
#include "nemo_interface/SnakeTile.h"
namespace routing {
namespace {
const QString generatorType = "LinearGenerator";
GeneratorBase *creator(QObject *parent) { return new LinearGenerator(parent); }
const char *distanceKey = "TransectDistance";
const char *alphaKey = "Alpha";
const char *minLengthKey = "MinLength";
} // namespace
REGISTER_GENERATOR(generatorType, creator)
QGC_LOGGING_CATEGORY(LinearGeneratorLog, "LinearGeneratorLog")
......@@ -25,9 +32,6 @@ bool linearTransects(const snake::FPolygon &polygon,
snake::Length minLength, snake::Transects &transects);
const char *LinearGenerator::settingsGroup = "LinearGenerator";
const char *distanceKey = "TransectDistance";
const char *alphaKey = "Alpha";
const char *minLengthKey = "MinLength";
LinearGenerator::LinearGenerator(QObject *parent)
: LinearGenerator(nullptr, parent) {}
......@@ -159,6 +163,8 @@ bool LinearGenerator::get(Generator &generator) {
bool LinearGenerator::save(QJsonObject &obj) const {
QJsonObject temp;
GeneratorBase::save(temp);
bool ok = false;
auto variant = _distance.rawValue();
auto val = variant.toDouble(&ok);
......@@ -200,6 +206,14 @@ bool LinearGenerator::save(QJsonObject &obj) const {
bool LinearGenerator::load(const QJsonObject &obj, QString &errorString) {
bool returnValue = true;
{
QString e;
if (!GeneratorBase::load(obj, e)) {
returnValue = false;
errorString.append(e);
}
}
// load distance
{
QString e;
......
......@@ -30,13 +30,13 @@ constexpr typename std::underlying_type<T>::type integral(T value) {
const char *MeasurementComplexItem::settingsGroup = "MeasurementComplexItem";
const char *MeasurementComplexItem::jsonComplexItemTypeValue =
"MeasurementComplexItem";
const char *MeasurementComplexItem::variantName = "Variant";
const char *MeasurementComplexItem::altitudeName = "Altitude";
const QString MeasurementComplexItem::name(tr("Measurement"));
const char *areaDataName = "AreaData";
const char *variantNamesName = "VariantNames";
const char *generatorsName = "Generators";
const char *variantsName = "Variants";
const char *variantKey = "Variant";
const char *altitudeKey = "Altitude";
const char *areaDataKey = "AreaData";
const char *variantNamesKey = "VariantNames";
const char *generatorsKey = "Generators";
const char *variantsKey = "Variants";
MeasurementComplexItem::MeasurementComplexItem(
PlanMasterController *masterController, bool flyView,
......@@ -46,8 +46,8 @@ MeasurementComplexItem::MeasurementComplexItem(
_metaDataMap(FactMetaData::createMapFromJsonFile(
QStringLiteral(":/json/MeasurementComplexItem.SettingsGroup.json"),
this)),
_altitude(settingsGroup, _metaDataMap[altitudeName]),
_variant(settingsGroup, _metaDataMap[variantName]),
_altitude(settingsGroup, _metaDataMap[altitudeKey]),
_variant(settingsGroup, _metaDataMap[variantKey]),
_pAreaData(new AreaData(this)), _pEditorData(new AreaData(this)),
_pCurrentData(_pAreaData), _pGenerator(nullptr),
_pWorker(new RoutingThread(this)) {
......@@ -103,6 +103,8 @@ MeasurementComplexItem::MeasurementComplexItem(
resetGenerators();
qCritical() << "ToDo: _altitude connections missing.";
qCritical() << "ToDo: remove generatorNameList and use GeneratorBase::name() "
"instead.";
}
MeasurementComplexItem::~MeasurementComplexItem() {}
......@@ -123,10 +125,6 @@ QStringList MeasurementComplexItem::variantNames() const {
bool MeasurementComplexItem::load(const QJsonObject &complexObject,
int sequenceNumber, QString &errorString) {
qWarning() << "MeasurementComplexItem::load(): area data load missing.";
qWarning() << "MeasurementComplexItem::load(): mission item load missing.";
qWarning() << "MeasurementComplexItem::load(): add editingStart/Stop.";
// We need to pull version first to determine what validation/conversion
// needs to be performed
QList<JsonHelper::KeyValidateInfo> versionKeyInfoList = {
......@@ -169,23 +167,166 @@ bool MeasurementComplexItem::load(const QJsonObject &complexObject,
setSequenceNumber(sequenceNumber);
startEditing();
bool returnValue = true;
// load variant
if (complexObject.contains(variantName) &&
complexObject[variantName].isDouble()) {
_variant.setRawValue(complexObject[variantName].toInt());
if (complexObject.contains(variantKey) &&
complexObject[variantKey].isDouble()) {
_variant.setRawValue(complexObject[variantKey].toInt());
} else {
errorString.append(tr("Not able to load route variant number."));
returnValue = false;
errorString.append(tr("No route variant number found in file.\n"));
}
// load altitude
if (complexObject.contains(altitudeName) &&
complexObject[altitudeName].isDouble()) {
_altitude.setRawValue(complexObject[altitudeName].toDouble());
if (complexObject.contains(altitudeKey) &&
complexObject[altitudeKey].isDouble()) {
_altitude.setRawValue(complexObject[altitudeKey].toDouble());
} else {
returnValue = false;
errorString.append(tr("No altitude found in file.\n"));
}
// load AreaData.
if (complexObject.contains(areaDataKey) &&
complexObject[areaDataKey].isObject()) {
QString e;
if (_pCurrentData->load(complexObject[areaDataKey].toObject(), e)) {
_pCurrentData->setShowErrorMessages(false);
if (!_pCurrentData->isCorrect()) {
_pCurrentData->setShowErrorMessages(true);
errorString.append(
tr("Loaded area data does not fullfill rules. Abort loading.\n"));
abortEditing();
return false;
}
_pCurrentData->setShowErrorMessages(true);
} else {
// this is critical, proceeding is not
// reasonable.
errorString.append(e);
errorString.append(tr("Abort loading.\n"));
abortEditing();
return false;
}
} else {
// this is critical, if no area data present, proceeding is not reasonable.
errorString.append(tr("No area data found in file. Abort loading.\n"));
abortEditing();
return false;
}
// load Generators.
if (complexObject.contains(generatorsKey) &&
complexObject[generatorsKey].isArray()) {
QVector<PtrGenerator> generatorList;
QObject parent;
for (const auto valueRef : complexObject[generatorsKey].toArray()) {
const auto jsonGen = valueRef.toObject();
if (jsonGen.contains(routing::GeneratorBase::typeKey) &&
jsonGen[routing::GeneratorBase::typeKey].isString()) {
QString e;
// create generator
auto gen = routing::GeneratorFactory::instance()->create(
jsonGen, e, &parent /*parent*/);
if (gen != nullptr) {
// remove generators of same type and insert this generator.
for (int i = 0; i < _generatorList.size();) {
auto otherGen = generator(i);
if (gen->type() == otherGen->type()) {
removeGenerator(i);
} else {
++i;
}
}
gen->setData(this->_pAreaData);
generatorList.append(gen);
} else {
// error loading generator.
errorString.append(
tr("Error loading generator of type ") +
jsonGen[routing::GeneratorBase::typeKey].toString() + ".\n");
if (!routing::GeneratorFactory::instance()->registered(
jsonGen[routing::GeneratorBase::typeKey].toString())) {
errorString.append(tr("This type is unknown.\n"));
qCritical()
<< "MeasurementComplexItem::load(): generator of type :"
<< jsonGen[routing::GeneratorBase::typeKey]
<< " not registered with the GeneratorFactory. This can either "
"mean that the file contains a invalid entry or "
"that the generator was not registered. In the latter case "
"use the REGISTER_GENERATOR() for registration";
}
returnValue = false;
}
} else {
errorString.append(tr(
"Can not determine type of generator. Skipping this generator."));
returnValue = false;
}
// insert generators
for (const auto gen : generatorList) {
gen->setParent(this);
addGenerator(gen->name(), gen);
}
}
} else {
returnValue = false;
errorString.append(
tr("No generators found in file. Leaving generators unchanged.\n"));
}
// load Route Variants
if (complexObject.contains(variantsKey) &&
complexObject[variantsKey].isArray()) {
QVector<Variant> variantVector;
// load variants to variantVector for further processing.
for (const auto valueRef : complexObject[variantsKey].toArray()) {
if (valueRef.isArray()) {
const auto jsonVariant = valueRef.toObject();
Variant variant;
QString e;
if (JsonHelper::loadGeoCoordinateArray(jsonVariant, false, variantList,
e)) {
if (variant.size() > 0) {
variantVector.append(std::move(variant));
} else {
errorString.append("Empty route variant skipped.\n");
returnValue = false;
}
} else {
errorString.append(e);
errorString.append("\n");
returnValue = false;
}
} else {
qCDebug(MeasurementComplexItemLog)
<< "json variant is not an array but of type: " << valueRef.type();
returnValue = false;
}
}
// Check if variants are covered by safe area.
qCritical() << "Continue here!";
} else {
errorString.append(tr("Not able to load altitude."));
returnValue = false;
errorString.append(tr(
"No route variants found in file. Calculating new route variants.\n"));
stopEditing();
}
return true;
stopEditing(false);
return returnValue;
}
double
......@@ -227,15 +368,15 @@ void MeasurementComplexItem::save(QJsonArray &planItems) {
jsonComplexItemTypeValue;
// Variant and altitude.
saveObject[variantName] = double(_variant.rawValue().toUInt());
saveObject[altitudeName] = double(_altitude.rawValue().toUInt());
saveObject[variantKey] = double(_variant.rawValue().toUInt());
saveObject[altitudeKey] = double(_altitude.rawValue().toUInt());
// Variant names.
QJsonArray jsonVariantNames;
for (auto const &name : _variantNames) {
jsonVariantNames.append(name);
}
saveObject[variantNamesName] = jsonVariantNames;
saveObject[variantNamesKey] = jsonVariantNames;
// AreaData.
QJsonObject jsonAreaData;
......@@ -244,7 +385,7 @@ void MeasurementComplexItem::save(QJsonArray &planItems) {
<< "save(): not able to save area data";
return;
}
saveObject[areaDataName] = jsonAreaData;
saveObject[areaDataKey] = jsonAreaData;
// Generators.
QJsonArray generatorArray;
......@@ -262,7 +403,7 @@ void MeasurementComplexItem::save(QJsonArray &planItems) {
generatorArray.append(outerObj);
}
}
saveObject[generatorsName] = generatorArray;
saveObject[generatorsKey] = generatorArray;
// Route Variants
QJsonArray variantsArray;
......@@ -275,7 +416,7 @@ void MeasurementComplexItem::save(QJsonArray &planItems) {
}
variantsArray.append(variant);
}
saveObject[variantsName] = variantsArray;
saveObject[variantsKey] = variantsArray;
planItems.append(saveObject);
} else {
......@@ -777,7 +918,7 @@ void MeasurementComplexItem::resetGenerators() {
addGenerator(cg->name(), cg);
}
QStringList MeasurementComplexItem::generatorNameList() {
QStringList MeasurementComplexItem::generatorNameList() const {
return this->_generatorNameList;
}
......@@ -785,7 +926,28 @@ routing::GeneratorBase *MeasurementComplexItem::generator() {
return _pGenerator;
}
int MeasurementComplexItem::generatorIndex() {
const routing::GeneratorBase *MeasurementComplexItem::generator() const {
return _pGenerator;
}
const routing::GeneratorBase *
MeasurementComplexItem::generator(int index) const {
if (index > 0 && index < _generatorList.size()) {
return _generatorList[index];
} else {
return nullptr;
}
}
routing::GeneratorBase *MeasurementComplexItem::generator(int index) {
if (index > 0 && index < _generatorList.size()) {
return _generatorList[index];
} else {
return nullptr;
}
}
int MeasurementComplexItem::generatorIndex() const {
return this->_generatorList.indexOf(this->_pGenerator);
}
......@@ -797,7 +959,7 @@ void MeasurementComplexItem::startEditing() {
}
}
void MeasurementComplexItem::stopEditing() {
bool MeasurementComplexItem::stopEditing(bool doUpdate) {
if (editing()) {
bool correct = _pEditorData->isCorrect();
if (correct) {
......@@ -805,10 +967,13 @@ void MeasurementComplexItem::stopEditing() {
}
_setAreaData(_pAreaData);
_setState(STATE::IDLE);
if (correct && *_pEditorData != *_pAreaData) {
if (doUpdate && correct && *_pEditorData != *_pAreaData) {
_updateRoute();
}
return correct;
}
return false;
}
void MeasurementComplexItem::abortEditing() {
......
......@@ -101,9 +101,12 @@ public:
Q_INVOKABLE bool switchToGenerator(const QString &name);
Q_INVOKABLE bool switchToGenerator(int index);
Q_INVOKABLE void resetGenerators();
QStringList generatorNameList();
QStringList generatorNameList() const;
routing::GeneratorBase *generator();
int generatorIndex();
const routing::GeneratorBase *generator() const;
routing::GeneratorBase *generator(int index);
const routing::GeneratorBase *generator(int index) const;
int generatorIndex() const;
// Editing.
//!
......@@ -119,7 +122,11 @@ public:
//! Stops area editing. Will reset area data to the state before
//! editingStart() if it is invalid. Triggers a route update.
//!
Q_INVOKABLE void stopEditing();
//! \param doUpdate No route update will be triggered if false, route update
//! will eventually be triggered if true. \return Returns true if a route
//! update was triggered, false either.
//!
Q_INVOKABLE bool stopEditing(bool doUpdate = true);
//!
//! \brief abortEditing Aborts area editing.
//!
......@@ -143,8 +150,6 @@ public:
bool followTerrain() const;
static const char *settingsGroup;
static const char *variantName;
static const char *altitudeName;
static const char *jsonComplexItemTypeValue;
static const QString name;
......
......@@ -38,10 +38,9 @@ inline static void qCallOnce(Function func, QBasicAtomicInt &flag) {
}
template <class Function> inline static void qCallOncePerThread(Function func) {
using namespace CallOnce;
if (!once_flag()->hasLocalData()) {
once_flag()->setLocalData(new QAtomicInt(CO_Request));
qCallOnce(func, *once_flag()->localData());
if (!CallOnce::once_flag()->hasLocalData()) {
CallOnce::once_flag()->setLocalData(new QAtomicInt(CallOnce::CO_Request));
qCallOnce(func, *CallOnce::once_flag()->localData());
}
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment