Commit fb9b1767 authored by Valentin Platzgummer's avatar Valentin Platzgummer

plan creator added, area editor improved

parent 42fe8ce4
......@@ -195,5 +195,6 @@
<file alias="Yield.svg">src/ui/toolbar/Images/Yield.svg</file>
<file alias="ZoomMinus.svg">src/FlightMap/Images/ZoomMinus.svg</file>
<file alias="ZoomPlus.svg">src/FlightMap/Images/ZoomPlus.svg</file>
<file alias="PlanCreator/MeasurementPlanCreator.png">src/MeasurementComplexItem/MeasurementPlanCreator.png</file>
</qresource>
</RCC>
......@@ -447,6 +447,7 @@ contains (DEFINES, QGC_ENABLE_PAIRING) {
HEADERS += \
src/MeasurementComplexItem/IDArray.h \
src/MeasurementComplexItem/LogicalArray.h \
src/MeasurementComplexItem/MeasurementPlanCreator.h \
src/MeasurementComplexItem/TileArray.h \
src/MeasurementComplexItem/TilePtrArray.h \
src/MeasurementComplexItem/geometry/ProgressArray.h \
......@@ -527,6 +528,7 @@ contains (DEFINES, QGC_ENABLE_PAIRING) {
}
SOURCES += \
src/MeasurementComplexItem/MeasurementPlanCreator.cpp \
src/MeasurementComplexItem/geometry/GeoArea.cc \
src/MeasurementComplexItem/geometry/MeasurementArea.cc \
src/MeasurementComplexItem/geometry/SafeArea.cc \
......
#include "MeasurementPlanCreator.h"
#include "MeasurementComplexItem.h"
#include "PlanMasterController.h"
MeasurementPlanCreator::MeasurementPlanCreator(
PlanMasterController *planMasterController, QObject *parent)
: PlanCreator(
planMasterController, MeasurementComplexItem::name,
QStringLiteral("/qmlimages/PlanCreator/MeasurementPlanCreator.png"),
parent) {}
void MeasurementPlanCreator::createPlan(const QGeoCoordinate &mapCenterCoord) {
_planMasterController->removeAll();
VisualMissionItem *takeoffItem =
_missionController->insertTakeoffItem(mapCenterCoord, -1);
_missionController->insertComplexMissionItem(MeasurementComplexItem::name,
mapCenterCoord, -1);
_missionController->insertLandItem(mapCenterCoord, -1);
_missionController->setCurrentPlanViewSeqNum(takeoffItem->sequenceNumber(),
true);
}
#ifndef MEASUREMENTCOMPLEXITEMPLANCREATOR_H
#define MEASUREMENTCOMPLEXITEMPLANCREATOR_H
#include "PlanCreator.h"
class MeasurementPlanCreator : public PlanCreator {
Q_OBJECT
public:
MeasurementPlanCreator(PlanMasterController *planMasterController,
QObject *parent = nullptr);
Q_INVOKABLE void createPlan(const QGeoCoordinate &mapCenterCoord) final;
};
#endif // MEASUREMENTCOMPLEXITEMPLANCREATOR_H
......@@ -251,7 +251,7 @@ std::shared_future<QVariant>
NemoInterface::Impl::addTiles(const TilePtrArray &tileArray) {
using namespace nemo_interface;
qDebug() << "addTiles called";
// qDebug() << "addTiles called";
if (tileArray.size() > 0) {
......@@ -318,7 +318,7 @@ std::shared_future<QVariant>
NemoInterface::Impl::removeTiles(const IDArray &idArray) {
using namespace nemo_interface;
qDebug() << "removeTiles called";
// qDebug() << "removeTiles called";
if (idArray.size() > 0) {
......@@ -364,7 +364,7 @@ NemoInterface::Impl::removeTiles(const IDArray &idArray) {
std::shared_future<QVariant> NemoInterface::Impl::clearTiles() {
using namespace nemo_interface;
qDebug() << "clearTiles called";
// qDebug() << "clearTiles called";
// clear local tiles (_localTiles)
if (!_localTiles.empty()) {
......@@ -396,14 +396,27 @@ std::shared_future<QVariant> NemoInterface::Impl::clearTiles() {
TileArray NemoInterface::Impl::getTiles(const IDArray &idArray) const {
TileArray tileArray;
for (const auto &id : idArray) {
const auto it = _localTiles.find(id);
if (it != _localTiles.end()) {
MeasurementTile copy;
copy.setId(it->second->id());
copy.setProgress(it->second->progress());
copy.setPath(it->second->tile());
tileArray.append(std::move(copy));
if (this->ready()) {
for (const auto &id : idArray) {
const auto it = _remoteTiles.find(id);
if (it != _remoteTiles.end()) {
MeasurementTile copy;
copy.setId(it->second->id());
copy.setProgress(it->second->progress());
copy.setPath(it->second->tile());
tileArray.append(std::move(copy));
}
}
} else {
for (const auto &id : idArray) {
const auto it = _localTiles.find(id);
if (it != _localTiles.end()) {
MeasurementTile copy;
copy.setId(it->second->id());
copy.setProgress(it->second->progress());
copy.setPath(it->second->tile());
tileArray.append(std::move(copy));
}
}
}
......@@ -413,13 +426,25 @@ TileArray NemoInterface::Impl::getTiles(const IDArray &idArray) const {
TileArray NemoInterface::Impl::getAllTiles() const {
TileArray tileArray;
for (const auto &entry : _localTiles) {
auto pTile = entry.second;
MeasurementTile copy;
copy.setId(pTile->id());
copy.setProgress(pTile->progress());
copy.setPath(pTile->tile());
tileArray.append(std::move(copy));
if (this->ready()) {
for (const auto &entry : _remoteTiles) {
auto pTile = entry.second;
MeasurementTile copy;
copy.setId(pTile->id());
copy.setProgress(pTile->progress());
copy.setPath(pTile->tile());
tileArray.append(std::move(copy));
}
} else {
for (const auto &entry : _localTiles) {
auto pTile = entry.second;
MeasurementTile copy;
copy.setId(pTile->id());
copy.setProgress(pTile->progress());
copy.setPath(pTile->tile());
tileArray.append(std::move(copy));
}
}
return tileArray;
......@@ -518,7 +543,7 @@ const QString &NemoInterface::Impl::warningString() const {
void NemoInterface::Impl::_updateProgress(std::shared_ptr<ProgressArray> pArray,
std::promise<bool> promise) {
qDebug() << "_updateProgress called";
// qDebug() << "_updateProgress called";
bool error = false;
for (auto itLP = pArray->begin(); itLP != pArray->end();) {
......@@ -799,7 +824,7 @@ void NemoInterface::Impl::_doAction() {
QVariant NemoInterface::Impl::_callAddTiles(
std::shared_ptr<QVector<std::shared_ptr<const Tile>>> pTileArray) {
qDebug() << "_callAddTiles called";
// qDebug() << "_callAddTiles called";
this->_lastCall = CALL_NAME::ADD_TILES;
......@@ -900,7 +925,7 @@ QVariant NemoInterface::Impl::_callAddTiles(
QVariant
NemoInterface::Impl::_callRemoveTiles(std::shared_ptr<IDArray> pIdArray) {
qDebug() << "_callRemoveTiles called";
// qDebug() << "_callRemoveTiles called";
this->_lastCall = CALL_NAME::REMOVE_TILES;
......@@ -995,7 +1020,7 @@ NemoInterface::Impl::_callRemoveTiles(std::shared_ptr<IDArray> pIdArray) {
QVariant NemoInterface::Impl::_callClearTiles() {
qDebug() << "_callClearTiles called";
// qDebug() << "_callClearTiles called";
this->_lastCall = CALL_NAME::CLEAR_TILES;
// create response handler.
......@@ -1068,7 +1093,7 @@ QVariant NemoInterface::Impl::_callClearTiles() {
QVariant
NemoInterface::Impl::_callGetProgress(std::shared_ptr<IDArray> pIdArray) {
qDebug() << "_callGetProgress called";
// qDebug() << "_callGetProgress called";
this->_lastCall = CALL_NAME::GET_PROGRESS;
......@@ -1168,7 +1193,7 @@ NemoInterface::Impl::_callGetProgress(std::shared_ptr<IDArray> pIdArray) {
}
QVariant NemoInterface::Impl::_callGetAllProgress() {
qDebug() << "_callGetAllProgress called";
// qDebug() << "_callGetAllProgress called";
this->_lastCall = CALL_NAME::GET_ALL_PROGRESS;
......@@ -1279,7 +1304,7 @@ void NemoInterface::Impl::_addTilesRemote(
std::shared_ptr<QVector<std::shared_ptr<const Tile>>> pTileArray,
std::promise<bool> promise) {
qDebug() << "_addTilesRemote called";
// qDebug() << "_addTilesRemote called";
auto pArrayDup = std::make_shared<QVector<std::shared_ptr<Tile>>>();
for (auto pTile : *pTileArray) {
......@@ -1292,7 +1317,7 @@ void NemoInterface::Impl::_addTilesRemote2(
std::shared_ptr<QVector<std::shared_ptr<Tile>>> pTileArray,
std::promise<bool> promise) {
qDebug() << "_addTilesRemote2 called";
// qDebug() << "_addTilesRemote2 called";
bool anyChange = false;
bool error = false;
......@@ -1326,7 +1351,7 @@ void NemoInterface::Impl::_addTilesRemote2(
void NemoInterface::Impl::_removeTilesRemote(std::shared_ptr<IDArray> idArray,
std::promise<bool> promise) {
qDebug() << "_removeTilesRemote called";
// qDebug() << "_removeTilesRemote called";
bool anyChange = false;
for (const auto id : *idArray) {
......@@ -1351,7 +1376,7 @@ void NemoInterface::Impl::_removeTilesRemote(std::shared_ptr<IDArray> idArray,
}
void NemoInterface::Impl::_clearTilesRemote(std::promise<bool> promise) {
qDebug() << "_clearTilesRemote called";
// qDebug() << "_clearTilesRemote called";
if (_remoteTiles.size() > 0) {
_remoteTiles.clear();
if (this->_isSynchronized()) {
......
......@@ -12,227 +12,240 @@ import QGroundControl.Palette 1.0
Rectangle {
id: _root
width: mainGrid.width
height: mainGrid.height
width: mainColumn.width
height: mainColumn.height
color: qgcPal.windowShadeDark
property bool checked: true
property bool editing: missionItem.editing
property var missionItem: undefined
property int availableWidth: 300
property bool areasCorrect: false
property string errorString: ""
signal abort
property var _areaData: missionItem.areaData
property real _margin: ScreenTools.defaultFontPixelWidth / 2
Component.onCompleted: {
console.assert(missionItem !== undefined,
"please set the missionItem property")
if (checked) {
if (editing) {
areasCorrectTimer.start()
}
}
onCheckedChanged: {
if (checked) {
onEditingChanged: {
if (editing){
areasCorrectTimer.start()
} else {
areasCorrectTimer.stop()
}
}
GridLayout {
id: mainGrid
ColumnLayout {
id: mainColumn
width: availableWidth
columnSpacing: _margin
rowSpacing: _margin
columns: 2
QGCLabel {
text: _root.errorString
wrapMode: Text.WordWrap
horizontalAlignment: Text.AlignLeft
color: "orange"
Layout.columnSpan: parent.columns
spacing: _margin
QGCButton {
id: editButton
text: _root.editing ? qsTr("Done") : qsTr("Edit")
enabled: (_root.editing && _root.areasCorrect) || !_root.editing
onClicked: {
if (_root.editing) {
_root.missionItem.stopEditing()
} else {
_root.missionItem.startEditing()
}
}
Layout.fillWidth: true
visible: !_root.areasCorrect
}
ExclusiveGroup {
id: areaGroup
}
Repeater {
id: areaSelector
GridLayout {
property int selectedIndex: -1
width: availableWidth
columnSpacing: _margin
Layout.fillWidth: true
rowSpacing: _margin
columns: 2
enabled: _root.editing
model: _missionItem.areaData.areaList
delegate: QGCRadioButton {
text: object.objectName
checkable: _root.checked
QGCLabel {
text: _root.errorString
wrapMode: Text.WordWrap
horizontalAlignment: Text.AlignLeft
color: "orange"
Layout.columnSpan: parent.columns
Layout.fillWidth: true
Layout.columnSpan: 2
onCheckedChanged: {
if (checked) {
areaSelector.selectedIndex = index
}
}
visible: !_root.areasCorrect
}
Component.onCompleted: {
if (index === 0) {
checked = true
}
object.interactive = Qt.binding(function () {
return checked && _root.checked
})
}
ExclusiveGroup {
id: areaGroup
}
} // area Repeater
ColumnLayout {
id: editorParent
Layout.fillWidth: true
Layout.maximumWidth: parent.width
Layout.columnSpan: 2
}
Repeater {
id: areaSelector
Repeater {
id: areaEditorRepeater
Layout.maximumWidth: parent.width
model: _missionItem.areaData.areaList
delegate: Item {
id: editor
visible: index == areaSelector.selectedIndex
property var _visualItem: undefined
property var geoArea: object
Component.onCompleted: {
if (geoArea.editorQML && !_visualItem) {
var component = Qt.createComponent(geoArea.editorQML)
if (component.status === Component.Error) {
console.log("Error loading Qml: ",
geoArea.editorQML,
component.errorString())
} else {
_visualItem = component.createObject(editorParent, {
"geoArea": editor.geoArea,
"visible": Qt.binding(
function () {
return editor.visible
}),
"availableWidth": Qt.binding(function () {
return editorParent.width
})
})
property int selectedIndex: -1
model: _missionItem.areaData.areaList
delegate: QGCRadioButton {
text: object.objectName
Layout.fillWidth: true
Layout.columnSpan: 2
onCheckedChanged: {
if (checked) {
areaSelector.selectedIndex = index
}
}
}
Component.onDestruction: {
if (_visualItem) {
_visualItem.destroy()
Component.onCompleted: {
if (index === 0) {
checked = true
}
object.interactive = Qt.binding(function () {
return checked && _root.editing && _missionItem.isCurrentItem
})
}
}
} // editor
} // areaEditorRepeater
} // area Repeater
SectionHeader {
id: commandsHeader
Layout.fillWidth: true
Layout.columnSpan: parent.columns
text: qsTr("Commands")
}
ColumnLayout {
id: editorParent
Layout.fillWidth: true
Layout.maximumWidth: parent.width
Layout.columnSpan: 2
}
GridLayout {
columnSpacing: _margin
rowSpacing: _margin
columns: 2
Layout.columnSpan: 2
Layout.fillWidth: true
visible: commandsHeader.checked
Repeater {
id: areaEditorRepeater
Layout.maximumWidth: parent.width
model: _missionItem.areaData.areaList
delegate: Item {
id: editor
visible: index == areaSelector.selectedIndex
property var _visualItem: undefined
property var geoArea: object
Component.onCompleted: {
if (geoArea.editorQML && !_visualItem) {
var component = Qt.createComponent(
geoArea.editorQML)
if (component.status === Component.Error) {
console.log("Error loading Qml: ",
geoArea.editorQML,
component.errorString())
} else {
_visualItem = component.createObject(
editorParent, {
"geoArea": editor.geoArea,
"visible": Qt.binding(
function () {
return editor.visible
}),
"availableWidth": Qt.binding(
function () {
return editorParent.width
})
})
}
}
}
Component.onDestruction: {
if (_visualItem) {
_visualItem.destroy()
}
}
} // editor
} // areaEditorRepeater
QGCButton {
text: "Intersection"
enabled: _root.checked
SectionHeader {
id: commandsHeader
Layout.fillWidth: true
Layout.columnSpan: parent.columns
onClicked: {
_areaData.intersection()
}
text: qsTr("Commands")
}
QGCButton {
text: "Reset"
onClicked: {
missionItem.reset()
}
GridLayout {
columnSpacing: _margin
rowSpacing: _margin
columns: 2
Layout.columnSpan: 2
Layout.fillWidth: true
}
visible: commandsHeader.checked
QGCButton {
text: "Intersection"
Layout.fillWidth: true
Layout.columnSpan: parent.columns
onClicked: {
_areaData.intersection()
}
}
QGCButton {
text: "Abort"
onClicked: {
_root.abort()
QGCButton {
text: "Reset"
Layout.fillWidth: true
Layout.columnSpan: parent.columns
onClicked: {
missionItem.reset()
}
}
Layout.fillWidth: true
}
}
SectionHeader {
id: hintHeader
Layout.fillWidth: true
Layout.columnSpan: parent.columns
text: qsTr("Hints")
}
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
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).
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.fillWidth: true
Layout.columnSpan: parent.columns
}
}
}
Timer {
id: areasCorrectTimer
running: false
interval: 100
repeat: true
onTriggered: {
_root.areasCorrect = _missionItem.areaData.isCorrect(
false /*show gui message*/
)
if (!_root.areasCorrect) {
_root.errorString = _missionItem.areaData.errorString
} else {
_root.errorString = ""
Timer {
id: areasCorrectTimer
running: false
interval: 100
repeat: true
onTriggered: {
_root.areasCorrect = _missionItem.areaData.isCorrect(
false /*show gui message*/
)
if (!_root.areasCorrect) {
_root.errorString = _missionItem.areaData.errorString
} else {
_root.errorString = ""
}
}
}
}
Settings {
property alias showHint: hintHeader.checked
}
Settings {
property alias showHint: hintHeader.checked
}
} // GridLayout
} // GridLayout
} // Rectangle
......@@ -49,13 +49,12 @@ Rectangle {
anchors.left: parent.left
anchors.right: parent.right
enabled: !editing || editing && correct
enabled: !editing
readonly property int areaEditorIndex: 0
readonly property int parameterEditorIndex: 1
readonly property int nemoEditorIndex: 2
property bool editing: _missionItem.editing
property bool correct: false
Component.onCompleted: currentIndex = editing ? areaEditorIndex : parameterEditorIndex
......@@ -71,47 +70,18 @@ Rectangle {
icon.source: "qrc:/res/fish.svg"
icon.height: ScreenTools.defaultFontPixelHeight
}
onEditingChanged: {
if (editing) {
areasCorrectTimer.start()
} else {
areasCorrectTimer.stop()
}
}
onCurrentIndexChanged: {
if (currentIndex === areaEditorIndex) {
_missionItem.startEditing()
} else {
_missionItem.stopEditing()
}
}
Timer {
id: areasCorrectTimer
running: false
interval: 100
repeat: true
onTriggered: {
tabBar.correct = _missionItem.areaData.isCorrect(
false /*show gui message*/
)
}
}
}
MCI.AreaDataEditor {
id: areaEditor
visible: tabBar.currentIndex === tabBar.areaEditorIndex
checked: visible
missionItem: _root._missionItem
availableWidth: mainColumn.width
onAbort: {
missionItem.abortEditing()
tabBar.currentIndex = tabBar.parameterEditorIndex
onVisibleChanged:{
if (visible){
_missionItem.startEditing()