diff --git a/qgcresources.qrc b/qgcresources.qrc index c6c6cf321bf249f9a4d74fb9a8a25ef7395bdb89..dda957c4ec49f16b5f271c02b7f1ff12cfc53c99 100644 --- a/qgcresources.qrc +++ b/qgcresources.qrc @@ -18,7 +18,7 @@ resources/counter-clockwise-arrow.svg resources/chevron-down.svg resources/chevron-up.svg - resources/DropArrow.svg + resources/DropArrow.svg resources/gear-black.svg resources/gear-white.svg resources/helicoptericon.svg @@ -34,7 +34,7 @@ resources/Play.svg resources/PowerButton.svg resources/QGCLogoBlack.svg - resources/QGCLogoFull.svg + resources/QGCLogoFull.svg resources/QGCLogoWhite.svg resources/QGCLogoArrow.svg resources/QGroundControlConnect.svg @@ -56,6 +56,7 @@ resources/street.png resources/measurement.png resources/calculator.png + resources/fish.svg resources/firmware/3drradio.png diff --git a/qgroundcontrol.qrc b/qgroundcontrol.qrc index b2dc3e37e65e38d04f477e4d26b0b2b361df3da2..6774f22a8b9bfb67659de2c4c8c052f554a55807 100644 --- a/qgroundcontrol.qrc +++ b/qgroundcontrol.qrc @@ -293,6 +293,7 @@ src/MeasurementComplexItem/qml/AreaDataEditor.qml src/MeasurementComplexItem/qml/ParameterEditor.qml src/MeasurementComplexItem/qml/MeasurementComplexItem.qmldir + src/MeasurementComplexItem/qml/NemoEditor.qml src/FirstRunPromptDialogs/UnitsFirstRunPrompt.qml diff --git a/resources/InstrumentValueIcons/.directory b/resources/InstrumentValueIcons/.directory new file mode 100644 index 0000000000000000000000000000000000000000..deeb4ca199fd64c4dc8beb4d956030d9ca0ba6bf --- /dev/null +++ b/resources/InstrumentValueIcons/.directory @@ -0,0 +1,4 @@ +[Dolphin] +PreviewsShown=true +Timestamp=2020,12,19,15,18,21 +Version=4 diff --git a/resources/credits.txt b/resources/credits.txt new file mode 100644 index 0000000000000000000000000000000000000000..f645d7379802e0e1938b6f9d64f1409f07807cae --- /dev/null +++ b/resources/credits.txt @@ -0,0 +1 @@ +fish.svg: from https://commons.wikimedia.org/wiki/File:Font_Awesome_5_solid_fish.svg diff --git a/resources/fish.svg b/resources/fish.svg new file mode 100644 index 0000000000000000000000000000000000000000..b5e0bf2a719dadcd790006b43ed15cd264713e09 --- /dev/null +++ b/resources/fish.svg @@ -0,0 +1,5 @@ + + \ No newline at end of file diff --git a/src/MeasurementComplexItem/AreaData.cc b/src/MeasurementComplexItem/AreaData.cc index a8579e7f1b9267ad866b39781603de1febdc13a8..165e531a5de0069d9f267fe4e9f49b532f1f6e74 100644 --- a/src/MeasurementComplexItem/AreaData.cc +++ b/src/MeasurementComplexItem/AreaData.cc @@ -126,8 +126,9 @@ bool AreaData::isCorrect(bool showError) { // ss << "safeAreaENU: " << bg::wkt(safeAreaENU) << std::endl; // qDebug() << ss.str().c_str(); if (!bg::covered_by(measurementAreaENU, safeAreaENU)) { - _processError(tr("Measurement Area not inside Safe Area. Please adjust " - "the Measurement Area.\n"), + _processError(tr("Measurement Area is not covered by Safe " + "Area. Please adjust " + "the areas accordingly.\n"), showError); return false; } @@ -228,10 +229,10 @@ void AreaData::intersection(bool showError) { boost::geometry::intersection(measurementAreaENU, safeAreaENU, outputENU); if (outputENU.size() < 1 || outputENU[0].outer().size() < 4) { - _processError( - "Intersection did't deliver any result. Measurement Area and " - "Safe Area must touch each other.", - showError); + _processError("Intersection did't deliver any result. The Measurement " + "Area(s) and " + "The Safe Area must touch each other.", + showError); return; } @@ -266,11 +267,29 @@ void AreaData::intersection(bool showError) { } } -MeasurementArea *AreaData::measurementArea() { - return getGeoArea(_areaList); +QVector AreaData::measurementAreaArray() { + return getGeoAreaList(_areaList); +} + +QVector AreaData::safeAreaArray() { + return getGeoAreaList(_areaList); } -SafeArea *AreaData::safeArea() { return getGeoArea(_areaList); } +QmlObjectListModel *AreaData::measurementAreaList() { + _measurementAreaList.clear(); + auto array = getGeoAreaList(_areaList); + for (auto area : array) + _measurementAreaList.append(area); + return &_measurementAreaList; +} + +QmlObjectListModel *AreaData::safeAreaList() { + _safeAreaList.clear(); + auto array = getGeoAreaList(_areaList); + for (auto &area : array) + _safeAreaList.append(area); + return &_safeAreaList; +} bool AreaData::operator==(const AreaData &other) const { if (_areaList.count() == other._areaList.count()) { @@ -442,13 +461,13 @@ bool AreaData::_getAreas(MeasurementArea **measurementArea, SafeArea **safeArea, *measurementArea = getGeoArea(_areaList); if (*measurementArea == nullptr) { _processError( - tr("Measurement Area missing. Please define a measurement area."), + tr("Measurement Area is missing. Please define a Measurement Area."), showError); return false; } *safeArea = getGeoArea(_areaList); if (*safeArea == nullptr) { - _processError(tr("Safe Area missing. Please define a safe area."), + _processError(tr("Safe Area is missing. Please define a Safe Area."), showError); return false; } diff --git a/src/MeasurementComplexItem/AreaData.h b/src/MeasurementComplexItem/AreaData.h index f2f3ac2c2f1d3cd31b2fed4638ec5d9c97369468..3f87865f6a126c2f58ce06a0eb8c081bcdb428cc 100644 --- a/src/MeasurementComplexItem/AreaData.h +++ b/src/MeasurementComplexItem/AreaData.h @@ -20,6 +20,10 @@ public: AreaData &operator=(const AreaData &other); Q_PROPERTY(QmlObjectListModel *areaList READ areaList NOTIFY areaListChanged) + Q_PROPERTY(QmlObjectListModel *measurementAreaList READ measurementAreaList + NOTIFY areaListChanged) + Q_PROPERTY( + QmlObjectListModel *safeAreaList READ safeAreaList NOTIFY areaListChanged) Q_PROPERTY(QString errorString READ errorString NOTIFY error) // Member Methodes @@ -70,8 +74,10 @@ public: Q_INVOKABLE bool initialized(); Q_INVOKABLE void intersection(bool showError = true); - Q_INVOKABLE MeasurementArea *measurementArea(); - Q_INVOKABLE SafeArea *safeArea(); + QVector measurementAreaArray(); + QVector safeAreaArray(); + QmlObjectListModel *measurementAreaList(); + QmlObjectListModel *safeAreaList(); bool operator==(const AreaData &other) const; bool operator!=(const AreaData &other) const; @@ -97,5 +103,7 @@ private: QGeoCoordinate _origin; QmlObjectListModel _areaList; + QmlObjectListModel _measurementAreaList; + QmlObjectListModel _safeAreaList; QString _errorString; }; diff --git a/src/MeasurementComplexItem/GeneratorBase.h b/src/MeasurementComplexItem/GeneratorBase.h index b0ce44f455495ca5e87c3525880c66f5c9cda01c..4d1f6daf45cbe8dd012d167454f3be6692a7a2ff 100644 --- a/src/MeasurementComplexItem/GeneratorBase.h +++ b/src/MeasurementComplexItem/GeneratorBase.h @@ -83,9 +83,9 @@ private: std::map _creatorMap; }; +#define pGeneratorFactory ::routing::GeneratorFactory::instance() #define REGISTER_GENERATOR(type, creator) \ namespace { \ - auto registered = \ - GeneratorFactory::instance() -> registerGenerator(type, creator); \ + auto registered = pGeneratorFactory -> registerGenerator(type, creator); \ } } // namespace routing diff --git a/src/MeasurementComplexItem/GenericSingelton.h b/src/MeasurementComplexItem/GenericSingelton.h index 93e1ec0d5b684d8059b896f607a4851018b611ae..940d07c05853f6e5bcc4bc55df8a703ac0b1f6c8 100644 --- a/src/MeasurementComplexItem/GenericSingelton.h +++ b/src/MeasurementComplexItem/GenericSingelton.h @@ -3,6 +3,8 @@ #include #include +// from https://stackoverflow.com/questions/46172607/qt-singleton-implementation + template class GenericSingelton { private: typedef T *(*CreateInstanceFunction)(); diff --git a/src/MeasurementComplexItem/MeasurementComplexItem.cc b/src/MeasurementComplexItem/MeasurementComplexItem.cc index 723ccbf4b62845abb6da8861b8642f2f906d01af..d287a3032a2a56df9cf4c698c545225565af7ccf 100644 --- a/src/MeasurementComplexItem/MeasurementComplexItem.cc +++ b/src/MeasurementComplexItem/MeasurementComplexItem.cc @@ -247,8 +247,7 @@ bool MeasurementComplexItem::load(const QJsonObject &complexObject, QString e; // create generator - auto gen = routing::GeneratorFactory::instance()->create( - jsonGen, e, &parent /*parent*/); + auto gen = pGeneratorFactory->create(jsonGen, e, &parent /*parent*/); if (gen != nullptr) { // remove generators of same type and insert this generator. @@ -267,7 +266,7 @@ bool MeasurementComplexItem::load(const QJsonObject &complexObject, errorString.append( tr("Error loading generator of type ") + jsonGen[routing::GeneratorBase::typeKey].toString() + ".\n"); - if (!routing::GeneratorFactory::instance()->registered( + if (!pGeneratorFactory->registered( jsonGen[routing::GeneratorBase::typeKey].toString())) { errorString.append(tr("This type is unknown.\n")); qCritical() @@ -360,8 +359,10 @@ bool MeasurementComplexItem::load(const QJsonObject &complexObject, // Check if variants are covered by safe area. if (variantsSuccess) { - auto safeArea = _pCurrentData->safeArea(); - if (safeArea != nullptr) { + auto safeAreaArray = _pCurrentData->safeAreaArray(); + + if (safeAreaArray.size() > 0 && safeAreaArray.at(0) != nullptr) { + auto safeArea = safeAreaArray[0]; QGeoCoordinate origin = safeArea->pathModel().value(0)->coordinate(); snake::FPolygon safeAreaENU; @@ -733,8 +734,11 @@ void MeasurementComplexItem::_updateFlightpathSegments() { if (hasCollisionOld != hasCollision) { emit terrainCollisionChanged(hasCollision); } - if (_pAreaData->measurementArea() != nullptr) { - _pAreaData->measurementArea()->setShowAltColor(hasCollision); + auto measurementAreaArray = _pAreaData->measurementAreaArray(); + for (auto area : measurementAreaArray) { + if (area != nullptr) { + area->setShowAltColor(hasCollision); + } } _masterController->missionController()->recalcTerrainProfile(); @@ -782,6 +786,20 @@ void MeasurementComplexItem::_updateRoute() { if (this->_pAreaData->isCorrect()) { + auto measurmentAreaArray = _pAreaData->measurementAreaArray(); + bool measurementComplete = true; + for (const auto &area : measurmentAreaArray) { + if (!area->measurementCompleted()) { + measurementComplete = false; + } + } + + if (measurementComplete) { + qCDebug(MeasurementComplexItemLog) + << "_updateWorker(): measurement complete!"; + return; + } + // Prepare data. auto origin = this->_pAreaData->origin(); origin.setAltitude(0); @@ -1039,13 +1057,13 @@ void MeasurementComplexItem::resetGenerators() { removeGenerator(0); } - auto lg = routing::GeneratorFactory::instance()->create( - routing::LinearGenerator::typeString, this); + auto lg = + pGeneratorFactory->create(routing::LinearGenerator::typeString, this); lg->setData(this->_pAreaData); addGenerator(lg); - auto cg = routing::GeneratorFactory::instance()->create( - routing::CircularGenerator::typeString, this); + auto cg = + pGeneratorFactory->create(routing::CircularGenerator::typeString, this); cg->setData(this->_pAreaData); addGenerator(cg); } @@ -1139,6 +1157,24 @@ void MeasurementComplexItem::abortEditing() { } } +void MeasurementComplexItem::reset() { + if (editing()) { + *_pEditorData = *_pAreaData; + } +} + +bool MeasurementComplexItem::initialize(const QGeoCoordinate &bottomLeft, + const QGeoCoordinate &topRight) { + bool r1 = _pAreaData->initialize(bottomLeft, topRight); + bool r2 = _pEditorData->initialize(bottomLeft, topRight); + + return r1 && r2; +} + +bool MeasurementComplexItem::initialized() { + return _pCurrentData->initialized(); +} + void MeasurementComplexItem::_storeRoutingData( MeasurementComplexItem::PtrRoutingData pRoute) { if (this->_state == STATE::ROUTING) { diff --git a/src/MeasurementComplexItem/MeasurementComplexItem.h b/src/MeasurementComplexItem/MeasurementComplexItem.h index 0c20fd1e6dcc3e2aa42a74fe8e675b9b97d6fc3f..f87224987f65305b8737deefb4f61cfc1830c127 100644 --- a/src/MeasurementComplexItem/MeasurementComplexItem.h +++ b/src/MeasurementComplexItem/MeasurementComplexItem.h @@ -174,6 +174,31 @@ public: //! editingStart(). //! Q_INVOKABLE void abortEditing(); + //! + //! \brief reset Resets the areas to the state before startEditing(). + //! + //! Resets the areas to the state before startEditing(). Does nothing if + //! editinge() == false. + //! + Q_INVOKABLE void reset(); + + //! + //! \brief initialize Initializes the areas in a valid way, such that they + //! area inside the bounding box. \param bottomLeft bottom left corner of the + //! bounding box. \param topRight top right corner of the bounding box. \note + //! Behavior is undefined, if \p bottomLeft and \p topRight are not the bottom + //! left and the top right corner of the bounding box. \return Returns true on + //! succes, false either. + //! + Q_INVOKABLE bool initialize(const QGeoCoordinate &bottomLeft, + const QGeoCoordinate &topRight); + //! + //! \brief initialized Checks if area data is initialized + //! \return Returns true if area list contains a SafeArea and a + //! MeasurementArea and both areas have at least three vertices, returns false + //! either. + //! + Q_INVOKABLE bool initialized(); // Property getters const AreaData *areaData() const; diff --git a/src/MeasurementComplexItem/NemoInterface.cpp b/src/MeasurementComplexItem/NemoInterface.cpp index 94a61efa883a5d5526c0362dce2fe32eef9d018c..afd765cf4a3d0f40eb8fc03156fc13eea80c0fd3 100644 --- a/src/MeasurementComplexItem/NemoInterface.cpp +++ b/src/MeasurementComplexItem/NemoInterface.cpp @@ -12,6 +12,7 @@ #include +#include "GenericSingelton.h" #include "geometry/MeasurementArea.h" #include "geometry/snake.h" #include "nemo_interface/QNemoHeartbeat.h" @@ -426,8 +427,15 @@ bool NemoInterface::Impl::setStatus(NemoInterface::STATUS s) { // =============================================================== // NemoInterface -NemoInterface::NemoInterface(QObject *parent) - : QObject(parent), pImpl(std::make_unique(this)) {} +NemoInterface::NemoInterface() + : QObject(), pImpl(std::make_unique(this)) {} + +NemoInterface *NemoInterface::createInstance() { return new NemoInterface(); } + +NemoInterface *NemoInterface::instance() { + return GenericSingelton::instance( + NemoInterface::createInstance); +} NemoInterface::~NemoInterface() {} @@ -449,9 +457,7 @@ bool NemoInterface::hasTileData(const TileData &tileData) const { return this->pImpl->hasTileData(tileData); } -int NemoInterface::status() const { return integral(this->pImpl->status()); } - -NemoInterface::STATUS NemoInterface::statusEnum() const { +NemoInterface::STATUS NemoInterface::status() const { return this->pImpl->status(); } diff --git a/src/MeasurementComplexItem/NemoInterface.h b/src/MeasurementComplexItem/NemoInterface.h index 459f02917dae3f177ef96e5579db979054c80c31..681d3251ca8543d3928d13d5756601d184bc028a 100644 --- a/src/MeasurementComplexItem/NemoInterface.h +++ b/src/MeasurementComplexItem/NemoInterface.h @@ -12,7 +12,14 @@ class NemoInterface : public QObject { class Impl; using PImpl = std::unique_ptr; + NemoInterface(); + NemoInterface(NemoInterface &other) = delete; + static NemoInterface *createInstance(); + public: + ~NemoInterface() override; + static NemoInterface *instance(); + enum class STATUS { NOT_CONNECTED = 0, HEARTBEAT_DETECTED = 1, @@ -20,11 +27,9 @@ public: TIMEOUT = -1, INVALID_HEARTBEAT = -2 }; + Q_ENUM(STATUS) - explicit NemoInterface(QObject *parent = nullptr); - ~NemoInterface() override; - - Q_PROPERTY(int status READ status NOTIFY statusChanged) + Q_PROPERTY(STATUS status READ status NOTIFY statusChanged) Q_PROPERTY(QString statusString READ statusString NOTIFY statusChanged) Q_PROPERTY(QVector progress READ progress NOTIFY progressChanged) Q_PROPERTY(QString editorQml READ editorQml CONSTANT) @@ -40,8 +45,7 @@ public: void setAutoPublish(bool ap); void setHoldProgress(bool hp); - int status() const; - STATUS statusEnum() const; + STATUS status() const; QString statusString() const; QVector progress() const; QString editorQml(); @@ -55,3 +59,5 @@ signals: private: PImpl pImpl; }; + +#define pNemoInterface NemoInterface::instance() diff --git a/src/MeasurementComplexItem/geometry/GeoArea.h b/src/MeasurementComplexItem/geometry/GeoArea.h index 0bd637ad8ff007de4517494b8ce8ebc24ca87159..9dff92211fb42e5982f3d238e4a7ee8fffa89bf9 100644 --- a/src/MeasurementComplexItem/geometry/GeoArea.h +++ b/src/MeasurementComplexItem/geometry/GeoArea.h @@ -56,8 +56,14 @@ private: // Example usage: // QmlObjecListModel list; // .... add areas .... -// auto area = getArea(list); // returns the first -// WimaMeasurementArea or nullptr +// auto area = getGeoArea(list); // returns the first +// MeasurementArea or nullptr +//! \example +//! +//! QmlObjecListModel list; +//! // .... add areas .... +//! auto area = getGeoArea(list); // returns the first +//! MeasurementArea or nullptr template inline AreaPtr getGeoArea(QObjectList &list) { static_assert(std::is_pointer::value, @@ -72,5 +78,28 @@ inline AreaPtr getGeoArea(QObjectList &list) { return nullptr; } +//! \example +//! +//! QmlObjecListModel list; +//! // .... add areas .... +//! auto areaArray = getGeoAreaArray(list); // returns a +//! QList +//! // containing all MeasurementArea's inside list +template class Container = QList, + class QObjectList> +inline Container getGeoAreaList(QObjectList &list) { + static_assert(std::is_pointer::value, + "AreaPtr must be a pointer type."); + Container out; + for (int i = 0; i < list.count(); ++i) { + auto obj = list[i]; + auto area = qobject_cast(obj); + if (area != nullptr) { + out.append(area); + } + } + return out; +} + bool copyAreaList(const QmlObjectListModel &from, QmlObjectListModel &to, QObject *parent); diff --git a/src/MeasurementComplexItem/geometry/MeasurementArea.cc b/src/MeasurementComplexItem/geometry/MeasurementArea.cc index af45d7a10f01871e41e61fae198efc61e8400d83..84080c576536720422f5dda30daa49f0f3256057 100644 --- a/src/MeasurementComplexItem/geometry/MeasurementArea.cc +++ b/src/MeasurementComplexItem/geometry/MeasurementArea.cc @@ -2,6 +2,7 @@ #include "QtConcurrentRun" #include "nemo_interface/SnakeTile.h" #include "snake.h" +#include #include @@ -170,7 +171,7 @@ MeasurementArea::MeasurementArea(QObject *parent) this /* QObject parent */)), _showTiles(SettingsFact(settingsGroup, _metaDataMap[showTilesKey], this /* QObject parent */)), - _state(STATE::IDLE) { + _holdProgress(false), _state(STATE::IDLE) { init(); } @@ -188,7 +189,7 @@ MeasurementArea::MeasurementArea(const MeasurementArea &other, QObject *parent) this /* QObject parent */)), _showTiles(SettingsFact(settingsGroup, _metaDataMap[showTilesKey], this /* QObject parent */)), - _state(STATE::IDLE) { + _holdProgress(false), _state(STATE::IDLE) { init(); disableUpdate(); @@ -272,6 +273,19 @@ int MeasurementArea::maxTiles() const { return SNAKE_MAX_TILES; } bool MeasurementArea::ready() const { return this->_state == STATE::IDLE; } +bool MeasurementArea::measurementCompleted() const { + if (ready()) { + for (const auto &p : _progress) { + if (p != 100) { + return false; + } + } + return true; + } else { + return false; + } +} + bool MeasurementArea::saveToJson(QJsonObject &json) { if (ready()) { if (this->GeoArea::saveToJson(json)) { @@ -406,15 +420,41 @@ bool MeasurementArea::isCorrect() { bool MeasurementArea::setProgress(const QVector &p) { if (ready()) { - if (p.size() == this->tiles()->count() && this->_progress != p) { + if (!_holdProgress && p.size() == this->tiles()->count() && + this->_progress != p) { this->_progress = p; emit progressChanged(); emit progressAccepted(); return true; } } + emit progressNotAccepted(); return false; } + +void MeasurementArea::randomProgress() { + if (ready()) { + std::srand(std::time(nullptr)); + for (auto &p : _progress) { + p += std::rand() % 100; + if (p > 100) { + p = 100; + } + } + + emit progressChanged(); + } +} + +void MeasurementArea::resetProgress() { + if (ready()) { + for (auto &p : _progress) { + p = 0; + } + + emit progressChanged(); + } +} //! //! \brief MeasurementArea::doUpdate //! \pre MeasurementArea::deferUpdate must be called first, don't call @@ -576,3 +616,12 @@ void MeasurementArea::setState(MeasurementArea::STATE s) { } } } + +bool MeasurementArea::holdProgress() const { return _holdProgress; } + +void MeasurementArea::setHoldProgress(bool holdProgress) { + if (_holdProgress != holdProgress) { + _holdProgress = holdProgress; + emit holdProgressChanged(); + } +} diff --git a/src/MeasurementComplexItem/geometry/MeasurementArea.h b/src/MeasurementComplexItem/geometry/MeasurementArea.h index ac0a3ad8ed30e644e332a5612466d08714f48491..6b3710e0c90e5681e740e34b16c04cb19fc61577 100644 --- a/src/MeasurementComplexItem/geometry/MeasurementArea.h +++ b/src/MeasurementComplexItem/geometry/MeasurementArea.h @@ -46,6 +46,8 @@ public: Q_PROPERTY(QmlObjectListModel *tiles READ tiles NOTIFY tilesChanged) Q_PROPERTY(int maxTiles READ maxTiles NOTIFY maxTilesChanged) Q_PROPERTY(QVector progress READ progressQml NOTIFY progressChanged) + Q_PROPERTY(bool holdProgress READ holdProgress WRITE setHoldProgress NOTIFY + holdProgressChanged) // Overrides from GeoArea QString mapVisualQML(void) const override; @@ -69,10 +71,24 @@ public: int maxTiles() const; bool ready() const; + bool measurementCompleted() const; + // Static Variables static const char *settingsGroup; static const char *nameString; + //! + //! \brief holdProgress + //! \return Returns a copy of the holdProgress variable. + //! + bool holdProgress() const; + //! + //! \brief setHoldProgress Sets the holdProgress variable to \p holdProgress. + //! \note If holdProgress() == true, than setProgress() will do nothing, but + //! return false and emit the progressNotAccepted() signal. + //! + void setHoldProgress(bool holdProgress); + signals: void tilesChanged(); void maxTilesChanged(); @@ -80,9 +96,12 @@ signals: void progressAccepted(); void progressNotAccepted(); void readyChanged(); + void holdProgressChanged(); public slots: bool setProgress(const QVector &p); + Q_INVOKABLE void randomProgress(); + Q_INVOKABLE void resetProgress(); private slots: void doUpdate(); @@ -105,6 +124,7 @@ private: SettingsFact _showTiles; QVector _progress; + bool _holdProgress; // Tile stuff. // Tile stuff. mutable QTimer _timer; diff --git a/src/MeasurementComplexItem/qml/AreaDataEditor.qml b/src/MeasurementComplexItem/qml/AreaDataEditor.qml index 28562732558492db678d6cdd7064c4b505c2771d..36eb2f6be03d68064091bed018c2b17107fbdcab 100644 --- a/src/MeasurementComplexItem/qml/AreaDataEditor.qml +++ b/src/MeasurementComplexItem/qml/AreaDataEditor.qml @@ -1,5 +1,6 @@ import QtQuick 2.0 +import Qt.labs.settings 1.0 import QtQuick.Layouts 1.11 import QtQuick.Controls 1.4 import QGroundControl.Controls 1.0 @@ -40,17 +41,18 @@ GridLayout { } } - ExclusiveGroup { - id: areaGroup - } - QGCLabel { - id: tipLabel + text: _root.errorString wrapMode: Text.WordWrap - horizontalAlignment: Text.AlignHCenter - text: qsTr("Use the Area Editor to modify areas.") - Layout.fillWidth: true + horizontalAlignment: Text.AlignLeft + color: "orange" Layout.columnSpan: parent.columns + Layout.fillWidth: true + visible: !_root.areasCorrect + } + + ExclusiveGroup { + id: areaGroup } Repeater { @@ -135,7 +137,7 @@ GridLayout { id: commandsHeader Layout.fillWidth: true Layout.columnSpan: parent.columns - text: qsTr("Commands and Errors") + text: qsTr("Commands") } GridLayout { @@ -146,16 +148,6 @@ GridLayout { Layout.fillWidth: true visible: commandsHeader.checked - QGCLabel { - text: qsTr("Message: ") + _root.errorString - wrapMode: Text.WordWrap - horizontalAlignment: Text.AlignHCenter - color: "orange" - Layout.columnSpan: parent.columns - Layout.fillWidth: true - visible: !_root.areasCorrect - } - QGCButton { text: "Intersection" enabled: _root.checked @@ -168,10 +160,44 @@ GridLayout { QGCButton { text: "Reset" + onClicked: { + _root.reset() + } + Layout.fillWidth: true + } + + QGCButton { + text: "Abort" onClicked: { _root.abort() } Layout.fillWidth: true + } + } + + SectionHeader { + id: hintHeader + Layout.fillWidth: true + Layout.columnSpan: parent.columns + text: qsTr("Hints") + } + + GridLayout { + columnSpacing: _margin + rowSpacing: _margin + columns: 2 + Layout.columnSpan: 2 + Layout.fillWidth: true + visible: hintHeader.checked + + QGCLabel { + id: hintLabel + wrapMode: Text.WordWrap + horizontalAlignment: Text.AlignLeft + text: qsTr("Use the Intersection button to clip the Measurement Area(s). +Use the Reset button to restore the areas to the state before entering this tab. +Use the Abort button to reset the areas and leave the tab.") + Layout.fillWidth: true Layout.columnSpan: parent.columns } } @@ -193,4 +219,8 @@ GridLayout { } } } + + Settings { + property alias showHint: hintHeader.checked + } } diff --git a/src/MeasurementComplexItem/qml/MeasurementAreaMapVisual.qml b/src/MeasurementComplexItem/qml/MeasurementAreaMapVisual.qml index 2000b854c85613ea77d491db753e54071de22d4d..e791270d89c8ab1f94e151583ef979b05e187e9e 100644 --- a/src/MeasurementComplexItem/qml/MeasurementAreaMapVisual.qml +++ b/src/MeasurementComplexItem/qml/MeasurementAreaMapVisual.qml @@ -1,3 +1,5 @@ + + /**************************************************************************** * * (c) 2009-2016 QGROUNDCONTROL PROJECT @@ -6,25 +8,24 @@ * COPYING.md in the root of the source code directory. * ****************************************************************************/ - -import QtQuick 2.3 +import QtQuick 2.3 import QtQuick.Controls 1.2 -import QtLocation 5.3 -import QtPositioning 5.3 +import QtLocation 5.3 +import QtPositioning 5.3 -import QGroundControl 1.0 -import QGroundControl.ScreenTools 1.0 -import QGroundControl.Palette 1.0 -import QGroundControl.Controls 1.0 -import QGroundControl.FlightMap 1.0 +import QGroundControl 1.0 +import QGroundControl.ScreenTools 1.0 +import QGroundControl.Palette 1.0 +import QGroundControl.Controls 1.0 +import QGroundControl.FlightMap 1.0 Item { id: _root - property var map: undefined ///< Map control to place item in - property var geoArea: undefined ///< GeoArea derived class + property var map: undefined ///< Map control to place item in + property var geoArea: undefined ///< GeoArea derived class - opacity: 0.3 + opacity: 0.2 signal clicked(int sequenceNumber) @@ -35,31 +36,30 @@ Item { // Area polygon QGCMapPolygonVisuals { - id: mapPolygonVisuals - - mapControl: _root.map - mapPolygon: _root.geoArea - interactive: geoArea.interactive - borderWidth: 3 - borderColor: "green" - interiorColor: "green" - altColor: QGroundControl.globalPalette.surveyPolygonTerrainCollision - z: QGroundControl.zOrderMapItems-1 - interiorOpacity: _root.opacity + id: mapPolygonVisuals + + mapControl: _root.map + mapPolygon: _root.geoArea + interactive: geoArea.interactive + borderWidth: 3 + interiorColor: "green" + altColor: QGroundControl.globalPalette.surveyPolygonTerrainCollision + z: QGroundControl.zOrderMapItems - 1 + interiorOpacity: _root.opacity } // Add Snake tiles to the map Component { id: tileComponent - Item{ + Item { id: root property MapPolygon polygon - MapPolygon{ - id:mapPolygon - path: [] + MapPolygon { + id: mapPolygon + path: [] } Component.onCompleted: { @@ -90,27 +90,27 @@ Item { property bool enable: geoArea.showTiles.value model: enable ? geoArea.tiles : [] - Item{ + Item { property var _tileComponent - property int _progress: _root.geoArea.progress[index] ? - _root.geoArea.progress[index] : 0 + property int _progress: _root.geoArea.progress[index] ? _root.geoArea.progress[index] : 0 Component.onCompleted: { _tileComponent = tileComponent.createObject(map) - _tileComponent.polygon.path = - Qt.binding(function(){return object.path}) + _tileComponent.polygon.path = Qt.binding(function () { + return object.path + }) _tileComponent.polygon.opacity = 0.6 _tileComponent.polygon.border.color = "black" _tileComponent.polygon.border.width = 1 - _tileComponent.polygon.color = - Qt.binding(function(){return getColor(_progress)}) + _tileComponent.polygon.color = Qt.binding(function () { + return getColor(_progress) + }) } Component.onDestruction: { _tileComponent.destroy() } - } } } diff --git a/src/MeasurementComplexItem/qml/MeasurementComplexItem.qmldir b/src/MeasurementComplexItem/qml/MeasurementComplexItem.qmldir index 2fd96c7292efdbad2580817e6a86752951155a4b..ff895118245641597be9cad326801aabde3fec41 100644 --- a/src/MeasurementComplexItem/qml/MeasurementComplexItem.qmldir +++ b/src/MeasurementComplexItem/qml/MeasurementComplexItem.qmldir @@ -4,3 +4,4 @@ LinearGenerator 1.0 LinearGenerator.qml CircularGenerator 1.0 CircularGenerator.qml SafeAreaEditor 1.0 SafeAreaEditor.qml MeasurementAreaEditor 1.0 MeasurementAreaEditor.qml +NemoEditor 1.0 NemoEditor.qml diff --git a/src/MeasurementComplexItem/qml/MeasurementItemEditor.qml b/src/MeasurementComplexItem/qml/MeasurementItemEditor.qml index 8b84e6f1480c7919afc44af6433b4a5c1374d955..5d1c6c60d612694ddea7f84c96690732c018fa85 100644 --- a/src/MeasurementComplexItem/qml/MeasurementItemEditor.qml +++ b/src/MeasurementComplexItem/qml/MeasurementItemEditor.qml @@ -60,7 +60,7 @@ Rectangle { Component.onCompleted: currentIndex = editing ? areaEditorIndex : parameterEditorIndex QGCTabButton { - icon.source: "/qmlimages/PatternCamera.png" + icon.source: "qrc:/res/waypoint.svg" icon.height: ScreenTools.defaultFontPixelHeight } QGCTabButton { @@ -68,7 +68,7 @@ Rectangle { icon.height: ScreenTools.defaultFontPixelHeight } QGCTabButton { - icon.source: "/qmlimages/PatternPresets.png" + icon.source: "qrc:/res/fish.svg" icon.height: ScreenTools.defaultFontPixelHeight } @@ -124,6 +124,14 @@ Rectangle { missionItem: _root._missionItem availableWidth: mainColumn.width } + + MCI.NemoEditor { + id: nemoEditor + + checked: visible + missionItem: _root._missionItem + availableWidth: mainColumn.width + } } } // main Column } // Rectangle diff --git a/src/MeasurementComplexItem/qml/MeasurementItemMapVisual.qml b/src/MeasurementComplexItem/qml/MeasurementItemMapVisual.qml index 99b99c0eeae2399aa562afca28e88e1b63f2939a..b85ddca76ed2c7655f2aae578d136888aab04cda 100644 --- a/src/MeasurementComplexItem/qml/MeasurementItemMapVisual.qml +++ b/src/MeasurementComplexItem/qml/MeasurementItemMapVisual.qml @@ -56,9 +56,9 @@ Item { Component.onCompleted: { console.assert(map != undefined, "please set the map property") - if (!_missionItem.areaData.initialized()){ + if (!_missionItem.initialized()){ var bbox = boundingBox() - _missionItem.areaData.initialize(bbox[0], bbox[1]) + _missionItem.initialize(bbox[0], bbox[1]) } // _addEntryCoordinate() // _addExitCoordinate() diff --git a/src/MeasurementComplexItem/qml/NemoEditor.qml b/src/MeasurementComplexItem/qml/NemoEditor.qml new file mode 100644 index 0000000000000000000000000000000000000000..518977207fdf7cb30b69b551f093f216fb306b9a --- /dev/null +++ b/src/MeasurementComplexItem/qml/NemoEditor.qml @@ -0,0 +1,227 @@ +import QtQuick 2.0 + +import Qt.labs.settings 1.0 +import QtQuick.Layouts 1.11 +import QtQuick.Controls 1.4 +import QGroundControl.Controls 1.0 +import QGroundControl.FactControls 1.0 +import QGroundControl.ScreenTools 1.0 + +import MeasurementComplexItem 1.0 as MCI + +GridLayout { + id: _root + + property bool checked: true + property var missionItem: undefined + property int availableWidth: 300 + property bool error: errorString.lenght >= 0 + readonly property bool running: _nemoInterface.running + property string errorString: "" + + signal abort + + property var _areaData: missionItem.areaData + property real _margin: ScreenTools.defaultFontPixelWidth / 2 + property var _nemoInterface: MCI.NemoInterface + property bool _holding + + columnSpacing: _margin + rowSpacing: _margin + columns: 2 + + Component.onCompleted: { + console.assert(missionItem !== undefined, + "please set the missionItem property") + _holding = false + _stopHolding() + } + + QGCLabel { + text: _root.errorString + wrapMode: Text.WordWrap + horizontalAlignment: Text.AlignLeft + color: "orange" + Layout.columnSpan: parent.columns + Layout.fillWidth: true + visible: !_root.areasCorrect + } + + QGCButton { + text: running ? qsTr("Stop") : qsTr("Start") + Layout.columnSpan: parent.columns + Layout.fillWidth: true + onPressed: { + if (running) { + _nemoInterface.stop() + } else { + _nemoInterface.start() + } + } + } + + QGCLabel { + text: qsTr("Status: ") + _nemoInterface.statusString + wrapMode: Text.WordWrap + horizontalAlignment: Text.AlignVCenter + Layout.columnSpan: parent.columns + Layout.fillWidth: true + } + + SectionHeader { + id: progressHeader + Layout.fillWidth: true + Layout.columnSpan: parent.columns + text: qsTr("Progress") + } + + GridLayout { + columnSpacing: _margin + rowSpacing: _margin + columns: 2 + Layout.columnSpan: parent.columns + Layout.fillWidth: true + visible: progressHeader.checked + + QGCButton { + text: !_holding ? qsTr("Hold") : qsTr("Stop Holding") + Layout.fillWidth: true + Layout.columnSpan: parent.columns + onPressed: { + if (_holding) { + _stopHolding() + _holding = false + } else { + _holdProgress() + _holding = true + } + } + } + + QGCButton { + text: qsTr("Random") + Layout.columnSpan: parent.columns + Layout.fillWidth: true + onPressed: { + _randomProgress() + } + } + + QGCButton { + text: qsTr("Reset") + Layout.columnSpan: parent.columns + Layout.fillWidth: true + onPressed: { + _resetProgress() + } + } + } + + // bussy indicator + ColumnLayout { + Layout.fillWidth: true + spacing: _margin + Layout.maximumWidth: parent.width + + BusyIndicator { + id: indicator + + property bool calculating: missionItem.calculating + + running: calculating + visible: calculating || timer.running + + onCalculatingChanged: { + if (!calculating) { + // defer hiding + timer.restart() + } + } + + Timer { + id: timer + interval: 1000 + repeat: false + running: false + } + } + } // indicator column + + SectionHeader { + id: hintHeader + Layout.fillWidth: true + Layout.columnSpan: parent.columns + text: qsTr("Hints") + } + + GridLayout { + columnSpacing: _margin + rowSpacing: _margin + columns: 2 + Layout.columnSpan: 2 + Layout.fillWidth: true + visible: hintHeader.checked + + QGCLabel { + id: hintLabel + wrapMode: Text.WordWrap + horizontalAlignment: Text.AlignLeft + text: qsTr("Use this tab to connect to a device implementing the Nemo Interface. +Use the Random button to simulate measurement progress.") + Layout.fillWidth: true + Layout.columnSpan: parent.columns + } + } + + Settings { + property alias showHint: hintHeader.checked + } + + function _holdProgress() { + var areaArray = _areaData.measurementAreaList + for (var i = 0; i < areaArray.count; ++i) { + var area = areaArray.get(i) + if (area) { + area.holdProgress = true + } else { + console.log("empty area!") + } + } + } + + function _stopHolding() { + var areaArray = _areaData.measurementAreaList + for (var i = 0; i < areaArray.count; ++i) { + var area = areaArray.get(i) + if (area) { + area.holdProgress = false + } else { + console.log("empty area!") + } + } + } + + function _randomProgress() { + var areaArray = _areaData.measurementAreaList + for (var i = 0; i < areaArray.count; ++i) { + var area = areaArray.get(i) + if (area) { + area.randomProgress() + } else { + console.log("empty area!") + } + } + } + + function _resetProgress() { + var areaArray = _areaData.measurementAreaList + for (var i = 0; i < areaArray.count; ++i) { + var area = areaArray.get(i) + if (area) { + area.resetProgress() + } else { + console.log("empty area!") + } + } + } +} diff --git a/src/MeasurementComplexItem/qml/SafeAreaMapVisual.qml b/src/MeasurementComplexItem/qml/SafeAreaMapVisual.qml index 78985cc45660f0ff62290cb2dcdb049ac6936199..6552174c17022c9c0518de9f1135df23b7d55229 100644 --- a/src/MeasurementComplexItem/qml/SafeAreaMapVisual.qml +++ b/src/MeasurementComplexItem/qml/SafeAreaMapVisual.qml @@ -39,11 +39,10 @@ Item { mapPolygon: geoArea interactive: geoArea.interactive borderWidth: 2 - borderColor: "blue" interiorColor: "blue" altColor: QGroundControl.globalPalette.surveyPolygonTerrainCollision z: QGroundControl.zOrderMapItems-1 - interiorOpacity: 0.3 + interiorOpacity: 0.2 } Item { diff --git a/src/MissionManager/MissionItem.h b/src/MissionManager/MissionItem.h index 72519e3f447f62e109bb96a9bba68f17e0d09cf2..869992b956b28a4d96036a86c4933548d7f39ced 100644 --- a/src/MissionManager/MissionItem.h +++ b/src/MissionManager/MissionItem.h @@ -7,157 +7,155 @@ * ****************************************************************************/ - #ifndef MissionItem_H #define MissionItem_H +#include +#include #include #include -#include #include -#include -#include +#include -#include "QGCMAVLink.h" -#include "QGC.h" -#include "QmlObjectListModel.h" #include "Fact.h" +#include "QGC.h" #include "QGCLoggingCategory.h" +#include "QGCMAVLink.h" #include "QmlObjectListModel.h" class SurveyComplexItem; -class RouteComplexItem; class SimpleMissionItem; class MissionController; #ifdef UNITTEST_BUILD - class MissionItemTest; +class MissionItemTest; #endif // Represents a Mavlink mission command. -class MissionItem : public QObject -{ - Q_OBJECT - +class MissionItem : public QObject { + Q_OBJECT + public: - MissionItem(QObject* parent = nullptr); - - MissionItem(int sequenceNumber, - MAV_CMD command, - MAV_FRAME frame, - double param1, - double param2, - double param3, - double param4, - double param5, - double param6, - double param7, - bool autoContinue, - bool isCurrentItem, - QObject* parent = nullptr); - - MissionItem(const MissionItem& other, QObject* parent = nullptr); - - ~MissionItem(); - - const MissionItem& operator=(const MissionItem& other); - - MAV_CMD command (void) const { return (MAV_CMD)_commandFact.rawValue().toInt(); } - bool isCurrentItem (void) const { return _isCurrentItem; } - int sequenceNumber (void) const { return _sequenceNumber; } - MAV_FRAME frame (void) const { return (MAV_FRAME)_frameFact.rawValue().toInt(); } - bool autoContinue (void) const { return _autoContinueFact.rawValue().toBool(); } - double param1 (void) const { return _param1Fact.rawValue().toDouble(); } - double param2 (void) const { return _param2Fact.rawValue().toDouble(); } - double param3 (void) const { return _param3Fact.rawValue().toDouble(); } - double param4 (void) const { return _param4Fact.rawValue().toDouble(); } - double param5 (void) const { return _param5Fact.rawValue().toDouble(); } - double param6 (void) const { return _param6Fact.rawValue().toDouble(); } - double param7 (void) const { return _param7Fact.rawValue().toDouble(); } - QGeoCoordinate coordinate (void) const; - int doJumpId (void) const { return _doJumpId; } - - /// @return Flight speed change value if this item supports it. If not it returns NaN. - double specifiedFlightSpeed(void) const; - - /// @return Flight gimbal yaw change value if this item supports it. If not it returns NaN. - double specifiedGimbalYaw(void) const; - - /// @return Flight gimbal pitch change value if this item supports it. If not it returns NaN. - double specifiedGimbalPitch(void) const; - - void setCommand (MAV_CMD command); - void setSequenceNumber (int sequenceNumber); - void setIsCurrentItem (bool isCurrentItem); - void setFrame (MAV_FRAME frame); - void setAutoContinue (bool autoContinue); - void setParam1 (double param1); - void setParam2 (double param2); - void setParam3 (double param3); - void setParam4 (double param4); - void setParam5 (double param5); - void setParam6 (double param6); - void setParam7 (double param7); - - void save(QJsonObject& json) const; - bool load(QTextStream &loadStream); - bool load(const QJsonObject& json, int sequenceNumber, QString& errorString); - - bool relativeAltitude(void) const { return frame() == MAV_FRAME_GLOBAL_RELATIVE_ALT; } + MissionItem(QObject *parent = nullptr); + + MissionItem(int sequenceNumber, MAV_CMD command, MAV_FRAME frame, + double param1, double param2, double param3, double param4, + double param5, double param6, double param7, bool autoContinue, + bool isCurrentItem, QObject *parent = nullptr); + + MissionItem(const MissionItem &other, QObject *parent = nullptr); + + ~MissionItem(); + + const MissionItem &operator=(const MissionItem &other); + + MAV_CMD command(void) const { + return (MAV_CMD)_commandFact.rawValue().toInt(); + } + bool isCurrentItem(void) const { return _isCurrentItem; } + int sequenceNumber(void) const { return _sequenceNumber; } + MAV_FRAME frame(void) const { + return (MAV_FRAME)_frameFact.rawValue().toInt(); + } + bool autoContinue(void) const { + return _autoContinueFact.rawValue().toBool(); + } + double param1(void) const { return _param1Fact.rawValue().toDouble(); } + double param2(void) const { return _param2Fact.rawValue().toDouble(); } + double param3(void) const { return _param3Fact.rawValue().toDouble(); } + double param4(void) const { return _param4Fact.rawValue().toDouble(); } + double param5(void) const { return _param5Fact.rawValue().toDouble(); } + double param6(void) const { return _param6Fact.rawValue().toDouble(); } + double param7(void) const { return _param7Fact.rawValue().toDouble(); } + QGeoCoordinate coordinate(void) const; + int doJumpId(void) const { return _doJumpId; } + + /// @return Flight speed change value if this item supports it. If not it + /// returns NaN. + double specifiedFlightSpeed(void) const; + + /// @return Flight gimbal yaw change value if this item supports it. If not it + /// returns NaN. + double specifiedGimbalYaw(void) const; + + /// @return Flight gimbal pitch change value if this item supports it. If not + /// it returns NaN. + double specifiedGimbalPitch(void) const; + + void setCommand(MAV_CMD command); + void setSequenceNumber(int sequenceNumber); + void setIsCurrentItem(bool isCurrentItem); + void setFrame(MAV_FRAME frame); + void setAutoContinue(bool autoContinue); + void setParam1(double param1); + void setParam2(double param2); + void setParam3(double param3); + void setParam4(double param4); + void setParam5(double param5); + void setParam6(double param6); + void setParam7(double param7); + + void save(QJsonObject &json) const; + bool load(QTextStream &loadStream); + bool load(const QJsonObject &json, int sequenceNumber, QString &errorString); + + bool relativeAltitude(void) const { + return frame() == MAV_FRAME_GLOBAL_RELATIVE_ALT; + } signals: - void isCurrentItemChanged (bool isCurrentItem); - void sequenceNumberChanged (int sequenceNumber); - void specifiedFlightSpeedChanged(double flightSpeed); - void specifiedGimbalYawChanged (double gimbalYaw); - void specifiedGimbalPitchChanged(double gimbalPitch); + void isCurrentItemChanged(bool isCurrentItem); + void sequenceNumberChanged(int sequenceNumber); + void specifiedFlightSpeedChanged(double flightSpeed); + void specifiedGimbalYawChanged(double gimbalYaw); + void specifiedGimbalPitchChanged(double gimbalPitch); private slots: - void _param1Changed(QVariant value); - void _param2Changed(QVariant value); - void _param3Changed(QVariant value); + void _param1Changed(QVariant value); + void _param2Changed(QVariant value); + void _param3Changed(QVariant value); private: - bool _convertJsonV1ToV2(const QJsonObject& json, QJsonObject& v2Json, QString& errorString); - bool _convertJsonV2ToV3(QJsonObject& json, QString& errorString); - - - Fact _autoContinueFact; - Fact _commandFact; - Fact _frameFact; - Fact _param1Fact; - Fact _param2Fact; - Fact _param3Fact; - Fact _param4Fact; - Fact _param5Fact; - Fact _param6Fact; - Fact _param7Fact; - - int _sequenceNumber; - int _doJumpId; - bool _isCurrentItem; - - // Keys for Json save - static const char* _jsonFrameKey; - static const char* _jsonCommandKey; - static const char* _jsonAutoContinueKey; - static const char* _jsonParamsKey; - static const char* _jsonDoJumpIdKey; - - // Deprecated V2 format keys - static const char* _jsonCoordinateKey; - - // Deprecated V1 format keys - static const char* _jsonParam1Key; - static const char* _jsonParam2Key; - static const char* _jsonParam3Key; - static const char* _jsonParam4Key; - - friend class SurveyComplexItem; - friend class RouteComplexItem; - friend class SimpleMissionItem; - friend class MissionController; + bool _convertJsonV1ToV2(const QJsonObject &json, QJsonObject &v2Json, + QString &errorString); + bool _convertJsonV2ToV3(QJsonObject &json, QString &errorString); + + Fact _autoContinueFact; + Fact _commandFact; + Fact _frameFact; + Fact _param1Fact; + Fact _param2Fact; + Fact _param3Fact; + Fact _param4Fact; + Fact _param5Fact; + Fact _param6Fact; + Fact _param7Fact; + + int _sequenceNumber; + int _doJumpId; + bool _isCurrentItem; + + // Keys for Json save + static const char *_jsonFrameKey; + static const char *_jsonCommandKey; + static const char *_jsonAutoContinueKey; + static const char *_jsonParamsKey; + static const char *_jsonDoJumpIdKey; + + // Deprecated V2 format keys + static const char *_jsonCoordinateKey; + + // Deprecated V1 format keys + static const char *_jsonParam1Key; + static const char *_jsonParam2Key; + static const char *_jsonParam3Key; + static const char *_jsonParam4Key; + + friend class SurveyComplexItem; + friend class RouteComplexItem; + friend class SimpleMissionItem; + friend class MissionController; #ifdef UNITTEST_BUILD - friend class MissionItemTest; + friend class MissionItemTest; #endif }; diff --git a/src/QGCApplication.cc b/src/QGCApplication.cc index 3eb73244a4245f0bb21785cbd6993d19a240040f..1e79d9d8a38f8a6bef2814109772f3516120b971 100644 --- a/src/QGCApplication.cc +++ b/src/QGCApplication.cc @@ -186,6 +186,11 @@ static QObject *shapeFileHelperSingletonFactory(QQmlEngine *, QJSEngine *) { return new ShapeFileHelper; } +QObject *getNemoInterface(QQmlEngine *engine, QJSEngine *) { + engine->setObjectOwnership(pNemoInterface, QQmlEngine::CppOwnership); + return pNemoInterface; +} + QGCApplication::QGCApplication(int &argc, char *argv[], bool unitTesting) : QApplication(argc, argv), _runningUnitTests(unitTesting) { _app = this; @@ -665,13 +670,13 @@ void QGCApplication::_initCommon() { #endif qmlRegisterUncreatableType( - "RouteComplexItem", 1, 0, "LinearGenerator", kRefOnly); - qmlRegisterType("RouteComplexItem", 1, 0, "AreaData"); - qmlRegisterUncreatableType("RouteComplexItem", 1, 0, - "NemoInterface", kRefOnly); + "MeasurementComplexItem", 1, 0, "LinearGenerator", kRefOnly); + qmlRegisterType("MeasurementComplexItem", 1, 0, "AreaData"); + qmlRegisterSingletonType("MeasurementComplexItem", 1, 0, + "NemoInterface", getNemoInterface); qmlRegisterInterface("GeneratorBase"); qmlRegisterUncreatableType( - "RouteComplexItem", 1, 0, "CircularGenerator", kRefOnly); + "MeasurementComplexItem", 1, 0, "CircularGenerator", kRefOnly); qmlRegisterType(kQGCControllers, 1, 0, "GeoTagController"); qmlRegisterType(kQGCControllers, 1, 0,