Commit ab5abb37 authored by Valentin Platzgummer's avatar Valentin Platzgummer

proper pictures added to MeasurementItemEditor.qml

parent 1b05f323
......@@ -18,7 +18,7 @@
<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-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-white.svg">resources/gear-white.svg</file>
<file alias="helicoptericon.svg">resources/helicoptericon.svg</file>
......@@ -34,7 +34,7 @@
<file alias="Play">resources/Play.svg</file>
<file alias="PowerButton">resources/PowerButton.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="QGCLogoArrow">resources/QGCLogoArrow.svg</file>
<file alias="QGroundControlConnect">resources/QGroundControlConnect.svg</file>
......@@ -56,6 +56,7 @@
<file alias="street.png">resources/street.png</file>
<file alias="measurement.png">resources/measurement.png</file>
<file alias="calculator.png">resources/calculator.png</file>
<file alias="fish.svg">resources/fish.svg</file>
</qresource>
<qresource prefix="/res/firmware">
<file alias="3drradio.png">resources/firmware/3drradio.png</file>
......
......@@ -293,6 +293,7 @@
<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/qmldir">src/MeasurementComplexItem/qml/MeasurementComplexItem.qmldir</file>
<file alias="MeasurementComplexItem/NemoEditor.qml">src/MeasurementComplexItem/qml/NemoEditor.qml</file>
</qresource>
<qresource prefix="/FirstRunPromptDialogs">
<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) {
// 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<MeasurementArea *>(_areaList);
QVector<MeasurementArea *> AreaData::measurementAreaArray() {
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 {
if (_areaList.count() == other._areaList.count()) {
......@@ -442,13 +461,13 @@ bool AreaData::_getAreas(MeasurementArea **measurementArea, SafeArea **safeArea,
*measurementArea = getGeoArea<MeasurementArea *>(_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<SafeArea *>(_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;
}
......
......@@ -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<MeasurementArea *> measurementAreaArray();
QVector<SafeArea *> 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;
};
......@@ -83,9 +83,9 @@ private:
std::map<QString, Creator> _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
......@@ -3,6 +3,8 @@
#include <QScopedPointer>
#include <QtGlobal>
// from https://stackoverflow.com/questions/46172607/qt-singleton-implementation
template <class T> class GenericSingelton {
private:
typedef T *(*CreateInstanceFunction)();
......
......@@ -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<QGCQGeoCoordinate *>(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) {
......
......@@ -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;
......
......@@ -12,6 +12,7 @@
#include <QTimer>
#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<NemoInterface::Impl>(this)) {}
NemoInterface::NemoInterface()
: 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() {}
......@@ -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();
}
......
......@@ -12,7 +12,14 @@ class NemoInterface : public QObject {
class Impl;
using PImpl = std::unique_ptr<Impl>;
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<int> 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<int> progress() const;
QString editorQml();
......@@ -55,3 +59,5 @@ signals:
private:
PImpl pImpl;
};
#define pNemoInterface NemoInterface::instance()
......@@ -56,8 +56,14 @@ private:
// Example usage:
// QmlObjecListModel list;
// .... add areas ....
// auto area = getArea<WimaMeasurementArea *>(list); // returns the first
// WimaMeasurementArea or nullptr
// auto area = getGeoArea<MeasurementArea *>(list); // returns the first
// MeasurementArea or nullptr
//! \example
//!
//! QmlObjecListModel list;
//! // .... add areas ....
//! auto area = getGeoArea<MeasurementArea *>(list); // returns the first
//! MeasurementArea or nullptr
template <class AreaPtr, class QObjectList>
inline AreaPtr getGeoArea(QObjectList &list) {
static_assert(std::is_pointer<AreaPtr>::value,
......@@ -72,5 +78,28 @@ inline AreaPtr getGeoArea(QObjectList &list) {
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,
QObject *parent);
......@@ -2,6 +2,7 @@
#include "QtConcurrentRun"
#include "nemo_interface/SnakeTile.h"
#include "snake.h"
#include <ctime>
#include <boost/units/systems/si.hpp>
......@@ -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<int> &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();
}
}
......@@ -46,6 +46,8 @@ public:
Q_PROPERTY(QmlObjectListModel *tiles READ tiles NOTIFY tilesChanged)
Q_PROPERTY(int maxTiles READ maxTiles NOTIFY maxTilesChanged)
Q_PROPERTY(QVector<int> 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<int> &p);
Q_INVOKABLE void randomProgress();
Q_INVOKABLE void resetProgress();
private slots:
void doUpdate();
......@@ -105,6 +124,7 @@ private:
SettingsFact _showTiles;
QVector<int> _progress;
bool _holdProgress;
// Tile stuff.
// Tile stuff.
mutable QTimer _timer;
......
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
}
}
/****************************************************************************
*
* (c) 2009-2016 QGROUNDCONTROL PROJECT <http://www.qgroundcontrol.org>
......@@ -6,25 +8,24 @@