From f778e405acd08eed4a1a1c0313d9362d557eb159 Mon Sep 17 00:00:00 2001 From: Valentin Platzgummer Date: Mon, 14 Dec 2020 19:50:06 +0100 Subject: [PATCH] loading almost finished --- src/MeasurementComplexItem/AreaData.cc | 174 ++++++++---------- src/MeasurementComplexItem/AreaData.h | 4 +- .../CircularGenerator.cpp | 87 ++++++--- .../CircularGenerator.h | 15 +- src/MeasurementComplexItem/GeneratorBase.cc | 26 +-- src/MeasurementComplexItem/GeneratorBase.h | 4 +- .../LinearGenerator.cpp | 68 ++++--- src/MeasurementComplexItem/LinearGenerator.h | 15 +- .../MeasurementComplexItem.cc | 155 ++++++++++------ .../MeasurementComplexItem.h | 6 +- .../qml/AreaDataEditor.qml | 11 -- .../qml/MeasurementItemEditor.qml | 33 +--- .../qml/MeasurementItemMapVisual.qml | 11 +- .../qml/ParameterEditor.qml | 2 +- 14 files changed, 329 insertions(+), 282 deletions(-) diff --git a/src/MeasurementComplexItem/AreaData.cc b/src/MeasurementComplexItem/AreaData.cc index ab5efd2a1..e4b1d796e 100644 --- a/src/MeasurementComplexItem/AreaData.cc +++ b/src/MeasurementComplexItem/AreaData.cc @@ -13,14 +13,13 @@ QGC_LOGGING_CATEGORY(AreaDataLog, "AreaDataLog") const char *originKey = "Origin"; const char *areaListKey = "AreaList"; -const char *initializedKey = "Initialized"; AreaData::AreaData(QObject *parent) : QObject(parent) {} AreaData::~AreaData() {} AreaData::AreaData(const AreaData &other, QObject *parent) - : QObject(parent), _initialized(false), _showErrorMessages(true) { + : QObject(parent), _showErrorMessages(true) { *this = other; } @@ -35,7 +34,6 @@ AreaData &AreaData::operator=(const AreaData &other) { } _origin = other._origin; - _initialized = other._initialized; return *this; } @@ -130,11 +128,10 @@ bool AreaData::isCorrect() { // qDebug() << ss.str().c_str(); if (!bg::covered_by(measurementAreaENU, safeAreaENU)) { _processError(tr("Measurement Area not inside Safe Area. Please adjust " - "the Measurement Area.")); + "the Measurement Area.\n")); return false; } - _initialized = true; return true; } @@ -196,7 +193,6 @@ bool AreaData::initialize(const QGeoCoordinate &bottomLeft, safeArea->vertexCoordinate(0).longitude() * 0.5 + measurementArea->vertexCoordinate(0).longitude() * 0.5)); - _initialized = true; return true; } else { qCWarning(AreaDataLog) @@ -206,7 +202,12 @@ bool AreaData::initialize(const QGeoCoordinate &bottomLeft, } } -bool AreaData::initialized() { return _initialized; } +bool AreaData::initialized() { + auto measurementArea = getGeoArea(_areaList); + auto safeArea = getGeoArea(_areaList); + return measurementArea != nullptr && safeArea != nullptr && + measurementArea->count() >= 3 && safeArea->count() >= 3; +} void AreaData::intersection() { if (initialized() && _areasCorrect()) { @@ -261,6 +262,12 @@ void AreaData::intersection() { } } +MeasurementArea *AreaData::measurementArea() { + return getGeoArea(_areaList); +} + +SafeArea *AreaData::safeArea() { return getGeoArea(_areaList); } + bool AreaData::operator==(const AreaData &other) const { if (_areaList.count() == other._areaList.count()) { for (int i = 0; i < _areaList.count(); ++i) { @@ -280,119 +287,93 @@ bool AreaData::operator!=(const AreaData &other) const { bool AreaData::load(const QJsonObject &obj, QString &errorString) { bool returnValue = true; - // load initialized. - { - QString e; - QList keyInfo = { - {initializedKey, QJsonValue::Bool, true}, - }; - if (JsonHelper::validateKeys(obj, keyInfo, e)) { - _initialized = obj[initializedKey].toBool(); - } else { - returnValue = false; - errorString.append(e); - errorString.append("\n"); - } - } - // load areaList. - { - QString e; - QList keyInfo = { - {areaListKey, QJsonValue::Array, true}, - }; - if (JsonHelper::validateKeys(obj, keyInfo, e)) { - this->clear(); - // iterate over json array - for (const auto valueRef : obj[areaListKey].toArray()) { - const auto jsonArea = valueRef.toObject(); - // check if area type key is present - QList areaInfo = { - {GeoArea::areaTypeKey, QJsonValue::String, true}, - }; - if (!JsonHelper::validateKeys(jsonArea, areaInfo, e)) { - // load MeasurementArea - if (jsonArea[GeoArea::areaTypeKey].toString() == - MeasurementArea::name) { - auto area = getGeoArea(_areaList); - if (area == nullptr) { - auto area = new MeasurementArea(this); - if (area->loadFromJson(jsonArea, e)) { - this->insert(area); - } else { - returnValue = false; - errorString.append(e); - errorString.append("\n"); - area->deleteLater(); - } + if (obj.contains(areaListKey) && obj[areaListKey].isArray()) { + + this->clear(); + + // iterate over json array + for (const auto valueRef : obj[areaListKey].toArray()) { + const auto jsonArea = valueRef.toObject(); + + // check if area type key is present + if (jsonArea.contains(GeoArea::areaTypeKey) && + jsonArea[GeoArea::areaTypeKey].isString()) { + + // load MeasurementArea + if (jsonArea[GeoArea::areaTypeKey].toString() == + MeasurementArea::name) { + + auto area = getGeoArea(_areaList); + + if (area == nullptr) { + + auto area = new MeasurementArea(this); + QString e; + if (area->loadFromJson(jsonArea, e)) { + this->insert(area); } else { returnValue = false; - errorString.append( - tr("Multiple Measurement Areas detected. Area was ignored.")); + errorString.append(e); + errorString.append("\n"); + area->deleteLater(); } + } else { + returnValue = false; + errorString.append( + tr("Multiple Measurement Areas detected. Area was ignored.")); } - // load SafeArea - else if (jsonArea[GeoArea::areaTypeKey].toString() == - SafeArea::name) { - auto area = getGeoArea(_areaList); - if (area == nullptr) { - auto area = new SafeArea(this); - if (area->loadFromJson(jsonArea, e)) { - this->insert(area); - } else { - returnValue = false; - errorString.append(e); - errorString.append("\n"); - area->deleteLater(); - } + } + // load SafeArea + else if (jsonArea[GeoArea::areaTypeKey].toString() == SafeArea::name) { + + auto area = getGeoArea(_areaList); + if (area == nullptr) { + + auto area = new SafeArea(this); + QString e; + if (area->loadFromJson(jsonArea, e)) { + this->insert(area); } else { returnValue = false; - errorString.append( - tr("Multiple Safe Areas detected. Area was ignored.")); + errorString.append(e); + errorString.append("\n"); + area->deleteLater(); } - } - // unknown area - else { + } else { returnValue = false; - errorString.append(tr("Unknown area type: ") + - jsonArea[GeoArea::areaTypeKey].toString()); + errorString.append( + tr("Multiple Safe Areas detected. Area was ignored.")); } } - // GeoArea::areaTypeKey missing + // unknown area else { returnValue = false; - errorString.append(e); - errorString.append("\n"); + errorString.append(tr("Unknown area type: ") + + jsonArea[GeoArea::areaTypeKey].toString()); } + } else { + // GeoArea::areaTypeKey missing + returnValue = false; + errorString.append( + "Area type key missing, not able to determine area type.\n"); } } + } else { // AreaList missing - else { - returnValue = false; - errorString.append(e); - errorString.append("\n"); - } + returnValue = false; + errorString.append("Not able to load areas.\n"); } // load origin - { + if (obj.contains(originKey) && obj[originKey].isObject()) { + QGeoCoordinate origin; QString e; - QList keyInfo = { - {originKey, QJsonValue::Object, true}, - }; - if (JsonHelper::validateKeys(obj, keyInfo, e)) { - QGeoCoordinate origin; - if (JsonHelper::loadGeoCoordinate(obj[originKey], false, origin, e)) { - _origin = origin; - } + if (JsonHelper::loadGeoCoordinate(obj[originKey], false, origin, e)) { + _origin = origin; } } - // check if this is correct. - if (!this->isCorrect()) { - returnValue = false; - } - return returnValue; } @@ -402,7 +383,6 @@ bool AreaData::save(QJsonObject &obj) { QJsonValue jsonOrigin; JsonHelper::saveGeoCoordinate(_origin, false, jsonOrigin); temp[originKey] = jsonOrigin; - temp[initializedKey] = _initialized; QJsonArray jsonAreaList; for (int i = 0; i < _areaList.count(); ++i) { diff --git a/src/MeasurementComplexItem/AreaData.h b/src/MeasurementComplexItem/AreaData.h index ae48f139e..20e6ae0fc 100644 --- a/src/MeasurementComplexItem/AreaData.h +++ b/src/MeasurementComplexItem/AreaData.h @@ -71,6 +71,9 @@ public: Q_INVOKABLE bool initialized(); Q_INVOKABLE void intersection(); + Q_INVOKABLE MeasurementArea *measurementArea(); + Q_INVOKABLE SafeArea *safeArea(); + bool operator==(const AreaData &other) const; bool operator!=(const AreaData &other) const; @@ -98,7 +101,6 @@ private: QGeoCoordinate _origin; QmlObjectListModel _areaList; - bool _initialized; QString _errorString; bool _showErrorMessages; }; diff --git a/src/MeasurementComplexItem/CircularGenerator.cpp b/src/MeasurementComplexItem/CircularGenerator.cpp index aa3b6e7bd..8e1c526fa 100644 --- a/src/MeasurementComplexItem/CircularGenerator.cpp +++ b/src/MeasurementComplexItem/CircularGenerator.cpp @@ -21,8 +21,6 @@ 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); } @@ -33,8 +31,6 @@ const char *minLengthKey = "MinLength"; const char *referenceKey = "ReferencePoint"; } // namespace -REGISTER_GENERATOR(generatorType, creator) - bool circularTransects(const snake::FPoint &reference, const snake::FPolygon &polygon, const std::vector &tiles, @@ -42,9 +38,20 @@ bool circularTransects(const snake::FPoint &reference, snake::Length minLength, snake::Transects &transects); const char *CircularGenerator::settingsGroup = "CircularGenerator"; +const char *CircularGenerator::typeString = "CircularGenerator"; + +REGISTER_GENERATOR(CircularGenerator::typeString, creator) CircularGenerator::CircularGenerator(QObject *parent) - : CircularGenerator(nullptr, parent) {} + : GeneratorBase(parent), + _metaDataMap(FactMetaData::createMapFromJsonFile( + QStringLiteral(":/json/CircularGenerator.SettingsGroup.json"), this)), + _distance(settingsGroup, _metaDataMap[distanceKey]), + _deltaAlpha(settingsGroup, _metaDataMap[deltaAlphaKey]), + _minLength(settingsGroup, _metaDataMap[minLengthKey]), + _measurementArea(nullptr) { + init(); +} CircularGenerator::CircularGenerator(GeneratorBase::Data d, QObject *parent) : GeneratorBase(d, parent), @@ -54,28 +61,20 @@ CircularGenerator::CircularGenerator(GeneratorBase::Data d, QObject *parent) _deltaAlpha(settingsGroup, _metaDataMap[deltaAlphaKey]), _minLength(settingsGroup, _metaDataMap[minLengthKey]), _measurementArea(nullptr) { - connect(this->distance(), &Fact::rawValueChanged, this, - &GeneratorBase::generatorChanged); - connect(this->deltaAlpha(), &Fact::rawValueChanged, this, - &GeneratorBase::generatorChanged); - connect(this->minLength(), &Fact::rawValueChanged, this, - &GeneratorBase::generatorChanged); - connect(this, &CircularGenerator::referenceChanged, this, - &GeneratorBase::generatorChanged); - setName(tr("Circular Generator")); + init(); } -QString CircularGenerator::editorQml() { +QString CircularGenerator::editorQml() const { return QStringLiteral("CircularGeneratorEditor.qml"); } -QString CircularGenerator::mapVisualQml() { +QString CircularGenerator::mapVisualQml() const { return QStringLiteral("CircularGeneratorMapVisual.qml"); } -QString CircularGenerator::abbreviation() { return tr("C. Gen."); } +QString CircularGenerator::abbreviation() const { return tr("C. Gen."); } -QString CircularGenerator::type() { return generatorType; } +QString CircularGenerator::type() const { return typeString; } bool CircularGenerator::get(Generator &generator) { if (this->_d) { @@ -327,19 +326,21 @@ void CircularGenerator::resetReferenceIfInvalid() { } void CircularGenerator::resetReference() { - auto measurementArea = - getGeoArea(*this->_d->areaList()); + if (this->_d != nullptr) { + auto measurementArea = + getGeoArea(*this->_d->areaList()); - if (measurementArea != nullptr) { - if (measurementArea->center().isValid()) { - setReference(measurementArea->center()); + if (measurementArea != nullptr) { + if (measurementArea->center().isValid()) { + setReference(measurementArea->center()); + } else { + qCWarning(CircularGeneratorLog) + << "measurement area center" << measurementArea->center(); + } } else { - qCWarning(CircularGeneratorLog) - << "measurement area center" << measurementArea->center(); + qCDebug(CircularGeneratorLog) + << "resetReference(): measurement area == nullptr"; } - } else { - qCDebug(CircularGeneratorLog) - << "resetReference(): measurement area == nullptr"; } } @@ -350,8 +351,34 @@ Fact *CircularGenerator::deltaAlpha() { return &_deltaAlpha; } Fact *CircularGenerator::minLength() { return &_minLength; } void CircularGenerator::onAreaListChanged() { - auto *measurementArea = getGeoArea(*this->_d->areaList()); - setMeasurementArea(measurementArea); + if (this->_d != nullptr) { + auto *measurementArea = + getGeoArea(*this->_d->areaList()); + setMeasurementArea(measurementArea); + } +} + +void CircularGenerator::onDataChanged() { + if (this->_d != nullptr) { + connect(this->_d, &AreaData::areaListChanged, this, + &CircularGenerator::onAreaListChanged); + onAreaListChanged(); + } +} + +void CircularGenerator::init() { + connect(this->distance(), &Fact::rawValueChanged, this, + &GeneratorBase::generatorChanged); + connect(this->deltaAlpha(), &Fact::rawValueChanged, this, + &GeneratorBase::generatorChanged); + connect(this->minLength(), &Fact::rawValueChanged, this, + &GeneratorBase::generatorChanged); + connect(this, &CircularGenerator::referenceChanged, this, + &GeneratorBase::generatorChanged); + connect(this, &CircularGenerator::dataChanged, this, + &CircularGenerator::onDataChanged); + onDataChanged(); + setName(tr("Circular Generator")); } void CircularGenerator::setMeasurementArea(MeasurementArea *area) { diff --git a/src/MeasurementComplexItem/CircularGenerator.h b/src/MeasurementComplexItem/CircularGenerator.h index 225a57698..49d6736dd 100644 --- a/src/MeasurementComplexItem/CircularGenerator.h +++ b/src/MeasurementComplexItem/CircularGenerator.h @@ -20,11 +20,11 @@ public: Q_PROPERTY(Fact *deltaAlpha READ deltaAlpha CONSTANT) Q_PROPERTY(Fact *minLength READ minLength CONSTANT) - virtual QString editorQml() override; - virtual QString mapVisualQml() override; + virtual QString editorQml() const override; + virtual QString mapVisualQml() const override; - virtual QString abbreviation() override; - virtual QString type() override; + virtual QString abbreviation() const override; + virtual QString type() const override; virtual bool get(Generator &generator) override; @@ -47,6 +47,7 @@ public: virtual bool load(const QJsonObject &obj, QString &guiErrorMessage) override; static const char *settingsGroup; + static const char *typeString; signals: void referenceChanged(); @@ -55,8 +56,12 @@ public slots: Q_INVOKABLE void resetReferenceIfInvalid(); Q_INVOKABLE void resetReference(); -private: +private slots: void onAreaListChanged(); + void onDataChanged(); + +private: + void init(); void setMeasurementArea(MeasurementArea *area); QGeoCoordinate _reference; diff --git a/src/MeasurementComplexItem/GeneratorBase.cc b/src/MeasurementComplexItem/GeneratorBase.cc index 52113cea1..968d08f12 100644 --- a/src/MeasurementComplexItem/GeneratorBase.cc +++ b/src/MeasurementComplexItem/GeneratorBase.cc @@ -11,20 +11,18 @@ GeneratorBase::GeneratorBase(QObject *parent) : GeneratorBase(nullptr, parent) {} GeneratorBase::GeneratorBase(GeneratorBase::Data d, QObject *parent) - : QObject(parent), _d(d) { - establishConnections(); -} + : QObject(parent), _d(d) {} GeneratorBase::~GeneratorBase() {} bool GeneratorBase::save(QJsonObject &obj) const { - obj[typeKey] = type(); - obj[name] = name(); + obj[typeKey] = this->type(); + obj[nameKey] = this->name(); return true; } bool GeneratorBase::load(const QJsonObject &obj, QString &errorString) { - if (obj.contains[nameKey] && obj[nameKey].isString()) { + if (obj.contains(nameKey) && obj[nameKey].isString()) { setName(obj[nameKey].toString()); return true; } else { @@ -46,18 +44,12 @@ void GeneratorBase::setName(const QString &name) { GeneratorBase::Data GeneratorBase::data() const { return _d; } void GeneratorBase::setData(Data d) { - if (d != _d && d != nullptr) { - deleteConnections(); + if (d != _d) { _d = d; - establishConnections(); emit dataChanged(); } } -void GeneratorBase::establishConnections() {} - -void GeneratorBase::deleteConnections() {} - GeneratorFactory::GeneratorFactory() {} GeneratorFactory *GeneratorFactory::createInstance() { @@ -112,14 +104,14 @@ GeneratorBase *GeneratorFactory::create(const QJsonObject &jsonGenerator, return nullptr; } } else { - errorMessage.append(QObject::tr("Not able to create generator of type") + - " " + - jsonGenerator[GeneratorBase::typeKey].toString()); + errorMessage.append( + QObject::tr("Not able to create generator of type.\n") + " " + + jsonGenerator[GeneratorBase::typeKey].toString()); return nullptr; } } else { errorMessage.append(QObject::tr( - "Not able to load Generator. Impossible to determine type.")); + "Not able to load Generator. Impossible to determine type.\n")); return nullptr; } } diff --git a/src/MeasurementComplexItem/GeneratorBase.h b/src/MeasurementComplexItem/GeneratorBase.h index e5b3373f7..b0ce44f45 100644 --- a/src/MeasurementComplexItem/GeneratorBase.h +++ b/src/MeasurementComplexItem/GeneratorBase.h @@ -53,8 +53,6 @@ signals: void nameChanged(); protected: - virtual void establishConnections(); - virtual void deleteConnections(); Data _d; QString _name; @@ -87,7 +85,7 @@ private: #define REGISTER_GENERATOR(type, creator) \ namespace { \ - auto registered_##type = \ + auto registered = \ GeneratorFactory::instance() -> registerGenerator(type, creator); \ } } // namespace routing diff --git a/src/MeasurementComplexItem/LinearGenerator.cpp b/src/MeasurementComplexItem/LinearGenerator.cpp index f97497936..bc3b6ffff 100644 --- a/src/MeasurementComplexItem/LinearGenerator.cpp +++ b/src/MeasurementComplexItem/LinearGenerator.cpp @@ -14,8 +14,6 @@ namespace routing { namespace { -const QString generatorType = "LinearGenerator"; - GeneratorBase *creator(QObject *parent) { return new LinearGenerator(parent); } const char *distanceKey = "TransectDistance"; @@ -23,7 +21,6 @@ const char *alphaKey = "Alpha"; const char *minLengthKey = "MinLength"; } // namespace -REGISTER_GENERATOR(generatorType, creator) QGC_LOGGING_CATEGORY(LinearGeneratorLog, "LinearGeneratorLog") bool linearTransects(const snake::FPolygon &polygon, @@ -32,9 +29,20 @@ bool linearTransects(const snake::FPolygon &polygon, snake::Length minLength, snake::Transects &transects); const char *LinearGenerator::settingsGroup = "LinearGenerator"; +const char *LinearGenerator::typeString = "LinearGenerator"; + +REGISTER_GENERATOR("LinearGenerator", creator) LinearGenerator::LinearGenerator(QObject *parent) - : LinearGenerator(nullptr, parent) {} + : GeneratorBase(nullptr, parent), + _metaDataMap(FactMetaData::createMapFromJsonFile( + QStringLiteral(":/json/LinearGenerator.SettingsGroup.json"), this)), + _distance(settingsGroup, _metaDataMap[distanceKey]), + _alpha(settingsGroup, _metaDataMap[alphaKey]), + _minLength(settingsGroup, _metaDataMap[minLengthKey]), + _measurementArea(nullptr) { + init(); +} LinearGenerator::LinearGenerator(GeneratorBase::Data d, QObject *parent) : GeneratorBase(d, parent), @@ -43,30 +51,24 @@ LinearGenerator::LinearGenerator(GeneratorBase::Data d, QObject *parent) _distance(settingsGroup, _metaDataMap[distanceKey]), _alpha(settingsGroup, _metaDataMap[alphaKey]), _minLength(settingsGroup, _metaDataMap[minLengthKey]), - _measurementArea(nullptr), _safeArea(nullptr) { - connect(this->distance(), &Fact::rawValueChanged, this, - &GeneratorBase::generatorChanged); - connect(this->alpha(), &Fact::rawValueChanged, this, - &GeneratorBase::generatorChanged); - connect(this->minLength(), &Fact::rawValueChanged, this, - &GeneratorBase::generatorChanged); - connect(this->_d, &AreaData::areaListChanged, this, - &LinearGenerator::onAreaListChanged); - setName(tr("Linear Generator")); + _measurementArea(nullptr) { + init(); } -QString LinearGenerator::editorQml() { +QString LinearGenerator::editorQml() const { return QStringLiteral("LinearGeneratorEditor.qml"); } -QString LinearGenerator::mapVisualQml() { return QStringLiteral(""); } +QString LinearGenerator::mapVisualQml() const { return QStringLiteral(""); } -QString LinearGenerator::abbreviation() { return QStringLiteral("L. Gen."); } +QString LinearGenerator::abbreviation() const { + return QStringLiteral("L. Gen."); +} -QString LinearGenerator::type() { return generatorType; } +QString LinearGenerator::type() const { return typeString; } bool LinearGenerator::get(Generator &generator) { - if (_d) { + if (_d != nullptr) { if (this->_d->isCorrect()) { // Prepare data. auto origin = this->_d->origin(); @@ -268,9 +270,33 @@ Fact *LinearGenerator::alpha() { return &_alpha; } Fact *LinearGenerator::minLength() { return &_minLength; } +void LinearGenerator::init() { + connect(this->distance(), &Fact::rawValueChanged, this, + &GeneratorBase::generatorChanged); + connect(this->alpha(), &Fact::rawValueChanged, this, + &GeneratorBase::generatorChanged); + connect(this->minLength(), &Fact::rawValueChanged, this, + &GeneratorBase::generatorChanged); + connect(this, &LinearGenerator::dataChanged, this, + &LinearGenerator::onDataChanged); + onDataChanged(); + setName(tr("Linear Generator")); +} + void LinearGenerator::onAreaListChanged() { - auto *measurementArea = getGeoArea(*this->_d->areaList()); - setMeasurementArea(measurementArea); + if (this->_d != nullptr) { + auto *measurementArea = + getGeoArea(*this->_d->areaList()); + setMeasurementArea(measurementArea); + } +} + +void LinearGenerator::onDataChanged() { + if (this->_d != nullptr) { + connect(this->_d, &AreaData::areaListChanged, this, + &LinearGenerator::onAreaListChanged); + onAreaListChanged(); + } } void LinearGenerator::setMeasurementArea(MeasurementArea *area) { diff --git a/src/MeasurementComplexItem/LinearGenerator.h b/src/MeasurementComplexItem/LinearGenerator.h index 0e5f2d030..dc3075da3 100644 --- a/src/MeasurementComplexItem/LinearGenerator.h +++ b/src/MeasurementComplexItem/LinearGenerator.h @@ -19,11 +19,11 @@ public: Q_PROPERTY(Fact *alpha READ alpha CONSTANT) Q_PROPERTY(Fact *minLength READ minLength CONSTANT) - virtual QString editorQml() override; - virtual QString mapVisualQml() override; + virtual QString editorQml() const override; + virtual QString mapVisualQml() const override; - virtual QString abbreviation() override; - virtual QString type() override; + virtual QString abbreviation() const override; + virtual QString type() const override; virtual bool get(Generator &generator) override; @@ -43,9 +43,14 @@ public: Fact *minLength(); static const char *settingsGroup; + static const char *typeString; -private: +private slots: void onAreaListChanged(); + void onDataChanged(); + +private: + void init(); void setMeasurementArea(MeasurementArea *area); QMap _metaDataMap; diff --git a/src/MeasurementComplexItem/MeasurementComplexItem.cc b/src/MeasurementComplexItem/MeasurementComplexItem.cc index 607e26d2c..4bca4cc11 100644 --- a/src/MeasurementComplexItem/MeasurementComplexItem.cc +++ b/src/MeasurementComplexItem/MeasurementComplexItem.cc @@ -31,12 +31,16 @@ const char *MeasurementComplexItem::settingsGroup = "MeasurementComplexItem"; const char *MeasurementComplexItem::jsonComplexItemTypeValue = "MeasurementComplexItem"; const QString MeasurementComplexItem::name(tr("Measurement")); + +namespace { const char *variantKey = "Variant"; const char *altitudeKey = "Altitude"; const char *areaDataKey = "AreaData"; const char *variantNamesKey = "VariantNames"; const char *generatorsKey = "Generators"; const char *variantsKey = "Variants"; +const char *generatorIndexKey = "generatorIndex"; +} // namespace MeasurementComplexItem::MeasurementComplexItem( PlanMasterController *masterController, bool flyView, @@ -101,6 +105,7 @@ MeasurementComplexItem::MeasurementComplexItem( [this] { emit this->complexDistanceChanged(); }); resetGenerators(); + startEditing(); qCritical() << "ToDo: _altitude connections missing."; qCritical() << "ToDo: remove generatorNameList and use GeneratorBase::name() " @@ -166,17 +171,12 @@ bool MeasurementComplexItem::load(const QJsonObject &complexObject, } setSequenceNumber(sequenceNumber); - startEditing(); - bool returnValue = true; // load variant if (complexObject.contains(variantKey) && complexObject[variantKey].isDouble()) { _variant.setRawValue(complexObject[variantKey].toInt()); - } else { - returnValue = false; - errorString.append(tr("No route variant number found in file.\n")); } // load altitude @@ -184,8 +184,9 @@ bool MeasurementComplexItem::load(const QJsonObject &complexObject, complexObject[altitudeKey].isDouble()) { _altitude.setRawValue(complexObject[altitudeKey].toDouble()); } else { - returnValue = false; errorString.append(tr("No altitude found in file.\n")); + abortEditing(); + return false; } // load AreaData. @@ -195,18 +196,17 @@ bool MeasurementComplexItem::load(const QJsonObject &complexObject, if (_pCurrentData->load(complexObject[areaDataKey].toObject(), e)) { _pCurrentData->setShowErrorMessages(false); if (!_pCurrentData->isCorrect()) { + errorString.append(_pCurrentData->errorString()); _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; } @@ -263,13 +263,14 @@ bool MeasurementComplexItem::load(const QJsonObject &complexObject, "that the generator was not registered. In the latter case " "use the REGISTER_GENERATOR() for registration"; } - returnValue = false; + abortEditing(); + return false; } } else { - errorString.append(tr( - "Can not determine type of generator. Skipping this generator.")); - returnValue = false; + errorString.append(tr("Can not determine type of generator.\n")); + abortEditing(); + return false; } // insert generators @@ -279,54 +280,97 @@ bool MeasurementComplexItem::load(const QJsonObject &complexObject, } } } else { - returnValue = false; errorString.append( tr("No generators found in file. Leaving generators unchanged.\n")); + abortEditing(); + return false; + } + + // load generator index + bool indexLoaded = false; + if (complexObject.contains(generatorIndexKey) && + complexObject[generatorIndexKey].isDouble()) { + int index = complexObject[generatorIndexKey].toDouble(); + if (index >= 0 && index < _generatorList.size()) { + indexLoaded = true; + switchToGenerator(index); + } + } + if (!indexLoaded) { + switchToGenerator(0); } // load Route Variants + bool variantsSuccess = true; + QVector variantVector; if (complexObject.contains(variantsKey) && complexObject[variantsKey].isArray()) { - QVector variantVector; - // load variants to variantVector for further processing. for (const auto valueRef : complexObject[variantsKey].toArray()) { if (valueRef.isArray()) { - const auto jsonVariant = valueRef.toObject(); + const auto jsonVariant = valueRef.toArray(); Variant variant; QString e; - if (JsonHelper::loadGeoCoordinateArray(jsonVariant, false, variantList, + if (JsonHelper::loadGeoCoordinateArray(jsonVariant, false, variant, e)) { if (variant.size() > 0) { variantVector.append(std::move(variant)); } else { - errorString.append("Empty route variant skipped.\n"); - returnValue = false; + qCDebug(MeasurementComplexItemLog) + << "Empty route variant skipped.\n" + << valueRef.type(); } } else { - errorString.append(e); - errorString.append("\n"); - returnValue = false; + qCDebug(MeasurementComplexItemLog) + << "Error loading route variant: " << e; + variantsSuccess = false; } } else { qCDebug(MeasurementComplexItemLog) << "json variant is not an array but of type: " << valueRef.type(); - returnValue = false; + variantsSuccess = false; } } // Check if variants are covered by safe area. - qCritical() << "Continue here!"; + if (variantsSuccess) { + auto safeArea = _pCurrentData->safeArea(); + if (safeArea != nullptr) { + QGeoCoordinate origin = + safeArea->pathModel().value(0)->coordinate(); + snake::FPolygon safeAreaENU; + snake::areaToEnu(origin, safeArea->coordinateList(), safeAreaENU); + for (const auto &variant : variantVector) { + snake::FLineString varENU; + for (const auto &vertex : variant) { + snake::FPoint vertexENU; + snake::toENU(origin, vertex.value(), vertexENU); + varENU.push_back(vertexENU); + } + + if (!bg::covered_by(varENU, safeAreaENU)) { + variantsSuccess = false; + break; + } + } + } else { + variantsSuccess = false; + } + } } else { - returnValue = false; - errorString.append(tr( - "No route variants found in file. Calculating new route variants.\n")); - stopEditing(); + variantsSuccess = false; } - stopEditing(false); - return returnValue; + if (!variantsSuccess) { + stopEditing(); // stop editing and trigger update + } else { + _variantVector.swap(variantVector); + qCritical() << "add variant names and set variant"; + stopEditing( + false /*doUpdate*/); // does noting if editing was already stopped + } + return true; } double @@ -392,24 +436,25 @@ void MeasurementComplexItem::save(QJsonArray &planItems) { for (int i = 0; i < _generatorList.size(); ++i) { auto const gen = _generatorList[i]; auto const &name = _generatorNameList[i]; - QJsonObject innerObj; - if (!gen->save(innerObj)) { + QJsonObject obj; + if (!gen->save(obj)) { qCDebug(MeasurementComplexItemLog) << "save(): not able to save generator: " << name; return; } else { - QJsonObject outerObj; - outerObj[name] = innerObj; - generatorArray.append(outerObj); + generatorArray.append(obj); } } saveObject[generatorsKey] = generatorArray; + // generator index + saveObject[generatorIndex] = generatorIndex(); + // Route Variants QJsonArray variantsArray; for (auto const &route : _variantVector) { QJsonValue variant; - if (!(route.size() == 0)) { + if (route.size() > 0) { JsonHelper::saveGeoCoordinateArray(route, false, variant); } else { JsonHelper::saveGeoCoordinateArray(_route, false, variant); @@ -814,19 +859,17 @@ int MeasurementComplexItem::lastSequenceNumber() const { bool MeasurementComplexItem::addGenerator(const QString &name, routing::GeneratorBase *g) { if (name.isEmpty()) { - qCDebug(MeasurementComplexItemLog) - << "registerGenerator(): empty name string."; + qCDebug(MeasurementComplexItemLog) << "addGenerator(): empty name string."; return false; } if (!g) { - qCDebug(MeasurementComplexItemLog) - << "registerGenerator(): empty generator."; + qCDebug(MeasurementComplexItemLog) << "addGenerator(): empty generator."; return false; } if (this->_generatorNameList.contains(name)) { - qCDebug(MeasurementComplexItemLog) << "registerGenerator(): generator " + qCDebug(MeasurementComplexItemLog) << "addGenerator(): generator " "already registered."; return false; } else { @@ -851,8 +894,6 @@ bool MeasurementComplexItem::removeGenerator(const QString &name) { _setGenerator(this->_generatorList.at(index - 1)); } else { _setGenerator(nullptr); - qCDebug(MeasurementComplexItemLog) - << "unregisterGenerator(): last generator unregistered."; } } @@ -864,20 +905,19 @@ bool MeasurementComplexItem::removeGenerator(const QString &name) { return true; } else { qCDebug(MeasurementComplexItemLog) - << "unregisterGenerator(): generator " << name << " not registered."; + << "removeGenerator(): generator " << name << " not registered."; return false; } } bool MeasurementComplexItem::removeGenerator(int index) { - if (index > 0 && index < this->_generatorNameList.size()) { + if (index >= 0 && index < this->_generatorNameList.size()) { return removeGenerator(this->_generatorNameList.at(index)); } else { - qCDebug(MeasurementComplexItemLog) - << "unregisterGenerator(): index (" << index - << ") out" - "of bounds ( " - << this->_generatorList.size() << " )."; + qCDebug(MeasurementComplexItemLog) << "removeGenerator(): index (" << index + << ") out" + "of bounds ( " + << this->_generatorList.size() << " )."; return false; } } @@ -895,7 +935,7 @@ bool MeasurementComplexItem::switchToGenerator(const QString &name) { } bool MeasurementComplexItem::switchToGenerator(int index) { - if (index >= 0) { + if (index >= 0 && index < _generatorList.size()) { _setGenerator(this->_generatorList.at(index)); return true; } else { @@ -932,7 +972,7 @@ const routing::GeneratorBase *MeasurementComplexItem::generator() const { const routing::GeneratorBase * MeasurementComplexItem::generator(int index) const { - if (index > 0 && index < _generatorList.size()) { + if (index >= 0 && index < _generatorList.size()) { return _generatorList[index]; } else { return nullptr; @@ -940,7 +980,7 @@ MeasurementComplexItem::generator(int index) const { } routing::GeneratorBase *MeasurementComplexItem::generator(int index) { - if (index > 0 && index < _generatorList.size()) { + if (index >= 0 && index < _generatorList.size()) { return _generatorList[index]; } else { return nullptr; @@ -961,17 +1001,20 @@ void MeasurementComplexItem::startEditing() { bool MeasurementComplexItem::stopEditing(bool doUpdate) { if (editing()) { + bool isDifferent = *_pEditorData != *_pAreaData; bool correct = _pEditorData->isCorrect(); if (correct) { *_pAreaData = *_pEditorData; } _setAreaData(_pAreaData); _setState(STATE::IDLE); - if (doUpdate && correct && *_pEditorData != *_pAreaData) { + bool updated = false; + if (doUpdate && correct && isDifferent) { + updated = true; _updateRoute(); } - return correct; + return updated; } return false; } diff --git a/src/MeasurementComplexItem/MeasurementComplexItem.h b/src/MeasurementComplexItem/MeasurementComplexItem.h index fe0dcea63..ae244dd27 100644 --- a/src/MeasurementComplexItem/MeasurementComplexItem.h +++ b/src/MeasurementComplexItem/MeasurementComplexItem.h @@ -123,7 +123,9 @@ public: //! editingStart() if it is invalid. Triggers a route update. //! //! \param doUpdate No route update will be triggered if false, route update - //! will eventually be triggered if true. \return Returns true if a route + //! will eventually be triggered if true. + //! + //! \return Returns true if a route //! update was triggered, false either. //! Q_INVOKABLE bool stopEditing(bool doUpdate = true); @@ -145,7 +147,7 @@ public: QStringList variantNames() const; bool calculating() const; - bool editing() const; + bool editing() const; // set to true on creation bool idle() const; bool followTerrain() const; diff --git a/src/MeasurementComplexItem/qml/AreaDataEditor.qml b/src/MeasurementComplexItem/qml/AreaDataEditor.qml index 73461d9ff..e2042ab51 100644 --- a/src/MeasurementComplexItem/qml/AreaDataEditor.qml +++ b/src/MeasurementComplexItem/qml/AreaDataEditor.qml @@ -23,11 +23,8 @@ GridLayout { Component.onCompleted: { console.assert(missionItem !== undefined, "please set the missionItem property") - checkedChangedHandler() } - onCheckedChanged: checkedChangedHandler() - ExclusiveGroup{id:areaGroup} Repeater{ @@ -115,13 +112,5 @@ GridLayout { _areaData.intersection() } } - - function checkedChangedHandler(){ - if (_root.checked){ - missionItem.startEditing() - } else { - missionItem.stopEditing() - } - } } diff --git a/src/MeasurementComplexItem/qml/MeasurementItemEditor.qml b/src/MeasurementComplexItem/qml/MeasurementItemEditor.qml index bdce46a02..b9e978ad1 100644 --- a/src/MeasurementComplexItem/qml/MeasurementItemEditor.qml +++ b/src/MeasurementComplexItem/qml/MeasurementItemEditor.qml @@ -65,7 +65,7 @@ Rectangle { Layout.fillWidth: true Layout.columnSpan: 2 onClicked:{ - areaDataEditor.checked = true + _missionItem.startEditing() } } @@ -75,7 +75,7 @@ Rectangle { visible: areaDataEditor.visible onClicked: { if (_areaData.isCorrect()){ - parameterEditor.checked = true + _missionItem.stopEditing() } } } @@ -86,32 +86,18 @@ Rectangle { Layout.fillWidth: true onClicked:{ missionItem.abortEditing() - parameterEditor.checked = true } } } // editorSelector - ExclusiveGroup { id:editorGroup} - MCI.ParameterEditor{ id:parameterEditor missionItem: _root._missionItem availableWidth: mainColumn.width + checked: !_missionItem.editing visible: checked - - property ExclusiveGroup group: editorGroup - - onGroupChanged: { - if (group){ - group.bindCheckable(parameterEditor) - } - } - - Component.onCompleted: { - checked = false - } } MCI.AreaDataEditor{ @@ -119,19 +105,8 @@ Rectangle { missionItem: _root._missionItem availableWidth: mainColumn.width + checked: _missionItem.editing visible: checked - - property ExclusiveGroup group: editorGroup - - onGroupChanged: { - if (group){ - group.bindCheckable(areaDataEditor) - } - } - - Component.onCompleted: { - checked = true - } } } // main Column diff --git a/src/MeasurementComplexItem/qml/MeasurementItemMapVisual.qml b/src/MeasurementComplexItem/qml/MeasurementItemMapVisual.qml index 8e94bd5d0..99b99c0ee 100644 --- a/src/MeasurementComplexItem/qml/MeasurementItemMapVisual.qml +++ b/src/MeasurementComplexItem/qml/MeasurementItemMapVisual.qml @@ -55,9 +55,12 @@ Item { Component.onCompleted: { console.assert(map != undefined, "please set the map property") - var bbox = boundingBox() - _missionItem.areaData.initialize(bbox[0], bbox[1]) -// _addEntryCoordinate() + + if (!_missionItem.areaData.initialized()){ + var bbox = boundingBox() + _missionItem.areaData.initialize(bbox[0], bbox[1]) + } + // _addEntryCoordinate() // _addExitCoordinate() _addTransects() _addGeneratorVisuals() @@ -174,7 +177,7 @@ Item { // Generator visuals function _addGeneratorVisuals(){ - if (_generator.mapVisualQml && !_generatorObject) { + if (_generator && _generator.mapVisualQml && !_generatorObject) { var component = Qt.createComponent(_generator.mapVisualQml) if (component.status === Component.Error) { console.log("Error loading Qml: ", diff --git a/src/MeasurementComplexItem/qml/ParameterEditor.qml b/src/MeasurementComplexItem/qml/ParameterEditor.qml index bd06a848a..b7ddbad1c 100644 --- a/src/MeasurementComplexItem/qml/ParameterEditor.qml +++ b/src/MeasurementComplexItem/qml/ParameterEditor.qml @@ -187,7 +187,7 @@ ColumnLayout { } // indicator column function _addGeneratorEditor(){ - if (_generator.editorQml && !_generatorEditor) { + if (_generator && _generator.editorQml && !_generatorEditor) { var component = Qt.createComponent(_generator.editorQml) if (component.status === Component.Error) { console.log("Error loading Qml: ", -- 2.22.0