Commit ab5abb37 authored by Valentin Platzgummer's avatar Valentin Platzgummer

proper pictures added to MeasurementItemEditor.qml

parent 1b05f323
...@@ -18,7 +18,7 @@ ...@@ -18,7 +18,7 @@
<file alias="counter-clockwise-arrow.svg">resources/counter-clockwise-arrow.svg</file> <file alias="counter-clockwise-arrow.svg">resources/counter-clockwise-arrow.svg</file>
<file alias="chevron-down.svg">resources/chevron-down.svg</file> <file alias="chevron-down.svg">resources/chevron-down.svg</file>
<file alias="chevron-up.svg">resources/chevron-up.svg</file> <file alias="chevron-up.svg">resources/chevron-up.svg</file>
<file alias="DropArrow.svg">resources/DropArrow.svg</file> <file alias="DropArrow.svg">resources/DropArrow.svg</file>
<file alias="gear-black.svg">resources/gear-black.svg</file> <file alias="gear-black.svg">resources/gear-black.svg</file>
<file alias="gear-white.svg">resources/gear-white.svg</file> <file alias="gear-white.svg">resources/gear-white.svg</file>
<file alias="helicoptericon.svg">resources/helicoptericon.svg</file> <file alias="helicoptericon.svg">resources/helicoptericon.svg</file>
...@@ -34,7 +34,7 @@ ...@@ -34,7 +34,7 @@
<file alias="Play">resources/Play.svg</file> <file alias="Play">resources/Play.svg</file>
<file alias="PowerButton">resources/PowerButton.svg</file> <file alias="PowerButton">resources/PowerButton.svg</file>
<file alias="QGCLogoBlack">resources/QGCLogoBlack.svg</file> <file alias="QGCLogoBlack">resources/QGCLogoBlack.svg</file>
<file alias="QGCLogoFull">resources/QGCLogoFull.svg</file> <file alias="QGCLogoFull">resources/QGCLogoFull.svg</file>
<file alias="QGCLogoWhite">resources/QGCLogoWhite.svg</file> <file alias="QGCLogoWhite">resources/QGCLogoWhite.svg</file>
<file alias="QGCLogoArrow">resources/QGCLogoArrow.svg</file> <file alias="QGCLogoArrow">resources/QGCLogoArrow.svg</file>
<file alias="QGroundControlConnect">resources/QGroundControlConnect.svg</file> <file alias="QGroundControlConnect">resources/QGroundControlConnect.svg</file>
...@@ -56,6 +56,7 @@ ...@@ -56,6 +56,7 @@
<file alias="street.png">resources/street.png</file> <file alias="street.png">resources/street.png</file>
<file alias="measurement.png">resources/measurement.png</file> <file alias="measurement.png">resources/measurement.png</file>
<file alias="calculator.png">resources/calculator.png</file> <file alias="calculator.png">resources/calculator.png</file>
<file alias="fish.svg">resources/fish.svg</file>
</qresource> </qresource>
<qresource prefix="/res/firmware"> <qresource prefix="/res/firmware">
<file alias="3drradio.png">resources/firmware/3drradio.png</file> <file alias="3drradio.png">resources/firmware/3drradio.png</file>
......
...@@ -293,6 +293,7 @@ ...@@ -293,6 +293,7 @@
<file alias="MeasurementComplexItem/AreaDataEditor.qml">src/MeasurementComplexItem/qml/AreaDataEditor.qml</file> <file alias="MeasurementComplexItem/AreaDataEditor.qml">src/MeasurementComplexItem/qml/AreaDataEditor.qml</file>
<file alias="MeasurementComplexItem/ParameterEditor.qml">src/MeasurementComplexItem/qml/ParameterEditor.qml</file> <file alias="MeasurementComplexItem/ParameterEditor.qml">src/MeasurementComplexItem/qml/ParameterEditor.qml</file>
<file alias="MeasurementComplexItem/qmldir">src/MeasurementComplexItem/qml/MeasurementComplexItem.qmldir</file> <file alias="MeasurementComplexItem/qmldir">src/MeasurementComplexItem/qml/MeasurementComplexItem.qmldir</file>
<file alias="MeasurementComplexItem/NemoEditor.qml">src/MeasurementComplexItem/qml/NemoEditor.qml</file>
</qresource> </qresource>
<qresource prefix="/FirstRunPromptDialogs"> <qresource prefix="/FirstRunPromptDialogs">
<file alias="UnitsFirstRunPrompt.qml">src/FirstRunPromptDialogs/UnitsFirstRunPrompt.qml</file> <file alias="UnitsFirstRunPrompt.qml">src/FirstRunPromptDialogs/UnitsFirstRunPrompt.qml</file>
......
[Dolphin]
PreviewsShown=true
Timestamp=2020,12,19,15,18,21
Version=4
fish.svg: from https://commons.wikimedia.org/wiki/File:Font_Awesome_5_solid_fish.svg
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 576 512"><path d="M327.1 96c-89.97 0-168.54 54.77-212.27 101.63L27.5 131.58c-12.13-9.18-30.24.6-27.14 14.66L24.54 256 .35 365.77c-3.1 14.06 15.01 23.83 27.14 14.66l87.33-66.05C158.55 361.23 237.13 416 327.1 416 464.56 416 576 288 576 256S464.56 96 327.1 96zm87.43 184c-13.25 0-24-10.75-24-24 0-13.26 10.75-24 24-24 13.26 0 24 10.74 24 24 0 13.25-10.75 24-24 24z"/></svg>
<!--
Font Awesome Free 5.2.0 by @fontawesome - https://fontawesome.com
License - https://fontawesome.com/license (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License)
-->
\ No newline at end of file
...@@ -126,8 +126,9 @@ bool AreaData::isCorrect(bool showError) { ...@@ -126,8 +126,9 @@ bool AreaData::isCorrect(bool showError) {
// ss << "safeAreaENU: " << bg::wkt(safeAreaENU) << std::endl; // ss << "safeAreaENU: " << bg::wkt(safeAreaENU) << std::endl;
// qDebug() << ss.str().c_str(); // qDebug() << ss.str().c_str();
if (!bg::covered_by(measurementAreaENU, safeAreaENU)) { if (!bg::covered_by(measurementAreaENU, safeAreaENU)) {
_processError(tr("Measurement Area not inside Safe Area. Please adjust " _processError(tr("Measurement Area is not covered by Safe "
"the Measurement Area.\n"), "Area. Please adjust "
"the areas accordingly.\n"),
showError); showError);
return false; return false;
} }
...@@ -228,10 +229,10 @@ void AreaData::intersection(bool showError) { ...@@ -228,10 +229,10 @@ void AreaData::intersection(bool showError) {
boost::geometry::intersection(measurementAreaENU, safeAreaENU, outputENU); boost::geometry::intersection(measurementAreaENU, safeAreaENU, outputENU);
if (outputENU.size() < 1 || outputENU[0].outer().size() < 4) { if (outputENU.size() < 1 || outputENU[0].outer().size() < 4) {
_processError( _processError("Intersection did't deliver any result. The Measurement "
"Intersection did't deliver any result. Measurement Area and " "Area(s) and "
"Safe Area must touch each other.", "The Safe Area must touch each other.",
showError); showError);
return; return;
} }
...@@ -266,11 +267,29 @@ void AreaData::intersection(bool showError) { ...@@ -266,11 +267,29 @@ void AreaData::intersection(bool showError) {
} }
} }
MeasurementArea *AreaData::measurementArea() { QVector<MeasurementArea *> AreaData::measurementAreaArray() {
return getGeoArea<MeasurementArea *>(_areaList); return getGeoAreaList<MeasurementArea *, QVector>(_areaList);
}
QVector<SafeArea *> AreaData::safeAreaArray() {
return getGeoAreaList<SafeArea *, QVector>(_areaList);
} }
SafeArea *AreaData::safeArea() { return getGeoArea<SafeArea *>(_areaList); } QmlObjectListModel *AreaData::measurementAreaList() {
_measurementAreaList.clear();
auto array = getGeoAreaList<MeasurementArea *, QVector>(_areaList);
for (auto area : array)
_measurementAreaList.append(area);
return &_measurementAreaList;
}
QmlObjectListModel *AreaData::safeAreaList() {
_safeAreaList.clear();
auto array = getGeoAreaList<SafeArea *, QVector>(_areaList);
for (auto &area : array)
_safeAreaList.append(area);
return &_safeAreaList;
}
bool AreaData::operator==(const AreaData &other) const { bool AreaData::operator==(const AreaData &other) const {
if (_areaList.count() == other._areaList.count()) { if (_areaList.count() == other._areaList.count()) {
...@@ -442,13 +461,13 @@ bool AreaData::_getAreas(MeasurementArea **measurementArea, SafeArea **safeArea, ...@@ -442,13 +461,13 @@ bool AreaData::_getAreas(MeasurementArea **measurementArea, SafeArea **safeArea,
*measurementArea = getGeoArea<MeasurementArea *>(_areaList); *measurementArea = getGeoArea<MeasurementArea *>(_areaList);
if (*measurementArea == nullptr) { if (*measurementArea == nullptr) {
_processError( _processError(
tr("Measurement Area missing. Please define a measurement area."), tr("Measurement Area is missing. Please define a Measurement Area."),
showError); showError);
return false; return false;
} }
*safeArea = getGeoArea<SafeArea *>(_areaList); *safeArea = getGeoArea<SafeArea *>(_areaList);
if (*safeArea == nullptr) { 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); showError);
return false; return false;
} }
......
...@@ -20,6 +20,10 @@ public: ...@@ -20,6 +20,10 @@ public:
AreaData &operator=(const AreaData &other); AreaData &operator=(const AreaData &other);
Q_PROPERTY(QmlObjectListModel *areaList READ areaList NOTIFY areaListChanged) 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) Q_PROPERTY(QString errorString READ errorString NOTIFY error)
// Member Methodes // Member Methodes
...@@ -70,8 +74,10 @@ public: ...@@ -70,8 +74,10 @@ public:
Q_INVOKABLE bool initialized(); Q_INVOKABLE bool initialized();
Q_INVOKABLE void intersection(bool showError = true); Q_INVOKABLE void intersection(bool showError = true);
Q_INVOKABLE MeasurementArea *measurementArea(); QVector<MeasurementArea *> measurementAreaArray();
Q_INVOKABLE SafeArea *safeArea(); QVector<SafeArea *> safeAreaArray();
QmlObjectListModel *measurementAreaList();
QmlObjectListModel *safeAreaList();
bool operator==(const AreaData &other) const; bool operator==(const AreaData &other) const;
bool operator!=(const AreaData &other) const; bool operator!=(const AreaData &other) const;
...@@ -97,5 +103,7 @@ private: ...@@ -97,5 +103,7 @@ private:
QGeoCoordinate _origin; QGeoCoordinate _origin;
QmlObjectListModel _areaList; QmlObjectListModel _areaList;
QmlObjectListModel _measurementAreaList;
QmlObjectListModel _safeAreaList;
QString _errorString; QString _errorString;
}; };
...@@ -83,9 +83,9 @@ private: ...@@ -83,9 +83,9 @@ private:
std::map<QString, Creator> _creatorMap; std::map<QString, Creator> _creatorMap;
}; };
#define pGeneratorFactory ::routing::GeneratorFactory::instance()
#define REGISTER_GENERATOR(type, creator) \ #define REGISTER_GENERATOR(type, creator) \
namespace { \ namespace { \
auto registered = \ auto registered = pGeneratorFactory -> registerGenerator(type, creator); \
GeneratorFactory::instance() -> registerGenerator(type, creator); \
} }
} // namespace routing } // namespace routing
...@@ -3,6 +3,8 @@ ...@@ -3,6 +3,8 @@
#include <QScopedPointer> #include <QScopedPointer>
#include <QtGlobal> #include <QtGlobal>
// from https://stackoverflow.com/questions/46172607/qt-singleton-implementation
template <class T> class GenericSingelton { template <class T> class GenericSingelton {
private: private:
typedef T *(*CreateInstanceFunction)(); typedef T *(*CreateInstanceFunction)();
......
...@@ -247,8 +247,7 @@ bool MeasurementComplexItem::load(const QJsonObject &complexObject, ...@@ -247,8 +247,7 @@ bool MeasurementComplexItem::load(const QJsonObject &complexObject,
QString e; QString e;
// create generator // create generator
auto gen = routing::GeneratorFactory::instance()->create( auto gen = pGeneratorFactory->create(jsonGen, e, &parent /*parent*/);
jsonGen, e, &parent /*parent*/);
if (gen != nullptr) { if (gen != nullptr) {
// remove generators of same type and insert this generator. // remove generators of same type and insert this generator.
...@@ -267,7 +266,7 @@ bool MeasurementComplexItem::load(const QJsonObject &complexObject, ...@@ -267,7 +266,7 @@ bool MeasurementComplexItem::load(const QJsonObject &complexObject,
errorString.append( errorString.append(
tr("Error loading generator of type ") + tr("Error loading generator of type ") +
jsonGen[routing::GeneratorBase::typeKey].toString() + ".\n"); jsonGen[routing::GeneratorBase::typeKey].toString() + ".\n");
if (!routing::GeneratorFactory::instance()->registered( if (!pGeneratorFactory->registered(
jsonGen[routing::GeneratorBase::typeKey].toString())) { jsonGen[routing::GeneratorBase::typeKey].toString())) {
errorString.append(tr("This type is unknown.\n")); errorString.append(tr("This type is unknown.\n"));
qCritical() qCritical()
...@@ -360,8 +359,10 @@ bool MeasurementComplexItem::load(const QJsonObject &complexObject, ...@@ -360,8 +359,10 @@ bool MeasurementComplexItem::load(const QJsonObject &complexObject,
// Check if variants are covered by safe area. // Check if variants are covered by safe area.
if (variantsSuccess) { if (variantsSuccess) {
auto safeArea = _pCurrentData->safeArea(); auto safeAreaArray = _pCurrentData->safeAreaArray();
if (safeArea != nullptr) {
if (safeAreaArray.size() > 0 && safeAreaArray.at(0) != nullptr) {
auto safeArea = safeAreaArray[0];
QGeoCoordinate origin = QGeoCoordinate origin =
safeArea->pathModel().value<QGCQGeoCoordinate *>(0)->coordinate(); safeArea->pathModel().value<QGCQGeoCoordinate *>(0)->coordinate();
snake::FPolygon safeAreaENU; snake::FPolygon safeAreaENU;
...@@ -733,8 +734,11 @@ void MeasurementComplexItem::_updateFlightpathSegments() { ...@@ -733,8 +734,11 @@ void MeasurementComplexItem::_updateFlightpathSegments() {
if (hasCollisionOld != hasCollision) { if (hasCollisionOld != hasCollision) {
emit terrainCollisionChanged(hasCollision); emit terrainCollisionChanged(hasCollision);
} }
if (_pAreaData->measurementArea() != nullptr) { auto measurementAreaArray = _pAreaData->measurementAreaArray();
_pAreaData->measurementArea()->setShowAltColor(hasCollision); for (auto area : measurementAreaArray) {
if (area != nullptr) {
area->setShowAltColor(hasCollision);
}
} }
_masterController->missionController()->recalcTerrainProfile(); _masterController->missionController()->recalcTerrainProfile();
...@@ -782,6 +786,20 @@ void MeasurementComplexItem::_updateRoute() { ...@@ -782,6 +786,20 @@ void MeasurementComplexItem::_updateRoute() {
if (this->_pAreaData->isCorrect()) { 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. // Prepare data.
auto origin = this->_pAreaData->origin(); auto origin = this->_pAreaData->origin();
origin.setAltitude(0); origin.setAltitude(0);
...@@ -1039,13 +1057,13 @@ void MeasurementComplexItem::resetGenerators() { ...@@ -1039,13 +1057,13 @@ void MeasurementComplexItem::resetGenerators() {
removeGenerator(0); removeGenerator(0);
} }
auto lg = routing::GeneratorFactory::instance()->create( auto lg =
routing::LinearGenerator::typeString, this); pGeneratorFactory->create(routing::LinearGenerator::typeString, this);
lg->setData(this->_pAreaData); lg->setData(this->_pAreaData);
addGenerator(lg); addGenerator(lg);
auto cg = routing::GeneratorFactory::instance()->create( auto cg =
routing::CircularGenerator::typeString, this); pGeneratorFactory->create(routing::CircularGenerator::typeString, this);
cg->setData(this->_pAreaData); cg->setData(this->_pAreaData);
addGenerator(cg); addGenerator(cg);
} }
...@@ -1139,6 +1157,24 @@ void MeasurementComplexItem::abortEditing() { ...@@ -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( void MeasurementComplexItem::_storeRoutingData(
MeasurementComplexItem::PtrRoutingData pRoute) { MeasurementComplexItem::PtrRoutingData pRoute) {
if (this->_state == STATE::ROUTING) { if (this->_state == STATE::ROUTING) {
......
...@@ -174,6 +174,31 @@ public: ...@@ -174,6 +174,31 @@ public:
//! editingStart(). //! editingStart().
//! //!
Q_INVOKABLE void abortEditing(); 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 // Property getters
const AreaData *areaData() const; const AreaData *areaData() const;
......
...@@ -12,6 +12,7 @@ ...@@ -12,6 +12,7 @@
#include <QTimer> #include <QTimer>
#include "GenericSingelton.h"
#include "geometry/MeasurementArea.h" #include "geometry/MeasurementArea.h"
#include "geometry/snake.h" #include "geometry/snake.h"
#include "nemo_interface/QNemoHeartbeat.h" #include "nemo_interface/QNemoHeartbeat.h"
...@@ -426,8 +427,15 @@ bool NemoInterface::Impl::setStatus(NemoInterface::STATUS s) { ...@@ -426,8 +427,15 @@ bool NemoInterface::Impl::setStatus(NemoInterface::STATUS s) {
// =============================================================== // ===============================================================
// NemoInterface // NemoInterface
NemoInterface::NemoInterface(QObject *parent) NemoInterface::NemoInterface()
: QObject(parent), pImpl(std::make_unique<NemoInterface::Impl>(this)) {} : QObject(), pImpl(std::make_unique<NemoInterface::Impl>(this)) {}
NemoInterface *NemoInterface::createInstance() { return new NemoInterface(); }
NemoInterface *NemoInterface::instance() {
return GenericSingelton<NemoInterface>::instance(
NemoInterface::createInstance);
}
NemoInterface::~NemoInterface() {} NemoInterface::~NemoInterface() {}
...@@ -449,9 +457,7 @@ bool NemoInterface::hasTileData(const TileData &tileData) const { ...@@ -449,9 +457,7 @@ bool NemoInterface::hasTileData(const TileData &tileData) const {
return this->pImpl->hasTileData(tileData); return this->pImpl->hasTileData(tileData);
} }
int NemoInterface::status() const { return integral(this->pImpl->status()); } NemoInterface::STATUS NemoInterface::status() const {
NemoInterface::STATUS NemoInterface::statusEnum() const {
return this->pImpl->status(); return this->pImpl->status();
} }
......
...@@ -12,7 +12,14 @@ class NemoInterface : public QObject { ...@@ -12,7 +12,14 @@ class NemoInterface : public QObject {
class Impl; class Impl;
using PImpl = std::unique_ptr<Impl>; using PImpl = std::unique_ptr<Impl>;
NemoInterface();
NemoInterface(NemoInterface &other) = delete;
static NemoInterface *createInstance();
public: public:
~NemoInterface() override;
static NemoInterface *instance();
enum class STATUS { enum class STATUS {
NOT_CONNECTED = 0, NOT_CONNECTED = 0,
HEARTBEAT_DETECTED = 1, HEARTBEAT_DETECTED = 1,
...@@ -20,11 +27,9 @@ public: ...@@ -20,11 +27,9 @@ public:
TIMEOUT = -1, TIMEOUT = -1,
INVALID_HEARTBEAT = -2 INVALID_HEARTBEAT = -2
}; };
Q_ENUM(STATUS)
explicit NemoInterface(QObject *parent = nullptr); Q_PROPERTY(STATUS status READ status NOTIFY statusChanged)
~NemoInterface() override;
Q_PROPERTY(int status READ status NOTIFY statusChanged)
Q_PROPERTY(QString statusString READ statusString NOTIFY statusChanged) Q_PROPERTY(QString statusString READ statusString NOTIFY statusChanged)
Q_PROPERTY(QVector<int> progress READ progress NOTIFY progressChanged) Q_PROPERTY(QVector<int> progress READ progress NOTIFY progressChanged)
Q_PROPERTY(QString editorQml READ editorQml CONSTANT) Q_PROPERTY(QString editorQml READ editorQml CONSTANT)
...@@ -40,8 +45,7 @@ public: ...@@ -40,8 +45,7 @@ public:
void setAutoPublish(bool ap); void setAutoPublish(bool ap);
void setHoldProgress(bool hp); void setHoldProgress(bool hp);
int status() const; STATUS status() const;
STATUS statusEnum() const;
QString statusString() const; QString statusString() const;
QVector<int> progress() const; QVector<int> progress() const;
QString editorQml(); QString editorQml();
...@@ -55,3 +59,5 @@ signals: ...@@ -55,3 +59,5 @@ signals:
private: private:
PImpl pImpl; PImpl pImpl;
}; };
#define pNemoInterface NemoInterface::instance()
...@@ -56,8 +56,14 @@ private: ...@@ -56,8 +56,14 @@ private:
// Example usage: // Example usage:
// QmlObjecListModel list; // QmlObjecListModel list;
// .... add areas .... // .... add areas ....
// auto area = getArea<WimaMeasurementArea *>(list); // returns the first // auto area = getGeoArea<MeasurementArea *>(list); // returns the first
// WimaMeasurementArea or nullptr // MeasurementArea or nullptr
//! \example
//!
//! QmlObjecListModel list;
//! // .... add areas ....
//! auto area = getGeoArea<MeasurementArea *>(list); // returns the first
//! MeasurementArea or nullptr
template <class AreaPtr, class QObjectList> template <class AreaPtr, class QObjectList>
inline AreaPtr getGeoArea(QObjectList &list) { inline AreaPtr getGeoArea(QObjectList &list) {
static_assert(std::is_pointer<AreaPtr>::value, static_assert(std::is_pointer<AreaPtr>::value,
...@@ -72,5 +78,28 @@ inline AreaPtr getGeoArea(QObjectList &list) { ...@@ -72,5 +78,28 @@ inline AreaPtr getGeoArea(QObjectList &list) {
return nullptr; return nullptr;
} }
//! \example
//!
//! QmlObjecListModel list;
//! // .... add areas ....
//! auto areaArray = getGeoAreaArray<MeasurementArea *>(list); // returns a
//! QList<MeasurementArea*>
//! // containing all MeasurementArea's inside list
template <class AreaPtr, template <class> class Container = QList,
class QObjectList>
inline Container<AreaPtr> getGeoAreaList(QObjectList &list) {
static_assert(std::is_pointer<AreaPtr>::value,
"AreaPtr must be a pointer type.");
Container<AreaPtr> out;
for (int i = 0; i < list.count(); ++i) {
auto obj = list[i];
auto area = qobject_cast<AreaPtr>(obj);
if (area != nullptr) {
out.append(area);
}
}
return out;
}
bool copyAreaList(const QmlObjectListModel &from, QmlObjectListModel &to, bool copyAreaList(const QmlObjectListModel &from, QmlObjectListModel &to,
QObject *parent); QObject *parent);
...@@ -2,6 +2,7 @@ ...@@ -2,6 +2,7 @@
#include "QtConcurrentRun" #include "QtConcurrentRun"
#include "nemo_interface/SnakeTile.h" #include "nemo_interface/SnakeTile.h"
#include "snake.h" #include "snake.h"
#include <ctime>
#include <boost/units/systems/si.hpp> #include <boost/units/systems/si.hpp>
...@@ -170,7 +171,7 @@ MeasurementArea::MeasurementArea(QObject *parent) ...@@ -170,7 +171,7 @@ MeasurementArea::MeasurementArea(QObject *parent)
this /* QObject parent */)), this /* QObject parent */)),
_showTiles(SettingsFact(settingsGroup, _metaDataMap[showTilesKey], _showTiles(SettingsFact(settingsGroup, _metaDataMap[showTilesKey],
this /* QObject parent */)), this /* QObject parent */)),
_state(STATE::IDLE) { _holdProgress(false), _state(STATE::IDLE) {
init(); init();
} }
...@@ -188,7 +189,7 @@ MeasurementArea::MeasurementArea(const MeasurementArea &other, QObject *parent) ...@@ -188,7 +189,7 @@ MeasurementArea::MeasurementArea(const MeasurementArea &other, QObject *parent)
this /* QObject parent */)), this /* QObject parent */)),
_showTiles(SettingsFact(settingsGroup, _metaDataMap[showTilesKey], _showTiles(SettingsFact(settingsGroup, _metaDataMap[showTilesKey],
this /* QObject parent */)), this /* QObject parent */)),
_state(STATE::IDLE) { _holdProgress(false), _state(STATE::IDLE) {
init(); init();
disableUpdate(); disableUpdate();
...@@ -272,6 +273,19 @@ int MeasurementArea::maxTiles() const { return SNAKE_MAX_TILES; } ...@@ -272,6 +273,19 @@ int MeasurementArea::maxTiles() const { return SNAKE_MAX_TILES; }
bool MeasurementArea::ready() const { return this->_state == STATE::IDLE; } 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) { bool MeasurementArea::saveToJson(QJsonObject &json) {
if (ready()) { if (ready()) {
if (this->GeoArea::saveToJson(json)) { if (this->GeoArea::saveToJson(json)) {
...@@ -406,15 +420,41 @@ bool MeasurementArea::isCorrect() { ...@@ -406,15 +420,41 @@ bool MeasurementArea::isCorrect() {
bool MeasurementArea::setProgress(const QVector<int> &p) { bool MeasurementArea::setProgress(const QVector<int> &p) {
if (ready()) { if (ready()) {
if (p.size() == this->tiles()->count() && this->_progress != p) { if (!_holdProgress && p.size() == this->tiles()->count() &&
this->_progress != p) {
this->_progress = p; this->_progress = p;
emit progressChanged(); emit progressChanged();
emit progressAccepted(); emit progressAccepted();
return true; return true;
} }
} }
emit progressNotAccepted();
return false; 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 //! \brief MeasurementArea::doUpdate
//! \pre MeasurementArea::deferUpdate must be called first, don't call //! \pre MeasurementArea::deferUpdate must be called first, don't call
...@@ -576,3 +616,12 @@ void MeasurementArea::setState(MeasurementArea::STATE s) { ...@@ -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();
}
}
...@@ -46,6 +46,8 @@ public: ...@@ -46,6 +46,8 @@ public:
Q_PROPERTY(QmlObjectListModel *tiles READ tiles NOTIFY tilesChanged) Q_PROPERTY(QmlObjectListModel *tiles READ tiles NOTIFY tilesChanged)
Q_PROPERTY(int maxTiles READ maxTiles NOTIFY maxTilesChanged) Q_PROPERTY(int maxTiles READ maxTiles NOTIFY maxTilesChanged)
Q_PROPERTY(QVector<int> progress READ progressQml NOTIFY progressChanged) Q_PROPERTY(QVector<int> progress READ progressQml NOTIFY progressChanged)
Q_PROPERTY(bool holdProgress READ holdProgress WRITE setHoldProgress NOTIFY
holdProgressChanged)
// Overrides from GeoArea // Overrides from GeoArea
QString mapVisualQML(void) const override; QString mapVisualQML(void) const override;
...@@ -69,10 +71,24 @@ public: ...@@ -69,10 +71,24 @@ public:
int maxTiles() const; int maxTiles() const;
bool ready() const; bool ready() const;
bool measurementCompleted() const;
// Static Variables // Static Variables
static const char *settingsGroup; static const char *settingsGroup;
static const char *nameString; 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: signals:
void tilesChanged(); void tilesChanged();
void maxTilesChanged(); void maxTilesChanged();
...@@ -80,9 +96,12 @@ signals: ...@@ -80,9 +96,12 @@ signals:
void progressAccepted(); void progressAccepted();
void progressNotAccepted(); void progressNotAccepted();
void readyChanged(); void readyChanged();
void holdProgressChanged();
public slots: public slots:
bool setProgress(const QVector<int> &p); bool setProgress(const QVector<int> &p);
Q_INVOKABLE void randomProgress();
Q_INVOKABLE void resetProgress();
private slots: private slots:
void doUpdate(); void doUpdate();
...@@ -105,6 +124,7 @@ private: ...@@ -105,6 +124,7 @@ private:
SettingsFact _showTiles; SettingsFact _showTiles;
QVector<int> _progress; QVector<int> _progress;
bool _holdProgress;
// Tile stuff. // Tile stuff.
// Tile stuff. // Tile stuff.
mutable QTimer _timer; mutable QTimer _timer;
......
import QtQuick 2.0 import QtQuick 2.0
import Qt.labs.settings 1.0
import QtQuick.Layouts 1.11 import QtQuick.Layouts 1.11
import QtQuick.Controls 1.4 import QtQuick.Controls 1.4
import QGroundControl.Controls 1.0 import QGroundControl.Controls 1.0
...@@ -40,17 +41,18 @@ GridLayout { ...@@ -40,17 +41,18 @@ GridLayout {
} }
} }
ExclusiveGroup {
id: areaGroup
}
QGCLabel { QGCLabel {
id: tipLabel text: _root.errorString
wrapMode: Text.WordWrap wrapMode: Text.WordWrap
horizontalAlignment: Text.AlignHCenter horizontalAlignment: Text.AlignLeft
text: qsTr("Use the Area Editor to modify areas.") color: "orange"
Layout.fillWidth: true
Layout.columnSpan: parent.columns Layout.columnSpan: parent.columns
Layout.fillWidth: true
visible: !_root.areasCorrect
}
ExclusiveGroup {
id: areaGroup
} }
Repeater { Repeater {
...@@ -135,7 +137,7 @@ GridLayout { ...@@ -135,7 +137,7 @@ GridLayout {
id: commandsHeader id: commandsHeader
Layout.fillWidth: true Layout.fillWidth: true
Layout.columnSpan: parent.columns Layout.columnSpan: parent.columns
text: qsTr("Commands and Errors") text: qsTr("Commands")
} }
GridLayout { GridLayout {
...@@ -146,16 +148,6 @@ GridLayout { ...@@ -146,16 +148,6 @@ GridLayout {
Layout.fillWidth: true Layout.fillWidth: true
visible: commandsHeader.checked 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 { QGCButton {
text: "Intersection" text: "Intersection"
enabled: _root.checked enabled: _root.checked
...@@ -168,10 +160,44 @@ GridLayout { ...@@ -168,10 +160,44 @@ GridLayout {
QGCButton { QGCButton {
text: "Reset" text: "Reset"
onClicked: {
_root.reset()
}
Layout.fillWidth: true
}
QGCButton {
text: "Abort"
onClicked: { onClicked: {
_root.abort() _root.abort()
} }
Layout.fillWidth: true 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 Layout.columnSpan: parent.columns
} }
} }
...@@ -193,4 +219,8 @@ GridLayout { ...@@ -193,4 +219,8 @@ GridLayout {
} }
} }
} }
Settings {
property alias showHint: hintHeader.checked
}
} }
/**************************************************************************** /****************************************************************************
* *
* (c) 2009-2016 QGROUNDCONTROL PROJECT <http://www.qgroundcontrol.org> * (c) 2009-2016 QGROUNDCONTROL PROJECT <http://www.qgroundcontrol.org>
...@@ -6,25 +8,24 @@ ...@@ -6,25 +8,24 @@
* COPYING.md in the root of the source code directory. * COPYING.md in the root of the source code directory.
* *
****************************************************************************/ ****************************************************************************/
import QtQuick 2.3
import QtQuick 2.3
import QtQuick.Controls 1.2 import QtQuick.Controls 1.2
import QtLocation 5.3 import QtLocation 5.3
import QtPositioning 5.3 import QtPositioning 5.3
import QGroundControl 1.0 import QGroundControl 1.0
import QGroundControl.ScreenTools 1.0 import QGroundControl.ScreenTools 1.0
import QGroundControl.Palette 1.0 import QGroundControl.Palette 1.0
import QGroundControl.Controls 1.0 import QGroundControl.Controls 1.0
import QGroundControl.FlightMap 1.0 import QGroundControl.FlightMap 1.0
Item { Item {
id: _root id: _root
property var map: undefined ///< Map control to place item in property var map: undefined ///< Map control to place item in
property var geoArea: undefined ///< GeoArea derived class property var geoArea: undefined ///< GeoArea derived class
opacity: 0.3 opacity: 0.2
signal clicked(int sequenceNumber) signal clicked(int sequenceNumber)
...@@ -35,31 +36,30 @@ Item { ...@@ -35,31 +36,30 @@ Item {
// Area polygon // Area polygon
QGCMapPolygonVisuals { QGCMapPolygonVisuals {
id: mapPolygonVisuals id: mapPolygonVisuals
mapControl: _root.map mapControl: _root.map
mapPolygon: _root.geoArea mapPolygon: _root.geoArea
interactive: geoArea.interactive interactive: geoArea.interactive
borderWidth: 3 borderWidth: 3
borderColor: "green" interiorColor: "green"
interiorColor: "green" altColor: QGroundControl.globalPalette.surveyPolygonTerrainCollision
altColor: QGroundControl.globalPalette.surveyPolygonTerrainCollision z: QGroundControl.zOrderMapItems - 1
z: QGroundControl.zOrderMapItems-1 interiorOpacity: _root.opacity
interiorOpacity: _root.opacity
} }
// Add Snake tiles to the map // Add Snake tiles to the map
Component { Component {
id: tileComponent id: tileComponent
Item{ Item {
id: root id: root
property MapPolygon polygon property MapPolygon polygon
MapPolygon{ MapPolygon {
id:mapPolygon id: mapPolygon
path: [] path: []
} }
Component.onCompleted: { Component.onCompleted: {
...@@ -90,27 +90,27 @@ Item { ...@@ -90,27 +90,27 @@ Item {
property bool enable: geoArea.showTiles.value property bool enable: geoArea.showTiles.value
model: enable ? geoArea.tiles : [] model: enable ? geoArea.tiles : []
Item{ Item {
property var _tileComponent property var _tileComponent
property int _progress: _root.geoArea.progress[index] ? property int _progress: _root.geoArea.progress[index] ? _root.geoArea.progress[index] : 0
_root.geoArea.progress[index] : 0
Component.onCompleted: { Component.onCompleted: {
_tileComponent = tileComponent.createObject(map) _tileComponent = tileComponent.createObject(map)
_tileComponent.polygon.path = _tileComponent.polygon.path = Qt.binding(function () {
Qt.binding(function(){return object.path}) return object.path
})
_tileComponent.polygon.opacity = 0.6 _tileComponent.polygon.opacity = 0.6
_tileComponent.polygon.border.color = "black" _tileComponent.polygon.border.color = "black"
_tileComponent.polygon.border.width = 1 _tileComponent.polygon.border.width = 1
_tileComponent.polygon.color = _tileComponent.polygon.color = Qt.binding(function () {
Qt.binding(function(){return getColor(_progress)}) return getColor(_progress)
})
} }
Component.onDestruction: { Component.onDestruction: {
_tileComponent.destroy() _tileComponent.destroy()
} }
} }
} }
} }
...@@ -4,3 +4,4 @@ LinearGenerator 1.0 LinearGenerator.qml ...@@ -4,3 +4,4 @@ LinearGenerator 1.0 LinearGenerator.qml
CircularGenerator 1.0 CircularGenerator.qml CircularGenerator 1.0 CircularGenerator.qml
SafeAreaEditor 1.0 SafeAreaEditor.qml SafeAreaEditor 1.0 SafeAreaEditor.qml
MeasurementAreaEditor 1.0 MeasurementAreaEditor.qml MeasurementAreaEditor 1.0 MeasurementAreaEditor.qml
NemoEditor 1.0 NemoEditor.qml
...@@ -60,7 +60,7 @@ Rectangle { ...@@ -60,7 +60,7 @@ Rectangle {
Component.onCompleted: currentIndex = editing ? areaEditorIndex : parameterEditorIndex Component.onCompleted: currentIndex = editing ? areaEditorIndex : parameterEditorIndex
QGCTabButton { QGCTabButton {
icon.source: "/qmlimages/PatternCamera.png" icon.source: "qrc:/res/waypoint.svg"
icon.height: ScreenTools.defaultFontPixelHeight icon.height: ScreenTools.defaultFontPixelHeight
} }
QGCTabButton { QGCTabButton {
...@@ -68,7 +68,7 @@ Rectangle { ...@@ -68,7 +68,7 @@ Rectangle {
icon.height: ScreenTools.defaultFontPixelHeight icon.height: ScreenTools.defaultFontPixelHeight
} }
QGCTabButton { QGCTabButton {
icon.source: "/qmlimages/PatternPresets.png" icon.source: "qrc:/res/fish.svg"
icon.height: ScreenTools.defaultFontPixelHeight icon.height: ScreenTools.defaultFontPixelHeight
} }
...@@ -124,6 +124,14 @@ Rectangle { ...@@ -124,6 +124,14 @@ Rectangle {
missionItem: _root._missionItem missionItem: _root._missionItem
availableWidth: mainColumn.width availableWidth: mainColumn.width
} }
MCI.NemoEditor {
id: nemoEditor
checked: visible
missionItem: _root._missionItem
availableWidth: mainColumn.width
}
} }
} // main Column } // main Column
} // Rectangle } // Rectangle
...@@ -56,9 +56,9 @@ Item { ...@@ -56,9 +56,9 @@ Item {
Component.onCompleted: { Component.onCompleted: {
console.assert(map != undefined, "please set the map property") console.assert(map != undefined, "please set the map property")
if (!_missionItem.areaData.initialized()){ if (!_missionItem.initialized()){
var bbox = boundingBox() var bbox = boundingBox()
_missionItem.areaData.initialize(bbox[0], bbox[1]) _missionItem.initialize(bbox[0], bbox[1])
} }
// _addEntryCoordinate() // _addEntryCoordinate()
// _addExitCoordinate() // _addExitCoordinate()
......
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!")
}
}
}
}
...@@ -39,11 +39,10 @@ Item { ...@@ -39,11 +39,10 @@ Item {
mapPolygon: geoArea mapPolygon: geoArea
interactive: geoArea.interactive interactive: geoArea.interactive
borderWidth: 2 borderWidth: 2
borderColor: "blue"
interiorColor: "blue" interiorColor: "blue"
altColor: QGroundControl.globalPalette.surveyPolygonTerrainCollision altColor: QGroundControl.globalPalette.surveyPolygonTerrainCollision
z: QGroundControl.zOrderMapItems-1 z: QGroundControl.zOrderMapItems-1
interiorOpacity: 0.3 interiorOpacity: 0.2
} }
Item { Item {
......
...@@ -7,157 +7,155 @@ ...@@ -7,157 +7,155 @@
* *
****************************************************************************/ ****************************************************************************/
#ifndef MissionItem_H #ifndef MissionItem_H
#define MissionItem_H #define MissionItem_H
#include <QGeoCoordinate>
#include <QJsonObject>
#include <QObject> #include <QObject>
#include <QString> #include <QString>
#include <QtQml>
#include <QTextStream> #include <QTextStream>
#include <QJsonObject> #include <QtQml>
#include <QGeoCoordinate>
#include "QGCMAVLink.h"
#include "QGC.h"
#include "QmlObjectListModel.h"
#include "Fact.h" #include "Fact.h"
#include "QGC.h"
#include "QGCLoggingCategory.h" #include "QGCLoggingCategory.h"
#include "QGCMAVLink.h"
#include "QmlObjectListModel.h" #include "QmlObjectListModel.h"
class SurveyComplexItem; class SurveyComplexItem;
class RouteComplexItem;
class SimpleMissionItem; class SimpleMissionItem;
class MissionController; class MissionController;
#ifdef UNITTEST_BUILD #ifdef UNITTEST_BUILD
class MissionItemTest; class MissionItemTest;
#endif #endif
// Represents a Mavlink mission command. // Represents a Mavlink mission command.
class MissionItem : public QObject class MissionItem : public QObject {
{ Q_OBJECT
Q_OBJECT
public: public:
MissionItem(QObject* parent = nullptr); MissionItem(QObject *parent = nullptr);
MissionItem(int sequenceNumber, MissionItem(int sequenceNumber, MAV_CMD command, MAV_FRAME frame,
MAV_CMD command, double param1, double param2, double param3, double param4,
MAV_FRAME frame, double param5, double param6, double param7, bool autoContinue,
double param1, bool isCurrentItem, QObject *parent = nullptr);
double param2,
double param3, MissionItem(const MissionItem &other, QObject *parent = nullptr);
double param4,
double param5, ~MissionItem();
double param6,
double param7, const MissionItem &operator=(const MissionItem &other);
bool autoContinue,
bool isCurrentItem, MAV_CMD command(void) const {
QObject* parent = nullptr); return (MAV_CMD)_commandFact.rawValue().toInt();
}
MissionItem(const MissionItem& other, QObject* parent = nullptr); bool isCurrentItem(void) const { return _isCurrentItem; }
int sequenceNumber(void) const { return _sequenceNumber; }
~MissionItem(); MAV_FRAME frame(void) const {
return (MAV_FRAME)_frameFact.rawValue().toInt();
const MissionItem& operator=(const MissionItem& other); }
bool autoContinue(void) const {
MAV_CMD command (void) const { return (MAV_CMD)_commandFact.rawValue().toInt(); } return _autoContinueFact.rawValue().toBool();
bool isCurrentItem (void) const { return _isCurrentItem; } }
int sequenceNumber (void) const { return _sequenceNumber; } double param1(void) const { return _param1Fact.rawValue().toDouble(); }
MAV_FRAME frame (void) const { return (MAV_FRAME)_frameFact.rawValue().toInt(); } double param2(void) const { return _param2Fact.rawValue().toDouble(); }
bool autoContinue (void) const { return _autoContinueFact.rawValue().toBool(); } double param3(void) const { return _param3Fact.rawValue().toDouble(); }
double param1 (void) const { return _param1Fact.rawValue().toDouble(); } double param4(void) const { return _param4Fact.rawValue().toDouble(); }
double param2 (void) const { return _param2Fact.rawValue().toDouble(); } double param5(void) const { return _param5Fact.rawValue().toDouble(); }
double param3 (void) const { return _param3Fact.rawValue().toDouble(); } double param6(void) const { return _param6Fact.rawValue().toDouble(); }
double param4 (void) const { return _param4Fact.rawValue().toDouble(); } double param7(void) const { return _param7Fact.rawValue().toDouble(); }
double param5 (void) const { return _param5Fact.rawValue().toDouble(); } QGeoCoordinate coordinate(void) const;
double param6 (void) const { return _param6Fact.rawValue().toDouble(); } int doJumpId(void) const { return _doJumpId; }
double param7 (void) const { return _param7Fact.rawValue().toDouble(); }
QGeoCoordinate coordinate (void) const; /// @return Flight speed change value if this item supports it. If not it
int doJumpId (void) const { return _doJumpId; } /// returns NaN.
double specifiedFlightSpeed(void) const;
/// @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.
/// @return Flight gimbal yaw change value if this item supports it. If not it returns NaN. double specifiedGimbalYaw(void) const;
double specifiedGimbalYaw(void) const;
/// @return Flight gimbal pitch change value if this item supports it. If not
/// @return Flight gimbal pitch change value if this item supports it. If not it returns NaN. /// it returns NaN.
double specifiedGimbalPitch(void) const; double specifiedGimbalPitch(void) const;
void setCommand (MAV_CMD command); void setCommand(MAV_CMD command);
void setSequenceNumber (int sequenceNumber); void setSequenceNumber(int sequenceNumber);
void setIsCurrentItem (bool isCurrentItem); void setIsCurrentItem(bool isCurrentItem);
void setFrame (MAV_FRAME frame); void setFrame(MAV_FRAME frame);
void setAutoContinue (bool autoContinue); void setAutoContinue(bool autoContinue);
void setParam1 (double param1); void setParam1(double param1);
void setParam2 (double param2); void setParam2(double param2);
void setParam3 (double param3); void setParam3(double param3);
void setParam4 (double param4); void setParam4(double param4);
void setParam5 (double param5); void setParam5(double param5);
void setParam6 (double param6); void setParam6(double param6);
void setParam7 (double param7); void setParam7(double param7);
void save(QJsonObject& json) const; void save(QJsonObject &json) const;
bool load(QTextStream &loadStream); bool load(QTextStream &loadStream);
bool load(const QJsonObject& json, int sequenceNumber, QString& errorString); bool load(const QJsonObject &json, int sequenceNumber, QString &errorString);
bool relativeAltitude(void) const { return frame() == MAV_FRAME_GLOBAL_RELATIVE_ALT; } bool relativeAltitude(void) const {
return frame() == MAV_FRAME_GLOBAL_RELATIVE_ALT;
}
signals: signals:
void isCurrentItemChanged (bool isCurrentItem); void isCurrentItemChanged(bool isCurrentItem);
void sequenceNumberChanged (int sequenceNumber); void sequenceNumberChanged(int sequenceNumber);
void specifiedFlightSpeedChanged(double flightSpeed); void specifiedFlightSpeedChanged(double flightSpeed);
void specifiedGimbalYawChanged (double gimbalYaw); void specifiedGimbalYawChanged(double gimbalYaw);
void specifiedGimbalPitchChanged(double gimbalPitch); void specifiedGimbalPitchChanged(double gimbalPitch);
private slots: private slots:
void _param1Changed(QVariant value); void _param1Changed(QVariant value);
void _param2Changed(QVariant value); void _param2Changed(QVariant value);
void _param3Changed(QVariant value); void _param3Changed(QVariant value);
private: private:
bool _convertJsonV1ToV2(const QJsonObject& json, QJsonObject& v2Json, QString& errorString); bool _convertJsonV1ToV2(const QJsonObject &json, QJsonObject &v2Json,
bool _convertJsonV2ToV3(QJsonObject& json, QString& errorString); QString &errorString);
bool _convertJsonV2ToV3(QJsonObject &json, QString &errorString);
Fact _autoContinueFact; Fact _autoContinueFact;
Fact _commandFact; Fact _commandFact;
Fact _frameFact; Fact _frameFact;
Fact _param1Fact; Fact _param1Fact;
Fact _param2Fact; Fact _param2Fact;
Fact _param3Fact; Fact _param3Fact;
Fact _param4Fact; Fact _param4Fact;
Fact _param5Fact; Fact _param5Fact;
Fact _param6Fact; Fact _param6Fact;
Fact _param7Fact; Fact _param7Fact;
int _sequenceNumber; int _sequenceNumber;
int _doJumpId; int _doJumpId;
bool _isCurrentItem; bool _isCurrentItem;
// Keys for Json save // Keys for Json save
static const char* _jsonFrameKey; static const char *_jsonFrameKey;
static const char* _jsonCommandKey; static const char *_jsonCommandKey;
static const char* _jsonAutoContinueKey; static const char *_jsonAutoContinueKey;
static const char* _jsonParamsKey; static const char *_jsonParamsKey;
static const char* _jsonDoJumpIdKey; static const char *_jsonDoJumpIdKey;
// Deprecated V2 format keys // Deprecated V2 format keys
static const char* _jsonCoordinateKey; static const char *_jsonCoordinateKey;
// Deprecated V1 format keys // Deprecated V1 format keys
static const char* _jsonParam1Key; static const char *_jsonParam1Key;
static const char* _jsonParam2Key; static const char *_jsonParam2Key;
static const char* _jsonParam3Key; static const char *_jsonParam3Key;
static const char* _jsonParam4Key; static const char *_jsonParam4Key;
friend class SurveyComplexItem; friend class SurveyComplexItem;
friend class RouteComplexItem; friend class RouteComplexItem;
friend class SimpleMissionItem; friend class SimpleMissionItem;
friend class MissionController; friend class MissionController;
#ifdef UNITTEST_BUILD #ifdef UNITTEST_BUILD
friend class MissionItemTest; friend class MissionItemTest;
#endif #endif
}; };
......
...@@ -186,6 +186,11 @@ static QObject *shapeFileHelperSingletonFactory(QQmlEngine *, QJSEngine *) { ...@@ -186,6 +186,11 @@ static QObject *shapeFileHelperSingletonFactory(QQmlEngine *, QJSEngine *) {
return new ShapeFileHelper; return new ShapeFileHelper;
} }
QObject *getNemoInterface(QQmlEngine *engine, QJSEngine *) {
engine->setObjectOwnership(pNemoInterface, QQmlEngine::CppOwnership);
return pNemoInterface;
}
QGCApplication::QGCApplication(int &argc, char *argv[], bool unitTesting) QGCApplication::QGCApplication(int &argc, char *argv[], bool unitTesting)
: QApplication(argc, argv), _runningUnitTests(unitTesting) { : QApplication(argc, argv), _runningUnitTests(unitTesting) {
_app = this; _app = this;
...@@ -665,13 +670,13 @@ void QGCApplication::_initCommon() { ...@@ -665,13 +670,13 @@ void QGCApplication::_initCommon() {
#endif #endif
qmlRegisterUncreatableType<routing::LinearGenerator>( qmlRegisterUncreatableType<routing::LinearGenerator>(
"RouteComplexItem", 1, 0, "LinearGenerator", kRefOnly); "MeasurementComplexItem", 1, 0, "LinearGenerator", kRefOnly);
qmlRegisterType<AreaData>("RouteComplexItem", 1, 0, "AreaData"); qmlRegisterType<AreaData>("MeasurementComplexItem", 1, 0, "AreaData");
qmlRegisterUncreatableType<NemoInterface>("RouteComplexItem", 1, 0, qmlRegisterSingletonType<NemoInterface>("MeasurementComplexItem", 1, 0,
"NemoInterface", kRefOnly); "NemoInterface", getNemoInterface);
qmlRegisterInterface<routing::GeneratorBase>("GeneratorBase"); qmlRegisterInterface<routing::GeneratorBase>("GeneratorBase");
qmlRegisterUncreatableType<routing::CircularGenerator>( qmlRegisterUncreatableType<routing::CircularGenerator>(
"RouteComplexItem", 1, 0, "CircularGenerator", kRefOnly); "MeasurementComplexItem", 1, 0, "CircularGenerator", kRefOnly);
qmlRegisterType<GeoTagController>(kQGCControllers, 1, 0, "GeoTagController"); qmlRegisterType<GeoTagController>(kQGCControllers, 1, 0, "GeoTagController");
qmlRegisterType<MavlinkConsoleController>(kQGCControllers, 1, 0, qmlRegisterType<MavlinkConsoleController>(kQGCControllers, 1, 0,
......
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