Commit be40a955 authored by Valentin Platzgummer's avatar Valentin Platzgummer

MeasurementItemEditor fixed

parent 3dfdeec9
......@@ -261,26 +261,20 @@
<file alias="QmlTest.qml">src/QmlControls/QmlTest.qml</file>
<file alias="RadioComponent.qml">src/AutoPilotPlugins/Common/RadioComponent.qml</file>
<file alias="SerialSettings.qml">src/ui/preferences/SerialSettings.qml</file>
<file alias="CircularGeneratorEditor.qml">src/WimaView/CircularGeneratorEditor.qml</file>
<file alias="QGroundControl/Controls/CircularGeneratorMapVisual.qml">src/WimaView/CircularGeneratorMapVisual.qml</file>
<file alias="CircularSurveyItemEditor.qml">src/WimaView/MeasurementItemEditor.qml</file>
<file alias="QGroundControl/Controls/CircularSurveyMapVisual.qml">src/WimaView/MeasurementItemMapVisual.qml</file>
<file alias="Wima/CoordinateIndicator.qml">src/WimaView/CoordinateIndicator.qml</file>
<file alias="Wima/CoordinateIndicatorDrag.qml">src/WimaView/CoordinateIndicatorDrag.qml</file>
<file alias="Wima/DragCoordinate.qml">src/WimaView/DragCoordinate.qml</file>
<file alias="LinearGeneratorEditor.qml">src/WimaView/LinearGeneratorEditor.qml</file>
<file alias="Wima/ProgressIndicator.qml">src/WimaView/ProgressIndicator.qml</file>
<file alias="Wima/qmldir">src/WimaView/Wima.qmldir</file>
<file alias="Wima/WimaAreaMapVisual.qml">src/WimaView/WimaAreaMapVisual.qml</file>
<file alias="Wima/WimaCorridorEditor.qml">src/WimaView/WimaCorridorEditor.qml</file>
<file alias="Wima/WimaItemEditor.qml">src/WimaView/WimaItemEditor.qml</file>
<file alias="Wima/WimaMapPolygonVisuals.qml">src/WimaView/WimaMapPolygonVisuals.qml</file>
<file alias="Wima/WimaMapVisual.qml">src/WimaView/WimaMapVisual.qml</file>
<file alias="Wima/WimaMeasurementAreaEditor.qml">src/WimaView/MeasurementAreaEditor.qml</file>
<file alias="Wima/WimaMeasurementAreaMapVisual.qml">src/WimaView/MeasurementAreaMapVisual.qml</file>
<file alias="Wima/WimaServiceAreaEditor.qml">src/WimaView/SafeAreaEditor.qml</file>
<file alias="Wima/WimaServiceAreaMapVisual.qml">src/WimaView/SafeAreaMapVisual.qml</file>
<file alias="Wima/WimaToolBar.qml">src/WimaView/WimaToolBar.qml</file>
<file alias="CircularGeneratorEditor.qml">src/MeasurementComplexItem/qml/CircularGeneratorEditor.qml</file>
<file alias="QGroundControl/Controls/CircularGeneratorMapVisual.qml">src/MeasurementComplexItem/qml/CircularGeneratorMapVisual.qml</file>
<file alias="MeasurementItemEditor.qml">src/MeasurementComplexItem/qml/MeasurementItemEditor.qml</file>
<file alias="QGroundControl/Controls/MeasurementItemMapVisual.qml">src/MeasurementComplexItem/qml/MeasurementItemMapVisual.qml</file>
<file alias="CoordinateIndicator.qml">src/MeasurementComplexItem/qml/CoordinateIndicator.qml</file>
<file alias="CoordinateIndicatorDrag.qml">src/MeasurementComplexItem/qml/CoordinateIndicatorDrag.qml</file>
<file alias="DragCoordinate.qml">src/MeasurementComplexItem/qml/DragCoordinate.qml</file>
<file alias="LinearGeneratorEditor.qml">src/MeasurementComplexItem/qml/LinearGeneratorEditor.qml</file>
<file alias="ProgressIndicator.qml">src/MeasurementComplexItem/qml/ProgressIndicator.qml</file>
<file alias="QGroundControl/Controls/GeoAreaVisualLoader.qml">src/MeasurementComplexItem/qml/GeoAreaVisualLoader.qml</file>
<file alias="MeasurementAreaEditor.qml">src/MeasurementComplexItem/qml/MeasurementAreaEditor.qml</file>
<file alias="MeasurementAreaMapVisual.qml">src/MeasurementComplexItem/qml/MeasurementAreaMapVisual.qml</file>
<file alias="SafeAreaEditor.qml">src/MeasurementComplexItem/qml/SafeAreaEditor.qml</file>
<file alias="SafeAreaMapVisual.qml">src/MeasurementComplexItem/qml/SafeAreaMapVisual.qml</file>
<file alias="SetupParameterEditor.qml">src/VehicleSetup/SetupParameterEditor.qml</file>
<file alias="SetupView.qml">src/VehicleSetup/SetupView.qml</file>
<file alias="SimpleItemEditor.qml">src/PlanView/SimpleItemEditor.qml</file>
......@@ -295,6 +289,7 @@
<file alias="VibrationPage.qml">src/AnalyzeView/VibrationPage.qml</file>
<file alias="VirtualJoystick.qml">src/FlightDisplay/VirtualJoystick.qml</file>
<file alias="VTOLLandingPatternEditor.qml">src/PlanView/VTOLLandingPatternEditor.qml</file>
<file>src/MeasurementComplexItem/qml/GeoAreaEditorLoader.qml</file>
</qresource>
<qresource prefix="/FirstRunPromptDialogs">
<file alias="UnitsFirstRunPrompt.qml">src/FirstRunPromptDialogs/UnitsFirstRunPrompt.qml</file>
......@@ -352,9 +347,10 @@
<file alias="Video.SettingsGroup.json">src/Settings/Video.SettingsGroup.json</file>
<file alias="VTOLLandingPattern.FactMetaData.json">src/MissionManager/VTOLLandingPattern.FactMetaData.json</file>
<file alias="Wima.SettingsGroup.json">src/Settings/Wima.SettingsGroup.json</file>
<file>src/MeasurementComplexItem/json/CircularGenerator.SettingsGroup.json</file>
<file>src/MeasurementComplexItem/json/LinearGenerator.SettingsGroup.json</file>
<file>src/MeasurementComplexItem/json/MeasurementComplexItem.SettingsGroup.json</file>
<file alias="CircularGenerator.SettingsGroup.json">src/MeasurementComplexItem/json/CircularGenerator.SettingsGroup.json</file>
<file alias="LinearGenerator.SettingsGroup.json">src/MeasurementComplexItem/json/LinearGenerator.SettingsGroup.json</file>
<file alias="MeasurementComplexItem.SettingsGroup.json">src/MeasurementComplexItem/json/MeasurementComplexItem.SettingsGroup.json</file>
<file alias="MeasurementArea.SettingsGroup.json">src/MeasurementComplexItem/geometry/json/MeasurementArea.SettingsGroup.json</file>
</qresource>
<qresource prefix="/MockLink">
<file alias="APMArduSubMockLink.params">src/comm/APMArduSubMockLink.params</file>
......
......@@ -30,29 +30,11 @@ AreaData &AreaData::operator=(const AreaData &other) {
}
bool AreaData::insert(GeoArea *areaData) {
{
SafeArea *area = qobject_cast<SafeArea *>(areaData);
if (area != nullptr) {
if (Q_LIKELY(!this->_areaList.contains(area))) {
_areaList.append(area);
emit areaList();
return true;
} else {
return false;
}
}
}
{
MeasurementArea *area = qobject_cast<MeasurementArea *>(areaData);
if (area != nullptr) {
if (Q_LIKELY(!this->_areaList.contains(area))) {
_areaList.append(area);
emit areaList();
return true;
} else {
return false;
}
if (areaData != nullptr) {
if (Q_LIKELY(!this->_areaList.contains(areaData))) {
_areaList.append(areaData);
emit areaList();
return true;
}
}
......@@ -111,7 +93,9 @@ bool AreaData::initialize(const QGeoCoordinate &bottomLeft,
auto *safeArea = getGeoArea<SafeArea *>(_areaList);
if (safeArea == nullptr) {
if (!insert(new SafeArea())) {
safeArea = new SafeArea(this);
if (!insert(safeArea)) {
safeArea->deleteLater();
qCCritical(AreaDataLog)
<< "initialize(): safeArea == nullptr, but insert() failed.";
return false;
......@@ -119,7 +103,9 @@ bool AreaData::initialize(const QGeoCoordinate &bottomLeft,
}
if (measurementArea == nullptr) {
if (!insert(new MeasurementArea())) {
measurementArea = new MeasurementArea(this);
if (!insert(measurementArea)) {
measurementArea->deleteLater();
qCCritical(AreaDataLog) << "initialize(): measurementArea == nullptr, "
"but insert() failed.";
return false;
......
......@@ -41,14 +41,15 @@ MeasurementComplexItem::MeasurementComplexItem(
const QString &kmlOrShpFile, QObject *parent)
: ComplexMissionItem(masterController, flyView, parent),
_masterController(masterController), _sequenceNumber(0),
_followTerrain(false),
_altitude(settingsGroup, _metaDataMap[altitudeName]), _state(STATE::IDLE),
_followTerrain(false), _state(STATE::IDLE),
_metaDataMap(FactMetaData::createMapFromJsonFile(
QStringLiteral(":/json/MeasurementComplexItem.SettingsGroup.json"),
this)),
_altitude(settingsGroup, _metaDataMap[altitudeName]),
_variant(settingsGroup, _metaDataMap[variantName]),
_areaData(new AreaData(this)), _editorData(new AreaData(this)),
_currentData(_areaData), _pWorker(new RoutingThread(this)) {
_pAreaData(new AreaData(this)), _pEditorData(new AreaData(this)),
_pCurrentData(_pAreaData), _pGenerator(nullptr),
_pWorker(new RoutingThread(this)) {
Q_UNUSED(kmlOrShpFile)
_editorQml = "qrc:/qml/MeasurementItemEditor.qml";
......@@ -61,7 +62,7 @@ MeasurementComplexItem::MeasurementComplexItem(
connect(this->_pWorker, &RoutingThread::result, this,
&MeasurementComplexItem::_storeRoutingData);
// Connect coordinate and exitCoordinate
// Connect coordinate and exitCoordinate.
connect(this, &MeasurementComplexItem::routeChanged,
[this] { emit this->coordinateChanged(this->coordinate()); });
connect(this, &MeasurementComplexItem::routeChanged,
......@@ -71,10 +72,14 @@ MeasurementComplexItem::MeasurementComplexItem(
this->exitCoordinateSameAsEntry());
});
// Connect complexDistance.
connect(this, &MeasurementComplexItem::routeChanged,
[this] { emit this->complexDistanceChanged(); });
// Register Generators.
auto lg = new routing::LinearGenerator(this->_areaData, this);
auto lg = new routing::LinearGenerator(this->_pAreaData, this);
registerGenerator(lg->name(), lg);
auto cg = new routing::CircularGenerator(this->_areaData, this);
auto cg = new routing::CircularGenerator(this->_pAreaData, this);
registerGenerator(cg->name(), cg);
qCritical() << "ToDo: _altitude connections missing.";
......@@ -86,10 +91,10 @@ MeasurementComplexItem::~MeasurementComplexItem() {}
void MeasurementComplexItem::reverseRoute() { _reverseRoute(); }
const AreaData *MeasurementComplexItem::areaData() const {
return this->_currentData;
return this->_pCurrentData;
}
AreaData *MeasurementComplexItem::areaData() { return this->_currentData; }
AreaData *MeasurementComplexItem::areaData() { return this->_pCurrentData; }
QVariantList MeasurementComplexItem::route() { return _route; }
......@@ -155,6 +160,24 @@ bool MeasurementComplexItem::load(const QJsonObject &complexObject,
return true;
}
double
MeasurementComplexItem::greatestDistanceTo(const QGeoCoordinate &other) const {
double d = -1 * std::numeric_limits<double>::infinity();
if (other.isValid()) {
if (this->_route.size() > 0) {
std::for_each(this->_route.cbegin(), this->_route.cend(),
[&d, &other](const QVariant &variant) {
auto vertex = variant.value<QGeoCoordinate>();
d = std::max(d, vertex.distanceTo(other));
});
}
} else {
qCDebug(MeasurementComplexItemLog)
<< "greatestDistanceTo(): invalid QGeoCoordinate: " << other;
}
return d;
}
bool MeasurementComplexItem::dirty() const { return _dirty; }
bool MeasurementComplexItem::isSimpleItem() const { return false; }
......@@ -202,6 +225,18 @@ double MeasurementComplexItem::maxAMSLAltitude() const {
return amslEntryAlt();
}
QString MeasurementComplexItem::commandDescription() const {
return QStringLiteral("Measurement");
}
QString MeasurementComplexItem::commandName() const {
return QStringLiteral("Measurement");
}
QString MeasurementComplexItem::abbreviation() const {
return QStringLiteral("M");
}
bool MeasurementComplexItem::specifiesCoordinate() const {
return _route.count() > 0;
}
......@@ -283,8 +318,12 @@ bool MeasurementComplexItem::_setGenerator(PtrGenerator newG) {
}
this->_pGenerator = newG;
connect(this->_pGenerator, &routing::GeneratorBase::generatorChanged, this,
&MeasurementComplexItem::_updateRoute);
if (this->_pGenerator != nullptr) {
connect(this->_pGenerator, &routing::GeneratorBase::generatorChanged,
this, &MeasurementComplexItem::_updateRoute);
}
emit generatorChanged();
if (!editing()) {
......@@ -321,14 +360,18 @@ bool MeasurementComplexItem::_calculating(MeasurementComplexItem::STATE state) {
return state == STATE::ROUTING;
}
bool MeasurementComplexItem::_editing(MeasurementComplexItem::STATE state) {
return state == STATE::EDITING;
}
bool MeasurementComplexItem::_ready(MeasurementComplexItem::STATE state) {
return state == STATE::IDLE;
}
void MeasurementComplexItem::_setAreaData(
MeasurementComplexItem::PtrAreaData data) {
if (_currentData != data) {
_currentData = data;
if (_pCurrentData != data) {
_pCurrentData = data;
emit areaDataChanged();
}
}
......@@ -340,10 +383,10 @@ bool MeasurementComplexItem::_updateRoute() {
this->_variantNames.clear();
emit variantNamesChanged();
if (this->_areaData->isValid()) {
if (this->_pAreaData->isValid()) {
// Prepare data.
auto origin = this->_areaData->origin();
auto origin = this->_pAreaData->origin();
origin.setAltitude(0);
if (!origin.isValid()) {
qCDebug(MeasurementComplexItemLog)
......@@ -353,7 +396,7 @@ bool MeasurementComplexItem::_updateRoute() {
// Convert safe area.
auto serviceArea =
getGeoArea<const SafeArea *>(*this->_areaData->areaList());
getGeoArea<const SafeArea *>(*this->_pAreaData->areaList());
auto geoSafeArea = serviceArea->coordinateList();
if (!(geoSafeArea.size() >= 3)) {
qCDebug(MeasurementComplexItemLog)
......@@ -378,7 +421,7 @@ bool MeasurementComplexItem::_updateRoute() {
snake::areaToEnu(origin, geoSafeArea, safeAreaENU);
// Create generator.
if (this->_pGenerator) {
if (this->_pGenerator != nullptr) {
routing::GeneratorBase::Generator g; // Transect generator.
if (this->_pGenerator->get(g)) {
// Start/Restart routing worker.
......@@ -491,6 +534,24 @@ void MeasurementComplexItem::setSequenceNumber(int sequenceNumber) {
QString MeasurementComplexItem::patternName() const { return name; }
double MeasurementComplexItem::complexDistance() const {
double d = 0;
if (this->_route.size() > 1) {
auto vertex = _route.first().value<QGeoCoordinate>();
std::for_each(this->_route.cbegin() + 1, this->_route.cend(),
[&vertex, &d](const QVariant &variant) {
auto otherVertex = variant.value<QGeoCoordinate>();
d += vertex.distanceTo(otherVertex);
vertex = otherVertex;
});
}
return d;
}
int MeasurementComplexItem::lastSequenceNumber() const {
return _sequenceNumber + std::max(0, this->_route.size() - 1);
}
bool MeasurementComplexItem::registerGenerator(const QString &name,
routing::GeneratorBase *g) {
if (name.isEmpty()) {
......@@ -602,20 +663,20 @@ int MeasurementComplexItem::generatorIndex() {
void MeasurementComplexItem::editingStart() {
if (!_editing(this->_state)) {
*_editorData = *_areaData;
_setAreaData(_editorData);
*_pEditorData = *_pAreaData;
_setAreaData(_pEditorData);
_setState(STATE::EDITING);
}
}
void MeasurementComplexItem::editingStop() {
if (_editing(this->_state)) {
if (_editorData->isValid()) {
*_areaData = *_editorData;
if (_pEditorData->isValid()) {
*_pAreaData = *_pEditorData;
}
_setAreaData(_areaData);
_setAreaData(_pAreaData);
_setState(STATE::IDLE);
if (_editorData->isValid() && *_editorData != *_areaData) {
if (_pEditorData->isValid() && *_pEditorData != *_pAreaData) {
_updateRoute();
}
}
......@@ -625,7 +686,7 @@ void MeasurementComplexItem::_storeRoutingData(
MeasurementComplexItem::PtrRoutingData pRoute) {
if (this->_state == STATE::ROUTING) {
// Store solutions.
auto ori = this->_areaData->origin();
auto ori = this->_pAreaData->origin();
ori.setAltitude(0);
const auto &transectsENU = pRoute->transects;
QVector<Variant> variantVector;
......@@ -742,4 +803,6 @@ bool MeasurementComplexItem::calculating() const {
bool MeasurementComplexItem::editing() const { return _editing(this->_state); }
bool MeasurementComplexItem::ready() const { return _ready(this->_state); }
bool MeasurementComplexItem::followTerrain() const { return _followTerrain; }
......@@ -45,8 +45,6 @@ public:
Q_PROPERTY(
routing::GeneratorBase *generator READ generator NOTIFY generatorChanged)
Q_PROPERTY(int generatorIndex READ generatorIndex NOTIFY generatorChanged)
Q_PROPERTY(bool editing READ editing NOTIFY editingChanged)
Q_PROPERTY(bool editing READ editing NOTIFY editingChanged)
Q_PROPERTY(AreaData *areaData READ areaData NOTIFY areaDataChanged)
Q_PROPERTY(QVariantList route READ route NOTIFY routeChanged)
......@@ -91,6 +89,9 @@ public:
virtual double amslExitAlt(void) const override final;
virtual double minAMSLAltitude(void) const override final;
virtual double maxAMSLAltitude(void) const override final;
virtual QString commandDescription(void) const override final;
virtual QString commandName(void) const override final;
virtual QString abbreviation(void) const override final;
// Generator
bool registerGenerator(const QString &name, routing::GeneratorBase *g);
......@@ -171,20 +172,20 @@ private:
PlanMasterController *_masterController;
int _sequenceNumber;
bool _followTerrain;
SettingsFact _altitude;
// State.
STATE _state;
// Facts
QMap<QString, FactMetaData *> _metaDataMap;
SettingsFact _altitude;
SettingsFact _variant;
QStringList _variantNames;
// Area data
PtrAreaData _areaData;
PtrAreaData _editorData;
PtrAreaData _currentData;
PtrAreaData _pAreaData;
PtrAreaData _pEditorData;
PtrAreaData _pCurrentData;
// Generators
QList<PtrGenerator> _generatorList;
......
......@@ -73,7 +73,7 @@ const char *MeasurementArea::MeasurementAreaName = "Measurement Area";
MeasurementArea::MeasurementArea(QObject *parent)
: GeoArea(parent),
_metaDataMap(FactMetaData::createMapFromJsonFile(
QStringLiteral(":/json/WimaMeasurementArea.SettingsGroup.json"),
QStringLiteral(":/json/MeasurementArea.SettingsGroup.json"),
this /* QObject parent */)),
_tileHeight(SettingsFact(settingsGroup, _metaDataMap[tileHeightName],
this /* QObject parent */)),
......
{
"version": 1,
"fileType": "FactMetaData",
"QGC.MetaData.Facts":
[
{
"name": "TileHeight",
......@@ -43,3 +47,4 @@
"defaultValue": 5
}
]
}
[
{
"name": "BorderPolygonOffset",
"shortDescription": "The distance between the measurement area and it's surrounding polygon",
"type": "double",
"units": "m",
"min": 0,
"decimalPlaces": 1,
"defaultValue": 5
},
{
"name": "ShowBorderPolygon",
"shortDescription": "Border polygon will be displayed if checked.",
"type": "bool",
"defaultValue": true
}
]
......@@ -7,11 +7,13 @@ import QGroundControl.FactControls 1.0
import QGroundControl.ScreenTools 1.0
GridLayout {
id: grid
property var generator // CircularGenerator
property var availableWidth
property real _margin: ScreenTools.defaultFontPixelWidth / 2
width: availableWidth
columnSpacing: _margin
rowSpacing: _margin
columns: 2
......
......@@ -15,26 +15,27 @@ import QtPositioning 5.3
import QGroundControl.ScreenTools 1.0
import QGroundControl.Palette 1.0
import QGroundControl.Controls 1.0
import QGroundControl 1.0
/// Wima map visual
Item {
id: _root
property var map ///< Map control to place item in
property var qgcView ///< QGCView to use for popping dialogs
property var geoArea ///< GeoArea derived class
signal clicked(int sequenceNumber)
property var _visualItem
Component.onCompleted: {
if (object.mapVisualQML) {
var component = Qt.createComponent(object.mapVisualQML)
if (geoArea.mapVisualQML) {
var component = Qt.createComponent(geoArea.mapVisualQML)
if (component.status === Component.Error) {
console.log("Error loading Qml: ", object.mapVisualQML, component.errorString())
console.log("Error loading Qml: ", geoArea.mapVisualQML, component.errorString())
}
_visualItem = component.createObject(map, { "map": _root.map, "qgcView": _root.qgcView })
_visualItem = component.createObject(map, { "map": _root.map, "qgcView": _root.qgcView, "geoArea": _root.geoArea})
_visualItem.clicked.connect(_root.clicked)
}
}
......
......@@ -8,10 +8,11 @@ import QGroundControl.ScreenTools 1.0
GridLayout {
property var generator ///< LinearGenerator
property var generator // CircularGenerator
property var availableWidth
property real _margin: ScreenTools.defaultFontPixelWidth / 2
width: availableWidth
columnSpacing: _margin
rowSpacing: _margin
columns: 2
......
......@@ -18,93 +18,29 @@ import QGroundControl.Palette 1.0
import QGroundControl.Controls 1.0
import QGroundControl.FlightMap 1.0
/// Wima Global Measurement Area visuals
Item {
id: _root
property var map ///< Map control to place item in
property var qgcView ///< QGCView to use for popping dialogs
property var areaItem ///< GeoArea derived class
property var areaItem: object
property var _polygon: areaItem
property var opacity: 0.5
signal clicked(int sequenceNumber)
/// Add an initial 4 sided polygon if there is none
function _addInitialPolygon() {
// Initial polygon is inset to take 2/3rds space
var rect = Qt.rect(map.centerViewport.x, map.centerViewport.y, map.centerViewport.width, map.centerViewport.height)
rect.x += (rect.width * 0.25) / 2
rect.y += (rect.height * 0.25) / 2
rect.width *= 0.75
rect.height *= 0.75
var centerCoord = map.toCoordinate(Qt.point(rect.x + (rect.width / 2), rect.y + (rect.height / 2)), false /* clipToViewPort */)
var topLeftCoord = map.toCoordinate(Qt.point(rect.x, rect.y), false /* clipToViewPort */)
var topRightCoord = map.toCoordinate(Qt.point(rect.x + rect.width, rect.y), false /* clipToViewPort */)
var bottomLeftCoord = map.toCoordinate(Qt.point(rect.x, rect.y + rect.height), false /* clipToViewPort */)
var bottomRightCoord = map.toCoordinate(Qt.point(rect.x + rect.width, rect.y + rect.height), false /* clipToViewPort */)
// Adjust polygon to max size
var maxSize = 100
var halfWidthMeters = Math.min(topLeftCoord.distanceTo(topRightCoord), maxSize) / 2
var halfHeightMeters = Math.min(topLeftCoord.distanceTo(bottomLeftCoord), maxSize) / 2
topLeftCoord = centerCoord.atDistanceAndAzimuth(halfWidthMeters, -90).atDistanceAndAzimuth(halfHeightMeters, 0)
topRightCoord = centerCoord.atDistanceAndAzimuth(halfWidthMeters, 90).atDistanceAndAzimuth(halfHeightMeters, 0)
bottomLeftCoord = centerCoord.atDistanceAndAzimuth(halfWidthMeters, -90).atDistanceAndAzimuth(halfHeightMeters, 180)
bottomRightCoord = centerCoord.atDistanceAndAzimuth(halfWidthMeters, 90).atDistanceAndAzimuth(halfHeightMeters, 180)
if (areaItem.showBorderPolygon.rawValue === true) {
if (areaItem.borderPolygon.count < 3) {
areaItem.borderPolygon.appendVertex(topLeftCoord)
areaItem.borderPolygon.appendVertex(topRightCoord)
areaItem.borderPolygon.appendVertex(bottomRightCoord)
areaItem.borderPolygon.appendVertex(bottomLeftCoord)
}
} else {
if (_polygon.count < 3) {
_polygon.appendVertex(topLeftCoord)
_polygon.appendVertex(topRightCoord)
_polygon.appendVertex(bottomRightCoord)
_polygon.appendVertex(bottomLeftCoord)
}
}
}
Component.onCompleted: {
_addInitialPolygon()
//_addInitialPolyline()
}
Component.onDestruction: {
}
// Polygon
WimaMapPolygonVisuals {
qgcView: _root.qgcView
// Area polygon
QGCMapPolygonVisuals {
id: mapPolygonVisuals
mapControl: map
mapPolygon: _polygon
mapPolygon: areaItem
interactive: true
borderWidth: 1
borderColor: "black"
interiorColor: "green"
interiorOpacity: 0.25
}
// Border Polygon
WimaMapPolygonVisuals {
qgcView: _root.qgcView
mapControl: map
mapPolygon: areaItem.borderPolygon
borderWidth: 1
borderColor: areaItem.borderPolygon.interactive ? "white" : "transparent"
interiorColor: "transparent"
interiorOpacity: 1
altColor: QGroundControl.globalPalette.surveyPolygonTerrainCollision
interiorOpacity: _root.opacity
}
// Add Snake tiles to the map
......@@ -131,6 +67,7 @@ Item {
}
}
}
function getColor(progress) {
if (progress === 0)
return "transparent"
......
import QtQuick 2.3
import QtQuick.Controls 1.2
import QtQuick.Controls.Styles 1.4
import QtQuick.Dialogs 1.2
import QtQuick.Extras 1.4
import QtQuick.Layouts 1.2
import QGroundControl 1.0
import QGroundControl.ScreenTools 1.0
import QGroundControl.Vehicle 1.0
import QGroundControl.Controls 1.0
import QGroundControl.FactSystem 1.0
import QGroundControl.FactControls 1.0
import QGroundControl.Palette 1.0
import QGroundControl.FlightMap 1.0
Rectangle {
id: _root
height: visible ? (editorColumn.height + (_margin * 2)) : 0
width: availableWidth
color: qgcPal.windowShadeDark
radius: _radius
// The following properties must be available up the hierarchy chain
//property real availableWidth ///< Width for control
//property var missionItem ///< Mission Item for editor
property real _margin: ScreenTools.defaultFontPixelWidth / 2
property real _fieldWidth: ScreenTools.defaultFontPixelWidth * 10.5
property var _vehicle: QGroundControl.multiVehicleManager.activeVehicle ?
QGroundControl.multiVehicleManager.activeVehicle :
QGroundControl.multiVehicleManager.offlineEditingVehicle
property var _missionItem: missionItem
property var _generator: missionItem.generator
property var _generatorEditor: undefined
QGCPalette { id: qgcPal; colorGroupEnabled: true }
Component.onCompleted: {
_addGeneratorEditor()
}
Component.onDestruction: {
_destroyGeneratorEditor()
}
on_GeneratorChanged: {
_destroyGeneratorEditor()
_addGeneratorEditor()
}
Column { // main column
id: editorColumn
anchors.margins: _margin
anchors.top: parent.top
anchors.left: parent.left
anchors.right: parent.right
// ColumnLayout {
// id: wizardColumn
// anchors.left: parent.left
// anchors.right: parent.right
// spacing: _margin
// visible: !_missionItem.surveyAreaPolygon.isValid || _missionItem.wizardMode
// ColumnLayout {
// Layout.fillWidth: true
// spacing: _margin
// visible: !_polygonDone
// QGCLabel {
// Layout.fillWidth: true
// wrapMode: Text.WordWrap
// horizontalAlignment: Text.AlignHCenter
// text: qsTr("Use the Polygon Tools to create the polygon which outlines your survey area.")
// }
// }
// }
Column {
anchors.left: parent.left
anchors.right: parent.right
spacing: _margin
//visible: !wizardColumn.visible
// QGCTabBar {
// id: tabBar
// anchors.left: parent.left
// anchors.right: parent.right
// Component.onCompleted: currentIndex = QGroundControl.settingsManager.planViewSettings.displayPresetsTabFirst.rawValue ? 2 : 0
// QGCTabButton { icon.source: "/qmlimages/PatternGrid.png"; icon.height: ScreenTools.defaultFontPixelHeight }
// QGCTabButton { icon.source: "/qmlimages/PatternCamera.png"; icon.height: ScreenTools.defaultFontPixelHeight }
// QGCTabButton { icon.source: "/qmlimages/PatternTerrain.png"; icon.height: ScreenTools.defaultFontPixelHeight }
// QGCTabButton { icon.source: "/qmlimages/PatternPresets.png"; icon.height: ScreenTools.defaultFontPixelHeight }
// }
// Grid tab
Column {
anchors.left: parent.left
anchors.right: parent.right
spacing: _margin
// visible: tabBar.currentIndex === 0
SectionHeader {
id: generalHeader
anchors.left: parent.left
anchors.right: parent.right
text: qsTr("General")
}
GridLayout {
id: generalGrid
anchors.left: parent.left
anchors.right: parent.right
columnSpacing: _margin
rowSpacing: _margin
columns: 2
visible: generalHeader.checked
QGCLabel { text: qsTr("Altitude!!!") }
QGCLabel { text: qsTr("Relative Altitude!!!") }
QGCLabel {
text: qsTr("Variant")
Layout.columnSpan: 2
visible: variantRepeater.len > 0
}
GridLayout{
Layout.columnSpan: 2
columnSpacing: _margin
rowSpacing: _margin
columns: 6
Repeater{
id: variantRepeater
property var fact: missionItem.variant
property int variant: fact.value
property var names: missionItem.variantNames
property int len: missionItem.variantNames.length
model: len
delegate: QGCRadioButton {
checked: index === variantRepeater.variant
text: variantRepeater.names[index] ? variantRepeater.names[index]: ""
onCheckedChanged: {
if (checked){
missionItem.variant.value = index
}
checked = Qt.binding(function(){ return index === variantRepeater.variant})
}
}
} // variant repeater
} // variant grid
} // general grid
// Generator Editor
SectionHeader {
id: generatorHeader
anchors.left: parent.left
anchors.right: parent.right
text: qsTr("Generator")
}
GridLayout{
anchors.left: parent.left
anchors.right: parent.right
columnSpacing: _margin
rowSpacing: _margin
columns: 2
visible: generatorHeader.checked
QGCComboBox {
property var names: missionItem.generatorNameList
property int length: names.length
anchors.margins: ScreenTools.defaultFontPixelWidth
currentIndex: missionItem.generatorIndex
Layout.columnSpan: 2
model: missionItem.generatorNameList
onActivated: {
missionItem.switchToGenerator(index)
}
}
}
ColumnLayout{
id:generatorEditorParent
anchors.left: parent.left
anchors.right: parent.right
visible: generatorHeader.checked
}
// bussy indicator
ColumnLayout{
anchors.left: parent.left
anchors.right: parent.right
spacing: _margin
BusyIndicator{
id: indicator
anchors.horizontalCenter: parent.horizontalCenter
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
} // Grid Column
} // Main editing column
} // Top level Column
KMLOrSHPFileDialog {
id: kmlOrSHPLoadDialog
title: qsTr("Select Polygon File")
selectExisting: true
onAcceptedForLoad: {
_missionItem.surveyAreaPolygon.loadKMLOrSHPFile(file)
_missionItem.resetState = false
//editorMap.mapFitFunctions.fitMapViewportTo_missionItems()
close()
}
}
function _addGeneratorEditor(){
if (_generator.editorQml && !_generatorEditor) {
var component = Qt.createComponent(_generator.editorQml)
if (component.status === Component.Error) {
console.log("Error loading Qml: ",
_generator.editorQml, component.errorString())
} else {
_generatorEditor =
component.createObject(
generatorEditorParent, {
"generator": _root._generator,
"availableWidth": generatorEditorParent.width,
})
}
}
}
function _destroyGeneratorEditor(){
if (_generatorEditor){
_generatorEditor.destroy()
_generatorEditor = undefined
}
}
} // Rectangle
......@@ -51,6 +51,8 @@ Item {
_addExitCoordinate()
_addTransectsComponent()
_addGeneratorVisuals()
var bbox = boundingBox()
_areaData.initialize(bbox[0], bbox[1])
}
Component.onDestruction: {
......@@ -70,7 +72,7 @@ Item {
id: visualTransectsComponent
MapPolyline {
property var transects: _missionItem.visualTransectPoints
property var transects: _missionItem.route
line.color: "white"
line.width: 2
path: transects.length > 0 ? transects : []
......@@ -120,13 +122,10 @@ Item {
Repeater {
model: _areaData.areaList
delegate: WimaMapVisual {
delegate: GeoAreaVisualLoader {
map: _root.map
qgcView: _root.qgcView
}
onItemAdded: {
//console.log("Item added")
geoArea: _areaData.areaList[index]
}
}
......@@ -205,4 +204,32 @@ Item {
_transectsComponent = undefined
}
}
function boundingBox() {
// Initial polygon is inset to take 2/3rds space
var rect = Qt.rect(map.centerViewport.x,
map.centerViewport.y,
map.centerViewport.width,
map.centerViewport.height)
rect.x += (rect.width * 0.25) / 2
rect.y += (rect.height * 0.25) / 2
rect.width *= 0.75
rect.height *= 0.75
var centerCoord = map.toCoordinate(Qt.point(rect.x + (rect.width / 2),
rect.y + (rect.height / 2)),
false /* clipToViewPort */)
var topRightCoord = map.toCoordinate(Qt.point(rect.x + rect.width, rect.y), false /* clipToViewPort */)
var bottomLeftCoord = map.toCoordinate(Qt.point(rect.x, rect.y + rect.height), false /* clipToViewPort */)
var topLeftCoord = map.toCoordinate(Qt.point(rect.x, rect.y), false /* clipToViewPort */)
var bottomRightCoord = map.toCoordinate(Qt.point(rect.x + rect.width, rect.y + rect.height), false /* clipToViewPort */)
// Initial polygon has max width and height of 3000 meters
var halfWidthMeters = Math.min(topLeftCoord.distanceTo(topRightCoord), 3000) / 2
var halfHeightMeters = Math.min(topLeftCoord.distanceTo(bottomLeftCoord), 3000) / 2
topRightCoord = centerCoord.atDistanceAndAzimuth(halfWidthMeters, 90).atDistanceAndAzimuth(halfHeightMeters, 0)
bottomLeftCoord = centerCoord.atDistanceAndAzimuth(halfWidthMeters, -90).atDistanceAndAzimuth(halfHeightMeters, 180)
return [ bottomLeftCoord, topRightCoord ]
}
}
......@@ -23,12 +23,14 @@ Item {
property var map ///< Map control to place item in
property var qgcView ///< QGCView to use for popping dialogs
property var areaItem ///< GeoArea derived class.
property var areaItem: object
property var _polygon: areaItem
property var _depot: undefined
property bool _showDepot: areaItem.interactive || areaItem.borderPolygon.interactive
signal clicked(int sequenceNumber)
on_ShowDepotChanged: {
if (_showDepot){
_addDepot()
......@@ -37,70 +39,7 @@ Item {
}
}
signal clicked(int sequenceNumber)
function _addDepot() {
if (!_depot){
_depot = depotPointComponent.createObject(_root)
map.addMapItem(_depot)
}
}
function _destroyDepot() {
if (_depot){
map.removeMapItem(_depot)
_depot.destroy()
_depot = undefined
}
}
/// Add an initial 4 sided polygon if there is none
function _addInitialPolygon() {
// Initial polygon is inset to take 2/3rds space
var rect = Qt.rect(map.centerViewport.x, map.centerViewport.y, map.centerViewport.width, map.centerViewport.height)
rect.x += (rect.width * 0.25) / 2
rect.y += (rect.height * 0.25) / 2
rect.width *= 0.75
rect.height *= 0.75
var centerCoord = map.toCoordinate(Qt.point(rect.x + (rect.width / 2), rect.y + (rect.height / 2)), false /* clipToViewPort */)
var topLeftCoord = map.toCoordinate(Qt.point(rect.x, rect.y), false /* clipToViewPort */)
var topRightCoord = map.toCoordinate(Qt.point(rect.x + rect.width, rect.y), false /* clipToViewPort */)
var bottomLeftCoord = map.toCoordinate(Qt.point(rect.x, rect.y + rect.height), false /* clipToViewPort */)
var bottomRightCoord = map.toCoordinate(Qt.point(rect.x + rect.width, rect.y + rect.height), false /* clipToViewPort */)
// Adjust polygon to max size
var maxSize = 100
var halfWidthMeters = Math.min(topLeftCoord.distanceTo(topRightCoord), maxSize) / 2
var halfHeightMeters = Math.min(topLeftCoord.distanceTo(bottomLeftCoord), maxSize) / 2
topLeftCoord = centerCoord.atDistanceAndAzimuth(halfWidthMeters, -90).atDistanceAndAzimuth(halfHeightMeters, 0)
topRightCoord = centerCoord.atDistanceAndAzimuth(halfWidthMeters, 90).atDistanceAndAzimuth(halfHeightMeters, 0)
bottomLeftCoord = centerCoord.atDistanceAndAzimuth(halfWidthMeters, -90).atDistanceAndAzimuth(halfHeightMeters, 180)
bottomRightCoord = centerCoord.atDistanceAndAzimuth(halfWidthMeters, 90).atDistanceAndAzimuth(halfHeightMeters, 180)
if (areaItem.showBorderPolygon.rawValue === true) {
if (areaItem.borderPolygon.count < 3) {
areaItem.borderPolygon.appendVertex(topLeftCoord)
areaItem.borderPolygon.appendVertex(topRightCoord)
areaItem.borderPolygon.appendVertex(bottomRightCoord)
areaItem.borderPolygon.appendVertex(bottomLeftCoord)
}
} else {
if (_polygon.count < 3) {
_polygon.appendVertex(topLeftCoord)
_polygon.appendVertex(topRightCoord)
_polygon.appendVertex(bottomRightCoord)
_polygon.appendVertex(bottomLeftCoord)
}
}
}
Component.onCompleted: {
_addInitialPolygon()
if (_showDepot){
_addDepot()
}
......@@ -110,24 +49,17 @@ Item {
_destroyDepot()
}
WimaMapPolygonVisuals {
qgcView: _root.qgcView
// Area polygon
QGCMapPolygonVisuals {
id: mapPolygonVisuals
mapControl: map
mapPolygon: _polygon
mapPolygon: areaItem
interactive: true
borderWidth: 1
borderColor: "black"
interiorColor: "yellow"
interiorOpacity: 0.25
}
WimaMapPolygonVisuals {
qgcView: _root.qgcView
mapControl: map
mapPolygon: areaItem.borderPolygon
borderWidth: 1
borderColor: areaItem.borderPolygon.interactive ? "white" : "transparent"
interiorColor: "transparent"
interiorOpacity: 1
interiorColor: "blue"
altColor: QGroundControl.globalPalette.surveyPolygonTerrainCollision
interiorOpacity: _root.opacity
}
// Depot Point.
......@@ -164,4 +96,18 @@ Item {
}
}
function _addDepot() {
if (!_depot){
_depot = depotPointComponent.createObject(_root)
map.addMapItem(_depot)
}
}
function _destroyDepot() {
if (_depot){
map.removeMapItem(_depot)
_depot.destroy()
_depot = undefined
}
}
}
......@@ -15,7 +15,6 @@ import QtPositioning 5.3
import QGroundControl.ScreenTools 1.0
import QGroundControl.Palette 1.0
import QGroundControl.Controls 1.0
import Wima 1.0
/// Mission item map visual
Item {
......
......@@ -26,7 +26,9 @@ Rectangle {
property real _margin: ScreenTools.defaultFontPixelWidth / 2
property real _fieldWidth: ScreenTools.defaultFontPixelWidth * 10.5
property var _vehicle: QGroundControl.multiVehicleManager.activeVehicle ? QGroundControl.multiVehicleManager.activeVehicle : QGroundControl.multiVehicleManager.offlineEditingVehicle
property var _vehicle: QGroundControl.multiVehicleManager.activeVehicle ?
QGroundControl.multiVehicleManager.activeVehicle :
QGroundControl.multiVehicleManager.offlineEditingVehicle
property real _cameraMinTriggerInterval: _missionItem.cameraCalc.minTriggerInterval.rawValue
property bool _polygonDone: false
property string _doneAdjusting: qsTr("Done")
......
......@@ -110,3 +110,6 @@ VehicleRotationCal 1.0 VehicleRotationCal.qml
VehicleSummaryRow 1.0 VehicleSummaryRow.qml
QGCHoverButton 1.0 QGCHoverButton.qml
MAVLinkChart 1.0 MAVLinkChart.qml
MeasurementItemMapVisual 1.0 MeasurementItemMapVisual.qml
CircularGeneratorMapVisual 1.0 CircularGeneratorMapVisual.qml
GeoAreaVisualLoader 1.0 GeoAreaVisualLoader.qml
import QtQuick 2.3
import QtQuick.Controls 1.2
import QtQuick.Controls.Styles 1.4
import QtQuick.Dialogs 1.2
import QtQuick.Extras 1.4
import QtQuick.Layouts 1.2
import QGroundControl 1.0
import QGroundControl.ScreenTools 1.0
import QGroundControl.Vehicle 1.0
import QGroundControl.Controls 1.0
import QGroundControl.FactSystem 1.0
import QGroundControl.FactControls 1.0
import QGroundControl.Palette 1.0
import QGroundControl.FlightMap 1.0
Rectangle {
id: _root
height: visible ? (editorColumn.height + (_margin * 2)) : 0
width: availableWidth
color: qgcPal.windowShadeDark
radius: _radius
// The following properties must be available up the hierarchy chain
//property real availableWidth ///< Width for control
//property var missionItem ///< Mission Item for editor
property real _margin: ScreenTools.defaultFontPixelWidth / 2
property var _generator: missionItem.generator
property var _generatorEditor: undefined
QGCPalette { id: qgcPal; colorGroupEnabled: true }
Component.onCompleted: {
_addGeneratorEditor()
}
Component.onDestruction: {
_destroyGeneratorEditor()
}
on_GeneratorChanged: {
_destroyGeneratorEditor()
_addGeneratorEditor()
}
Column {
id: editorColumn
anchors.margins: _margin
anchors.top: parent.top
anchors.left: parent.left
anchors.right: parent.right
spacing: _margin
SectionHeader {
id: generalHeader
text: qsTr("General")
}
GridLayout {
id: generalGrid
anchors.left: parent.left
anchors.right: parent.right
columnSpacing: _margin
rowSpacing: _margin
columns: 2
visible: generalHeader.checked
QGCLabel { text: qsTr("Altitude") }
FactTextField {
fact: missionItem.cameraCalc.distanceToSurface
Layout.fillWidth: true
}
QGCCheckBox {
id: relAlt
text: qsTr("Relative altitude")
checked: missionItem.cameraCalc.distanceToSurfaceRelative
enabled: missionItem.cameraCalc.isManualCamera && !missionItem.followTerrain
visible: QGroundControl.corePlugin.options.showMissionAbsoluteAltitude || (!missionItem.cameraCalc.distanceToSurfaceRelative && !missionItem.followTerrain)
onClicked: missionItem.cameraCalc.distanceToSurfaceRelative = checked
Layout.fillWidth: true
Layout.columnSpan: 2
Connections {
target: missionItem.cameraCalc
onDistanceToSurfaceRelativeChanged: relAlt.checked = missionItem.cameraCalc.distanceToSurfaceRelative
}
}
QGCLabel {
text: qsTr("Generator Type")
Layout.columnSpan: 2
}
QGCComboBox {
property var names: missionItem.generatorNameList
property int length: names.length
anchors.margins: ScreenTools.defaultFontPixelWidth
currentIndex: missionItem.generatorIndex
Layout.columnSpan: 2
model: missionItem.generatorNameList
onActivated: {
missionItem.switchToGenerator(index)
}
}
QGCLabel {
text: qsTr("Variant")
Layout.columnSpan: 2
}
GridLayout{
Layout.columnSpan: 2
columnSpacing: _margin
rowSpacing: _margin
columns: 6
Repeater{
id: variantRepeater
property var fact: missionItem.variant
property int variant: fact.value
property var names: missionItem.variantNames
property int len: missionItem.variantNames.length
model: len
delegate: QGCRadioButton {
checked: index === variantRepeater.variant
text: variantRepeater.names[index] ? variantRepeater.names[index]: ""
onCheckedChanged: {
if (checked){
missionItem.variant.value = index
}
checked = Qt.binding(function(){ return index === variantRepeater.variant})
}
}
}
}
}
// Generator Editor
SectionHeader {
id: transectsHeader
text: qsTr("Generator")
}
Column{
id:generatorEditorParent
visible: transectsHeader.checked
}
Column{
anchors.left: parent.left
anchors.right: parent.right
spacing: _margin
BusyIndicator{
id: indicator
anchors.horizontalCenter: parent.horizontalCenter
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
}
}
}
} // Column
function _addGeneratorEditor(){
if (_generator.editorQml && !_generatorEditor) {
var component = Qt.createComponent(_generator.editorQml)
if (component.status === Component.Error) {
console.log("Error loading Qml: ",
_generator.editorQml, component.errorString())
} else {
_generatorEditor =
component.createObject(
generatorEditorParent, {
"generator": _root._generator,
})
}
}
}
function _destroyGeneratorEditor(){
if (_generatorEditor){
_generatorEditor.destroy()
_generatorEditor = undefined
}
}
} // Rectangle
WimaMapVisual 1.0 WimaMapVisual.qml
WimaMeasurementAreaMapVisual 1.0 WimaMeasurementAreaMapVisual.qml
WimaJoinedAreaMapVisual 1.0 WimaJoinedAreaMapVisual.qml
WimaMeasurementAreaEditor 1.0 WimaMeasurementAreaEditor.qml
WimaServiceAreaMapVisual 1.0 WimaServiceAreaMapVisual.qml
WimaAreaMapVisual 1.0 WimaAreaMapVisual.qml
WimaServiceAreaEditor 1.0 WimaServiceAreaEditor.qml
WimaCorridorMapVisual 1.0 WimaCorridorMapVisual.qml
WimaItemEditor 1.0 WimaItemEditor.qml
WimaMapPolygonVisuals 1.0 WimaMapPolygonVisuals.qml
WimaMapPolylineVisuals 1.0 WimaMapPolylineVisuals.qml
CircularSurveyMapVisual 1.0 CircularSurveyMapVisual.qml
DragCoordinate 1.0 DragCoordinate.qml
CoordinateIndicator 1.0 CoordinateIndicator.qml
CoordinateIndicatorDrag 1.0 CoordinateIndicatorDrag.qml
ProgressIndicator 1.0 ProgressIndicator.qml
WimaToolBar 1.0 WimaToolBar.qml
import QtQuick 2.3
import QtQuick.Controls 1.2
import QtQuick.Controls.Styles 1.4
import QtQuick.Dialogs 1.2
import QtQuick.Extras 1.4
import QtQuick.Layouts 1.2
import QGroundControl 1.0
import QGroundControl.ScreenTools 1.0
import QGroundControl.Vehicle 1.0
import QGroundControl.Controls 1.0
import QGroundControl.FactControls 1.0
import QGroundControl.Palette 1.0
import QGroundControl.FlightMap 1.0
// Editor for Operating Area items
Rectangle {
id: _root
height: visible ? (editorColumn.height + (_margin * 2)) : 0
width: availableWidth
color: qgcPal.windowShadeDark
radius: _radius
// The following properties must be available up the hierarchy chain
//property real availableWidth ///< Width for control
//property var areaItem ///< Mission Item for editor
property real _margin: ScreenTools.defaultFontPixelWidth / 2
property real _fieldWidth: ScreenTools.defaultFontPixelWidth * 10.5
//property var polyline: areaItem.polyline
//property bool polylineInteractive: polyline.interactive
property bool polygonInteractive: areaItem.interactive
property var polygon: areaItem
property bool initNecesarry: true
/*onPolylineInteractiveChanged: {
polyline.interactive = polylineInteractive;
}*/
onPolygonInteractiveChanged: {
polygon.interactive = polygonInteractive;
}
/*function editPolyline(){
if (polylineInteractive){
//polyline.interactive = false;
polylineInteractive = false;
//polygonInteractive = true;
}else{
//polyline.interactive = true;
polylineInteractive = true;
//polygonInteractive = false;
}
}*/
QGCPalette { id: qgcPal; colorGroupEnabled: true }
Column {
id: editorColumn
anchors.margins: _margin
anchors.top: parent.top
anchors.left: parent.left
anchors.right: parent.right
spacing: _margin
SectionHeader {
id: scanHeader
text: qsTr("Settings")
}
Column {
anchors.left: parent.left
anchors.right: parent.right
spacing: _margin
visible: scanHeader.checked
GridLayout {
anchors.left: parent.left
anchors.right: parent.right
columnSpacing: _margin
rowSpacing: _margin
columns: 2
QGCLabel { text: qsTr("Offset") }
FactTextField {
fact: areaItem.borderPolygonOffset
Layout.fillWidth: true
}
/*QGCLabel {
text: qsTr("Bottom Layer Altitude")
}
FactTextField {
fact: areaItem.bottomLayerAltitude
Layout.fillWidth: true
}
QGCLabel { text: qsTr("Number of Layers") }
FactTextField {
fact: areaItem.numberOfLayers
Layout.fillWidth: true
}
QGCLabel { text: qsTr("Layer Distance") }
FactTextField {
fact: areaItem.layerDistance
Layout.fillWidth: true
}*/
}
Item {
height: ScreenTools.defaultFontPixelHeight / 2
width: 1
}
}
FactCheckBox {
text: qsTr("Border Polygon")
fact: areaItem.showBorderPolygon
//enabled: !missionItem.followTerrain
}
// Column - Scan
/*SectionHeader {
id: polylineHeader
text: qsTr("Gateway Poly Line")
}
QGCButton {
id: polylineEditor
anchors.topMargin: _margin / 2
anchors.leftMargin: ScreenTools.defaultFontPixelWidth * 2
anchors.rightMargin: ScreenTools.defaultFontPixelWidth
text: polylineInteractive ? "Done" : "Edit"
onClicked: editPolyline()
}
QGCButton {
id: swapEndpoints
anchors.topMargin: _margin / 2
anchors.leftMargin: ScreenTools.defaultFontPixelWidth * 2
anchors.rightMargin: ScreenTools.defaultFontPixelWidth
text: "Swap End-Points"
onClicked: polyline.swapEndPoints()
}*/
SectionHeader {
id: statsHeader
text: qsTr("Statistics")
}
Grid {
columns: 2
columnSpacing: ScreenTools.defaultFontPixelWidth
visible: statsHeader.checked
/*QGCLabel { text: qsTr("Layers") }
QGCLabel { text: areaItem.layers.valueString }*/
QGCLabel { text: qsTr("Area") }
QGCLabel { text: QGroundControl.squareMetersToAppSettingsAreaUnits(areaItem.area).toFixed(2) + " " + QGroundControl.appSettingsAreaUnitsString }
}
} // Column
} // Rectangle
import QtQuick 2.3
import QtQuick.Controls 1.2
import QtQuick.Layouts 1.2
import QtQuick.Dialogs 1.2
import QGroundControl 1.0
import QGroundControl.ScreenTools 1.0
import QGroundControl.Controls 1.0
import QGroundControl.FactControls 1.0
import QGroundControl.Palette 1.0
// Toolbar for Wima View
Rectangle {
id: _root
height: ScreenTools.toolbarHeight
anchors.left: parent.left
anchors.right: parent.right
anchors.top: parent.top
z: toolBar.z + 1
color: qgcPal.globalTheme === QGCPalette.Light ? Qt.rgba(1,1,1,0.8) : Qt.rgba(0,0,0,0.75)
visible: false
anchors.bottomMargin: 1
signal showFlyView
property var planMasterController
property var wimaPlaner
property var currentMissionItem ///< Mission item to display status for
property var missionItems: _controllerValid ? planMasterController.missionController.visualItems : undefined
property real missionDistance: _controllerValid ? planMasterController.missionController.missionDistance : NaN
property real missionTime: _controllerValid ? planMasterController.missionController.missionTime : NaN
property real missionMaxTelemetry: _controllerValid ? planMasterController.missionController.missionMaxTelemetry : NaN
property bool missionDirty: _controllerValid ? planMasterController.missionController.dirty : false
property bool _controllerValid: planMasterController !== undefined
property bool _controllerOffline: _controllerValid ? planMasterController.offline : true
property var _controllerDirty: _controllerValid ? planMasterController.dirty : false
property var _controllerSyncInProgress: _controllerValid ? planMasterController.syncInProgress : false
property bool _statusValid: currentMissionItem !== undefined
property bool _missionValid: missionItems !== undefined
property real _dataFontSize: ScreenTools.defaultFontPointSize
property real _largeValueWidth: ScreenTools.defaultFontPixelWidth * 8
property real _mediumValueWidth: ScreenTools.defaultFontPixelWidth * 4
property real _smallValueWidth: ScreenTools.defaultFontPixelWidth * 3
property real _labelToValueSpacing: ScreenTools.defaultFontPixelWidth
property real _rowSpacing: ScreenTools.isMobile ? 1 : 0
property real _distance: _statusValid && currentMissionItem ? currentMissionItem.distance : NaN
property real _altDifference: _statusValid && currentMissionItem ? currentMissionItem.altDifference : NaN
property real _gradient: _statusValid && currentMissionItem && currentMissionItem.distance > 0 ? Math.atan(currentMissionItem.altDifference / currentMissionItem.distance) : NaN
property real _gradientPercent: isNaN(_gradient) ? NaN : _gradient * 100
property real _azimuth: _statusValid && currentMissionItem ? currentMissionItem.azimuth : NaN
property real _heading: _statusValid && currentMissionItem ? currentMissionItem.missionVehicleYaw : NaN
property real _missionDistance: _missionValid ? missionDistance : NaN
property real _missionMaxTelemetry: _missionValid ? missionMaxTelemetry : NaN
property real _missionTime: _missionValid ? missionTime : NaN
property int _batteryChangePoint: _controllerValid ? planMasterController.missionController.batteryChangePoint : -1
property int _batteriesRequired: _controllerValid ? planMasterController.missionController.batteriesRequired : -1
property bool _batteryInfoAvailable: _batteryChangePoint >= 0 || _batteriesRequired >= 0
property real _controllerProgressPct: _controllerValid ? planMasterController.missionController.progressPct : 0
property bool _syncInProgress: _controllerValid ? planMasterController.missionController.syncInProgress : false
property string _distanceText: isNaN(_distance) ? "-.-" : QGroundControl.metersToAppSettingsDistanceUnits(_distance).toFixed(1) + " " + QGroundControl.appSettingsDistanceUnitsString
property string _altDifferenceText: isNaN(_altDifference) ? "-.-" : QGroundControl.metersToAppSettingsDistanceUnits(_altDifference).toFixed(1) + " " + QGroundControl.appSettingsDistanceUnitsString
property string _gradientText: isNaN(_gradient) ? "-.-" : _gradientPercent.toFixed(0) + " %"
property string _azimuthText: isNaN(_azimuth) ? "-.-" : Math.round(_azimuth) % 360
property string _headingText: isNaN(_azimuth) ? "-.-" : Math.round(_heading) % 360
property string _missionDistanceText: isNaN(_missionDistance) ? "-.-" : QGroundControl.metersToAppSettingsDistanceUnits(_missionDistance).toFixed(0) + " " + QGroundControl.appSettingsDistanceUnitsString
property string _missionMaxTelemetryText: isNaN(_missionMaxTelemetry) ? "-.-" : QGroundControl.metersToAppSettingsDistanceUnits(_missionMaxTelemetry).toFixed(0) + " " + QGroundControl.appSettingsDistanceUnitsString
property string _batteryChangePointText: _batteryChangePoint < 0 ? "N/A" : _batteryChangePoint
property string _batteriesRequiredText: _batteriesRequired < 0 ? "N/A" : _batteriesRequired
readonly property real _margins: ScreenTools.defaultFontPixelWidth
QGCPalette { id: qgcPal }
function getMissionTime() {
if(isNaN(_missionTime)) {
return "00:00:00"
}
var t = new Date(0, 0, 0, 0, 0, Number(_missionTime))
return Qt.formatTime(t, 'hh:mm:ss')
}
//-- Eat mouse events, preventing them from reaching toolbar, which is underneath us.
DeadMouseArea {
anchors.fill: parent
}
//-- The reason for this Row to be here is so the Logo (Home) button is in the same
// location as the one in the main toolbar.
Row {
id: logoRow
anchors.bottomMargin: 1
anchors.left: parent.left
anchors.top: parent.top
anchors.bottom: parent.bottom
QGCToolBarButton {
id: settingsButton
anchors.top: parent.top
anchors.bottom: parent.bottom
source: "/qmlimages/PaperPlane.svg"
logo: true
checked: false
onClicked: {
checked = false
showFlyView()
}
}
}
// Progress bar
on_ControllerProgressPctChanged: {
if (_controllerProgressPct === 1) {
missionStats.visible = false
uploadCompleteText.visible = true
progressBar.visible = false
resetProgressTimer.start()
} else if (_controllerProgressPct > 0) {
progressBar.visible = true
}
}
Timer {
id: resetProgressTimer
interval: 5000
onTriggered: {
missionStats.visible = true
uploadCompleteText.visible = false
}
}
QGCLabel {
id: uploadCompleteText
anchors.top: parent.top
anchors.bottom: parent.bottom
anchors.left: logoRow.right
anchors.right: buttonsRow.left
font.pointSize: ScreenTools.largeFontPointSize
horizontalAlignment: Text.AlignHCenter
verticalAlignment: Text.AlignVCenter
text: "Done"
visible: false
}
GridLayout {
id: missionStats
anchors.top: parent.top
anchors.bottom: parent.bottom
anchors.leftMargin: _margins
anchors.rightMargin: _margins
anchors.left: logoRow.right
anchors.right: buttonsRow.left
columnSpacing: 0
columns: 4
GridLayout {
columns: 8
rowSpacing: _rowSpacing
columnSpacing: _labelToValueSpacing
Layout.alignment: Qt.AlignVCenter | Qt.AlignHCenter
QGCLabel {
text: qsTr("Selected Waypoint")
Layout.columnSpan: 8
font.pointSize: ScreenTools.smallFontPointSize
}
QGCLabel { text: qsTr("Alt diff:"); font.pointSize: _dataFontSize; }
QGCLabel {
text: _altDifferenceText
font.pointSize: _dataFontSize
Layout.minimumWidth: _mediumValueWidth
}
Item { width: 1; height: 1 }
QGCLabel { text: qsTr("Azimuth:"); font.pointSize: _dataFontSize; }
QGCLabel {
text: _azimuthText
font.pointSize: _dataFontSize
Layout.minimumWidth: _smallValueWidth
}
Item { width: 1; height: 1 }
QGCLabel { text: qsTr("Distance:"); font.pointSize: _dataFontSize; }
QGCLabel {
text: _distanceText
font.pointSize: _dataFontSize
Layout.minimumWidth: _largeValueWidth
}
QGCLabel { text: qsTr("Gradient:"); font.pointSize: _dataFontSize; }
QGCLabel {
text: _gradientText
font.pointSize: _dataFontSize
Layout.minimumWidth: _mediumValueWidth
}
Item { width: 1; height: 1 }
QGCLabel { text: qsTr("Heading:"); font.pointSize: _dataFontSize; }
QGCLabel {
text: _headingText
font.pointSize: _dataFontSize
Layout.minimumWidth: _smallValueWidth
}
}
GridLayout {
columns: 5
rowSpacing: _rowSpacing
columnSpacing: _labelToValueSpacing
Layout.alignment: Qt.AlignVCenter | Qt.AlignHCenter
QGCLabel {
text: qsTr("Total Mission")
Layout.columnSpan: 5
font.pointSize: ScreenTools.smallFontPointSize
}
QGCLabel { text: qsTr("Distance:"); font.pointSize: _dataFontSize; }
QGCLabel {
text: _missionDistanceText
font.pointSize: _dataFontSize
Layout.minimumWidth: _largeValueWidth
}
Item { width: 1; height: 1 }
QGCLabel { text: qsTr("Max telem dist:"); font.pointSize: _dataFontSize; }
QGCLabel {
text: _missionMaxTelemetryText
font.pointSize: _dataFontSize
Layout.minimumWidth: _largeValueWidth
}
QGCLabel { text: qsTr("Time:"); font.pointSize: _dataFontSize; }
QGCLabel {
text: getMissionTime()
font.pointSize: _dataFontSize
Layout.minimumWidth: _largeValueWidth
}
}
GridLayout {
columns: 3
rowSpacing: _rowSpacing
columnSpacing: _labelToValueSpacing
Layout.alignment: Qt.AlignVCenter | Qt.AlignHCenter
visible: _batteryInfoAvailable
QGCLabel {
text: qsTr("Battery")
Layout.columnSpan: 3
font.pointSize: ScreenTools.smallFontPointSize
}
QGCLabel { text: qsTr("Batteries required:"); font.pointSize: _dataFontSize; }
QGCLabel {
text: _batteriesRequiredText
font.pointSize: _dataFontSize
Layout.minimumWidth: _mediumValueWidth
}
Item { width: 1; height: 1 }
/*
FIXME: Swap point display is currently hidden since the code which calcs it doesn't work correctly
QGCLabel { text: qsTr("Swap waypoint:"); font.pointSize: _dataFontSize; }
QGCLabel {
text: _batteryChangePointText
font.pointSize: _dataFontSize
Layout.minimumWidth: _mediumValueWidth
}
*/
}
GridLayout {
columns: 3
rowSpacing: _rowSpacing
columnSpacing: _labelToValueSpacing
Layout.alignment: Qt.AlignVCenter | Qt.AlignHCenter
QGCLabel {
text: qsTr("ROS")
Layout.columnSpan: 3
font.pointSize: ScreenTools.smallFontPointSize
}
QGCCheckBox {
id: enableCheckbox
property var nemo: wimaPlaner ? wimaPlaner.nemoInterface : undefined
text: qsTr("Enable")
checked: nemo ? nemo.running : false
onCheckedChanged: {
if (nemo){
if (checked){
nemo.start()
} else {
nemo.stop()
}
checked = Qt.binding(function(){return nemo.running})
}
}
Layout.minimumWidth: _mediumValueWidth
}
QGCLabel {
property var nemo: wimaPlaner ? wimaPlaner.nemoInterface : undefined
text: nemo ? nemo.statusString : ""
font.pointSize: _dataFontSize
Layout.minimumWidth: _mediumValueWidth
visible: enableCheckbox.checked
Layout.columnSpan: 2
}
QGCCheckBox {
property var nemo: wimaPlaner ? wimaPlaner.nemoInterface : undefined
text: qsTr("Lock Progress")
checked: wimaPlaner ? wimaPlaner.progressLocked : false
visible: enableCheckbox.checked
onCheckedChanged: {
if (wimaPlaner){
if (checked){
wimaPlaner.progressLocked = true
} else {
wimaPlaner.progressLocked = false
}
}
}
Layout.minimumWidth: _mediumValueWidth
}
}
}
Row {
id:buttonsRow
anchors.rightMargin: _margins
anchors.right: parent.right
anchors.verticalCenter: parent.verticalCenter
spacing: _margins
QGCButton {
id: uploadButton
text: qsTr("Upload")
enabled: wimaPlaner ?
wimaPlaner.readyForSynchronization : false
onClicked: {
if (wimaPlaner){
if (wimaPlaner.readyForSynchronization) {
wimaPlaner.synchronize()
planMasterController.sendToVehicle()
}
}
}
PropertyAnimation on opacity {
easing.type: Easing.OutQuart
from: 0.5
to: 1
loops: Animation.Infinite
running: wimaPlaner ? (wimaPlaner.readyForSynchronization
&& !wimaPlaner.synchronized)
: false
alwaysRunToEnd: true
duration: 2000
}
} // uploadButton
QGCButton {
id: updateButton
text: qsTr("Update")
enabled: true
onClicked: {
if (wimaPlaner){
wimaPlaner.update()
}
}
} // updateButton
} // buttonRow
// Small mission download progress bar
Rectangle {
id: progressBar
anchors.left: parent.left
anchors.bottom: parent.bottom
height: 4
width: _controllerProgressPct * parent.width
color: qgcPal.colorGreen
visible: false
onVisibleChanged: {
if (visible) {
largeProgressBar._userHide = false
}
}
}
/*
Rectangle {
anchors.bottom: parent.bottom
height: toolBar.height * 0.05
width: _activeVehicle ? _activeVehicle.parameterManager.loadProgress * parent.width : 0
color: qgcPal.colorGreen
visible: !largeProgressBar.visible
}
*/
// Large mission download progress bar
Rectangle {
id: largeProgressBar
anchors.bottom: parent.bottom
anchors.left: parent.left
anchors.right: parent.right
height: parent.height
color: qgcPal.window
visible: _showLargeProgress
property bool _userHide: false
property bool _showLargeProgress: progressBar.visible && !_userHide && qgcPal.globalTheme === QGCPalette.Light
Connections {
target: QGroundControl.multiVehicleManager
onActiveVehicleChanged: largeProgressBar._userHide = false
}
Rectangle {
anchors.top: parent.top
anchors.bottom: parent.bottom
width: _controllerProgressPct * parent.width
color: qgcPal.colorGreen
}
QGCLabel {
anchors.centerIn: parent
text: qsTr("Syncing Mission")
font.pointSize: ScreenTools.largeFontPointSize
}
QGCLabel {
anchors.margins: _margin
anchors.right: parent.right
anchors.bottom: parent.bottom
text: qsTr("Click anywhere to hide")
property real _margin: ScreenTools.defaultFontPixelWidth / 2
}
MouseArea {
anchors.fill: parent
onClicked: largeProgressBar._userHide = true
}
}
}
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