Commit fb9b1767 authored by Valentin Platzgummer's avatar Valentin Platzgummer

plan creator added, area editor improved

parent 42fe8ce4
...@@ -195,5 +195,6 @@ ...@@ -195,5 +195,6 @@
<file alias="Yield.svg">src/ui/toolbar/Images/Yield.svg</file> <file alias="Yield.svg">src/ui/toolbar/Images/Yield.svg</file>
<file alias="ZoomMinus.svg">src/FlightMap/Images/ZoomMinus.svg</file> <file alias="ZoomMinus.svg">src/FlightMap/Images/ZoomMinus.svg</file>
<file alias="ZoomPlus.svg">src/FlightMap/Images/ZoomPlus.svg</file> <file alias="ZoomPlus.svg">src/FlightMap/Images/ZoomPlus.svg</file>
<file alias="PlanCreator/MeasurementPlanCreator.png">src/MeasurementComplexItem/MeasurementPlanCreator.png</file>
</qresource> </qresource>
</RCC> </RCC>
...@@ -447,6 +447,7 @@ contains (DEFINES, QGC_ENABLE_PAIRING) { ...@@ -447,6 +447,7 @@ contains (DEFINES, QGC_ENABLE_PAIRING) {
HEADERS += \ HEADERS += \
src/MeasurementComplexItem/IDArray.h \ src/MeasurementComplexItem/IDArray.h \
src/MeasurementComplexItem/LogicalArray.h \ src/MeasurementComplexItem/LogicalArray.h \
src/MeasurementComplexItem/MeasurementPlanCreator.h \
src/MeasurementComplexItem/TileArray.h \ src/MeasurementComplexItem/TileArray.h \
src/MeasurementComplexItem/TilePtrArray.h \ src/MeasurementComplexItem/TilePtrArray.h \
src/MeasurementComplexItem/geometry/ProgressArray.h \ src/MeasurementComplexItem/geometry/ProgressArray.h \
...@@ -527,6 +528,7 @@ contains (DEFINES, QGC_ENABLE_PAIRING) { ...@@ -527,6 +528,7 @@ contains (DEFINES, QGC_ENABLE_PAIRING) {
} }
SOURCES += \ SOURCES += \
src/MeasurementComplexItem/MeasurementPlanCreator.cpp \
src/MeasurementComplexItem/geometry/GeoArea.cc \ src/MeasurementComplexItem/geometry/GeoArea.cc \
src/MeasurementComplexItem/geometry/MeasurementArea.cc \ src/MeasurementComplexItem/geometry/MeasurementArea.cc \
src/MeasurementComplexItem/geometry/SafeArea.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> ...@@ -251,7 +251,7 @@ std::shared_future<QVariant>
NemoInterface::Impl::addTiles(const TilePtrArray &tileArray) { NemoInterface::Impl::addTiles(const TilePtrArray &tileArray) {
using namespace nemo_interface; using namespace nemo_interface;
qDebug() << "addTiles called"; // qDebug() << "addTiles called";
if (tileArray.size() > 0) { if (tileArray.size() > 0) {
...@@ -318,7 +318,7 @@ std::shared_future<QVariant> ...@@ -318,7 +318,7 @@ std::shared_future<QVariant>
NemoInterface::Impl::removeTiles(const IDArray &idArray) { NemoInterface::Impl::removeTiles(const IDArray &idArray) {
using namespace nemo_interface; using namespace nemo_interface;
qDebug() << "removeTiles called"; // qDebug() << "removeTiles called";
if (idArray.size() > 0) { if (idArray.size() > 0) {
...@@ -364,7 +364,7 @@ NemoInterface::Impl::removeTiles(const IDArray &idArray) { ...@@ -364,7 +364,7 @@ NemoInterface::Impl::removeTiles(const IDArray &idArray) {
std::shared_future<QVariant> NemoInterface::Impl::clearTiles() { std::shared_future<QVariant> NemoInterface::Impl::clearTiles() {
using namespace nemo_interface; using namespace nemo_interface;
qDebug() << "clearTiles called"; // qDebug() << "clearTiles called";
// clear local tiles (_localTiles) // clear local tiles (_localTiles)
if (!_localTiles.empty()) { if (!_localTiles.empty()) {
...@@ -396,14 +396,27 @@ std::shared_future<QVariant> NemoInterface::Impl::clearTiles() { ...@@ -396,14 +396,27 @@ std::shared_future<QVariant> NemoInterface::Impl::clearTiles() {
TileArray NemoInterface::Impl::getTiles(const IDArray &idArray) const { TileArray NemoInterface::Impl::getTiles(const IDArray &idArray) const {
TileArray tileArray; TileArray tileArray;
for (const auto &id : idArray) { if (this->ready()) {
const auto it = _localTiles.find(id); for (const auto &id : idArray) {
if (it != _localTiles.end()) { const auto it = _remoteTiles.find(id);
MeasurementTile copy; if (it != _remoteTiles.end()) {
copy.setId(it->second->id()); MeasurementTile copy;
copy.setProgress(it->second->progress()); copy.setId(it->second->id());
copy.setPath(it->second->tile()); copy.setProgress(it->second->progress());
tileArray.append(std::move(copy)); 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 { ...@@ -413,13 +426,25 @@ TileArray NemoInterface::Impl::getTiles(const IDArray &idArray) const {
TileArray NemoInterface::Impl::getAllTiles() const { TileArray NemoInterface::Impl::getAllTiles() const {
TileArray tileArray; TileArray tileArray;
for (const auto &entry : _localTiles) { if (this->ready()) {
auto pTile = entry.second; for (const auto &entry : _remoteTiles) {
MeasurementTile copy; auto pTile = entry.second;
copy.setId(pTile->id()); MeasurementTile copy;
copy.setProgress(pTile->progress()); copy.setId(pTile->id());
copy.setPath(pTile->tile()); copy.setProgress(pTile->progress());
tileArray.append(std::move(copy)); 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; return tileArray;
...@@ -518,7 +543,7 @@ const QString &NemoInterface::Impl::warningString() const { ...@@ -518,7 +543,7 @@ const QString &NemoInterface::Impl::warningString() const {
void NemoInterface::Impl::_updateProgress(std::shared_ptr<ProgressArray> pArray, void NemoInterface::Impl::_updateProgress(std::shared_ptr<ProgressArray> pArray,
std::promise<bool> promise) { std::promise<bool> promise) {
qDebug() << "_updateProgress called"; // qDebug() << "_updateProgress called";
bool error = false; bool error = false;
for (auto itLP = pArray->begin(); itLP != pArray->end();) { for (auto itLP = pArray->begin(); itLP != pArray->end();) {
...@@ -799,7 +824,7 @@ void NemoInterface::Impl::_doAction() { ...@@ -799,7 +824,7 @@ void NemoInterface::Impl::_doAction() {
QVariant NemoInterface::Impl::_callAddTiles( QVariant NemoInterface::Impl::_callAddTiles(
std::shared_ptr<QVector<std::shared_ptr<const Tile>>> pTileArray) { std::shared_ptr<QVector<std::shared_ptr<const Tile>>> pTileArray) {
qDebug() << "_callAddTiles called"; // qDebug() << "_callAddTiles called";
this->_lastCall = CALL_NAME::ADD_TILES; this->_lastCall = CALL_NAME::ADD_TILES;
...@@ -900,7 +925,7 @@ QVariant NemoInterface::Impl::_callAddTiles( ...@@ -900,7 +925,7 @@ QVariant NemoInterface::Impl::_callAddTiles(
QVariant QVariant
NemoInterface::Impl::_callRemoveTiles(std::shared_ptr<IDArray> pIdArray) { NemoInterface::Impl::_callRemoveTiles(std::shared_ptr<IDArray> pIdArray) {
qDebug() << "_callRemoveTiles called"; // qDebug() << "_callRemoveTiles called";
this->_lastCall = CALL_NAME::REMOVE_TILES; this->_lastCall = CALL_NAME::REMOVE_TILES;
...@@ -995,7 +1020,7 @@ NemoInterface::Impl::_callRemoveTiles(std::shared_ptr<IDArray> pIdArray) { ...@@ -995,7 +1020,7 @@ NemoInterface::Impl::_callRemoveTiles(std::shared_ptr<IDArray> pIdArray) {
QVariant NemoInterface::Impl::_callClearTiles() { QVariant NemoInterface::Impl::_callClearTiles() {
qDebug() << "_callClearTiles called"; // qDebug() << "_callClearTiles called";
this->_lastCall = CALL_NAME::CLEAR_TILES; this->_lastCall = CALL_NAME::CLEAR_TILES;
// create response handler. // create response handler.
...@@ -1068,7 +1093,7 @@ QVariant NemoInterface::Impl::_callClearTiles() { ...@@ -1068,7 +1093,7 @@ QVariant NemoInterface::Impl::_callClearTiles() {
QVariant QVariant
NemoInterface::Impl::_callGetProgress(std::shared_ptr<IDArray> pIdArray) { NemoInterface::Impl::_callGetProgress(std::shared_ptr<IDArray> pIdArray) {
qDebug() << "_callGetProgress called"; // qDebug() << "_callGetProgress called";
this->_lastCall = CALL_NAME::GET_PROGRESS; this->_lastCall = CALL_NAME::GET_PROGRESS;
...@@ -1168,7 +1193,7 @@ NemoInterface::Impl::_callGetProgress(std::shared_ptr<IDArray> pIdArray) { ...@@ -1168,7 +1193,7 @@ NemoInterface::Impl::_callGetProgress(std::shared_ptr<IDArray> pIdArray) {
} }
QVariant NemoInterface::Impl::_callGetAllProgress() { QVariant NemoInterface::Impl::_callGetAllProgress() {
qDebug() << "_callGetAllProgress called"; // qDebug() << "_callGetAllProgress called";
this->_lastCall = CALL_NAME::GET_ALL_PROGRESS; this->_lastCall = CALL_NAME::GET_ALL_PROGRESS;
...@@ -1279,7 +1304,7 @@ void NemoInterface::Impl::_addTilesRemote( ...@@ -1279,7 +1304,7 @@ void NemoInterface::Impl::_addTilesRemote(
std::shared_ptr<QVector<std::shared_ptr<const Tile>>> pTileArray, std::shared_ptr<QVector<std::shared_ptr<const Tile>>> pTileArray,
std::promise<bool> promise) { std::promise<bool> promise) {
qDebug() << "_addTilesRemote called"; // qDebug() << "_addTilesRemote called";
auto pArrayDup = std::make_shared<QVector<std::shared_ptr<Tile>>>(); auto pArrayDup = std::make_shared<QVector<std::shared_ptr<Tile>>>();
for (auto pTile : *pTileArray) { for (auto pTile : *pTileArray) {
...@@ -1292,7 +1317,7 @@ void NemoInterface::Impl::_addTilesRemote2( ...@@ -1292,7 +1317,7 @@ void NemoInterface::Impl::_addTilesRemote2(
std::shared_ptr<QVector<std::shared_ptr<Tile>>> pTileArray, std::shared_ptr<QVector<std::shared_ptr<Tile>>> pTileArray,
std::promise<bool> promise) { std::promise<bool> promise) {
qDebug() << "_addTilesRemote2 called"; // qDebug() << "_addTilesRemote2 called";
bool anyChange = false; bool anyChange = false;
bool error = false; bool error = false;
...@@ -1326,7 +1351,7 @@ void NemoInterface::Impl::_addTilesRemote2( ...@@ -1326,7 +1351,7 @@ void NemoInterface::Impl::_addTilesRemote2(
void NemoInterface::Impl::_removeTilesRemote(std::shared_ptr<IDArray> idArray, void NemoInterface::Impl::_removeTilesRemote(std::shared_ptr<IDArray> idArray,
std::promise<bool> promise) { std::promise<bool> promise) {
qDebug() << "_removeTilesRemote called"; // qDebug() << "_removeTilesRemote called";
bool anyChange = false; bool anyChange = false;
for (const auto id : *idArray) { for (const auto id : *idArray) {
...@@ -1351,7 +1376,7 @@ void NemoInterface::Impl::_removeTilesRemote(std::shared_ptr<IDArray> idArray, ...@@ -1351,7 +1376,7 @@ void NemoInterface::Impl::_removeTilesRemote(std::shared_ptr<IDArray> idArray,
} }
void NemoInterface::Impl::_clearTilesRemote(std::promise<bool> promise) { void NemoInterface::Impl::_clearTilesRemote(std::promise<bool> promise) {
qDebug() << "_clearTilesRemote called"; // qDebug() << "_clearTilesRemote called";
if (_remoteTiles.size() > 0) { if (_remoteTiles.size() > 0) {
_remoteTiles.clear(); _remoteTiles.clear();
if (this->_isSynchronized()) { if (this->_isSynchronized()) {
......
...@@ -12,227 +12,240 @@ import QGroundControl.Palette 1.0 ...@@ -12,227 +12,240 @@ import QGroundControl.Palette 1.0
Rectangle { Rectangle {
id: _root id: _root
width: mainGrid.width width: mainColumn.width
height: mainGrid.height height: mainColumn.height
color: qgcPal.windowShadeDark color: qgcPal.windowShadeDark
property bool checked: true property bool editing: missionItem.editing
property var missionItem: undefined property var missionItem: undefined
property int availableWidth: 300 property int availableWidth: 300
property bool areasCorrect: false property bool areasCorrect: false
property string errorString: "" property string errorString: ""
signal abort
property var _areaData: missionItem.areaData property var _areaData: missionItem.areaData
property real _margin: ScreenTools.defaultFontPixelWidth / 2 property real _margin: ScreenTools.defaultFontPixelWidth / 2
Component.onCompleted: { Component.onCompleted: {
console.assert(missionItem !== undefined, console.assert(missionItem !== undefined,
"please set the missionItem property") "please set the missionItem property")
if (checked) { if (editing) {
areasCorrectTimer.start() areasCorrectTimer.start()
} }
} }
onCheckedChanged: { onEditingChanged: {
if (checked) { if (editing){
areasCorrectTimer.start() areasCorrectTimer.start()
} else { } else {
areasCorrectTimer.stop() areasCorrectTimer.stop()
} }
} }
GridLayout { ColumnLayout {
id: mainGrid id: mainColumn
width: availableWidth width: availableWidth
columnSpacing: _margin spacing: _margin
rowSpacing: _margin
columns: 2 QGCButton {
id: editButton
QGCLabel { text: _root.editing ? qsTr("Done") : qsTr("Edit")
text: _root.errorString enabled: (_root.editing && _root.areasCorrect) || !_root.editing
wrapMode: Text.WordWrap onClicked: {
horizontalAlignment: Text.AlignLeft if (_root.editing) {
color: "orange" _root.missionItem.stopEditing()
Layout.columnSpan: parent.columns } else {
_root.missionItem.startEditing()
}
}
Layout.fillWidth: true Layout.fillWidth: true
visible: !_root.areasCorrect
} }
ExclusiveGroup { GridLayout {
id: areaGroup
}
Repeater {
id: areaSelector
property int selectedIndex: -1 width: availableWidth
columnSpacing: _margin
Layout.fillWidth: true
rowSpacing: _margin
columns: 2
enabled: _root.editing
model: _missionItem.areaData.areaList QGCLabel {
delegate: QGCRadioButton { text: _root.errorString
text: object.objectName wrapMode: Text.WordWrap
checkable: _root.checked horizontalAlignment: Text.AlignLeft
color: "orange"
Layout.columnSpan: parent.columns
Layout.fillWidth: true Layout.fillWidth: true
Layout.columnSpan: 2 visible: !_root.areasCorrect
}
onCheckedChanged: {
if (checked) {
areaSelector.selectedIndex = index
}
}
Component.onCompleted: { ExclusiveGroup {
if (index === 0) { id: areaGroup
checked = true
}
object.interactive = Qt.binding(function () {
return checked && _root.checked
})
}
} }
} // area Repeater
ColumnLayout { Repeater {
id: editorParent id: areaSelector
Layout.fillWidth: true
Layout.maximumWidth: parent.width
Layout.columnSpan: 2
}
Repeater { property int selectedIndex: -1
id: areaEditorRepeater
model: _missionItem.areaData.areaList
Layout.maximumWidth: parent.width delegate: QGCRadioButton {
text: object.objectName
model: _missionItem.areaData.areaList Layout.fillWidth: true
delegate: Item { Layout.columnSpan: 2
id: editor
visible: index == areaSelector.selectedIndex onCheckedChanged: {
if (checked) {
property var _visualItem: undefined areaSelector.selectedIndex = index
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: { Component.onCompleted: {
if (_visualItem) { if (index === 0) {
_visualItem.destroy() checked = true
}
object.interactive = Qt.binding(function () {
return checked && _root.editing && _missionItem.isCurrentItem
})
} }
} }
} // editor } // area Repeater
} // areaEditorRepeater
SectionHeader { ColumnLayout {
id: commandsHeader id: editorParent
Layout.fillWidth: true Layout.fillWidth: true
Layout.columnSpan: parent.columns Layout.maximumWidth: parent.width
text: qsTr("Commands") Layout.columnSpan: 2
} }
GridLayout { Repeater {
columnSpacing: _margin id: areaEditorRepeater
rowSpacing: _margin
columns: 2 Layout.maximumWidth: parent.width
Layout.columnSpan: 2
Layout.fillWidth: true model: _missionItem.areaData.areaList
visible: commandsHeader.checked 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 { SectionHeader {
text: "Intersection" id: commandsHeader
enabled: _root.checked
Layout.fillWidth: true Layout.fillWidth: true
Layout.columnSpan: parent.columns Layout.columnSpan: parent.columns
onClicked: { text: qsTr("Commands")
_areaData.intersection()
}
} }
QGCButton { GridLayout {
text: "Reset" columnSpacing: _margin
onClicked: { rowSpacing: _margin
missionItem.reset() columns: 2
} Layout.columnSpan: 2
Layout.fillWidth: true Layout.fillWidth: true
} visible: commandsHeader.checked
QGCButton {
text: "Intersection"
Layout.fillWidth: true
Layout.columnSpan: parent.columns
onClicked: {
_areaData.intersection()
}
}
QGCButton { QGCButton {
text: "Abort" text: "Reset"
onClicked: { Layout.fillWidth: true
_root.abort() Layout.columnSpan: parent.columns
onClicked: {
missionItem.reset()
}
} }
Layout.fillWidth: true
} }
}
SectionHeader { SectionHeader {
id: hintHeader id: hintHeader
Layout.fillWidth: true Layout.fillWidth: true
Layout.columnSpan: parent.columns Layout.columnSpan: parent.columns
text: qsTr("Hints") text: qsTr("Hints")
} }
GridLayout { GridLayout {
columnSpacing: _margin columnSpacing: _margin
rowSpacing: _margin rowSpacing: _margin
columns: 2 columns: 2
Layout.columnSpan: 2 Layout.columnSpan: 2
Layout.fillWidth: true Layout.fillWidth: true
visible: hintHeader.checked visible: hintHeader.checked
QGCLabel { QGCLabel {
id: hintLabel id: hintLabel
wrapMode: Text.WordWrap wrapMode: Text.WordWrap
horizontalAlignment: Text.AlignLeft horizontalAlignment: Text.AlignLeft
text: qsTr("Use the Intersection button to clip the Measurement Area(s). 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 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.") Use the Abort button to reset the areas and leave the tab.")
Layout.fillWidth: true Layout.fillWidth: true
Layout.columnSpan: parent.columns Layout.columnSpan: parent.columns
}
} }
}
Timer { Timer {
id: areasCorrectTimer id: areasCorrectTimer
running: false running: false
interval: 100 interval: 100
repeat: true repeat: true
onTriggered: { onTriggered: {
_root.areasCorrect = _missionItem.areaData.isCorrect( _root.areasCorrect = _missionItem.areaData.isCorrect(
false /*show gui message*/ false /*show gui message*/
) )
if (!_root.areasCorrect) { if (!_root.areasCorrect) {
_root.errorString = _missionItem.areaData.errorString _root.errorString = _missionItem.areaData.errorString
} else { } else {
_root.errorString = "" _root.errorString = ""
}
} }
} }
}
Settings { Settings {
property alias showHint: hintHeader.checked property alias showHint: hintHeader.checked
} }
} // GridLayout
} // GridLayout } // GridLayout
} // Rectangle } // Rectangle
...@@ -49,13 +49,12 @@ Rectangle { ...@@ -49,13 +49,12 @@ Rectangle {
anchors.left: parent.left anchors.left: parent.left
anchors.right: parent.right anchors.right: parent.right
enabled: !editing || editing && correct enabled: !editing
readonly property int areaEditorIndex: 0 readonly property int areaEditorIndex: 0
readonly property int parameterEditorIndex: 1 readonly property int parameterEditorIndex: 1
readonly property int nemoEditorIndex: 2 readonly property int nemoEditorIndex: 2
property bool editing: _missionItem.editing property bool editing: _missionItem.editing
property bool correct: false
Component.onCompleted: currentIndex = editing ? areaEditorIndex : parameterEditorIndex Component.onCompleted: currentIndex = editing ? areaEditorIndex : parameterEditorIndex
...@@ -71,47 +70,18 @@ Rectangle { ...@@ -71,47 +70,18 @@ Rectangle {
icon.source: "qrc:/res/fish.svg" icon.source: "qrc:/res/fish.svg"
icon.height: ScreenTools.defaultFontPixelHeight 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 { MCI.AreaDataEditor {
id: areaEditor id: areaEditor
visible: tabBar.currentIndex === tabBar.areaEditorIndex visible: tabBar.currentIndex === tabBar.areaEditorIndex
checked: visible
missionItem: _root._missionItem missionItem: _root._missionItem
availableWidth: mainColumn.width availableWidth: mainColumn.width
onAbort: { onVisibleChanged:{
missionItem.abortEditing() if (visible){
tabBar.currentIndex = tabBar.parameterEditorIndex _missionItem.startEditing()
}
} }
} }
...@@ -119,7 +89,6 @@ Rectangle { ...@@ -119,7 +89,6 @@ Rectangle {
id: parameterEditor id: parameterEditor
visible: tabBar.currentIndex === tabBar.parameterEditorIndex visible: tabBar.currentIndex === tabBar.parameterEditorIndex
checked: visible
missionItem: _root._missionItem missionItem: _root._missionItem
availableWidth: mainColumn.width availableWidth: mainColumn.width
} }
...@@ -128,7 +97,6 @@ Rectangle { ...@@ -128,7 +97,6 @@ Rectangle {
id: nemoEditor id: nemoEditor
visible: tabBar.currentIndex === tabBar.nemoEditorIndex visible: tabBar.currentIndex === tabBar.nemoEditorIndex
checked: visible
missionItem: _root._missionItem missionItem: _root._missionItem
availableWidth: mainColumn.width availableWidth: mainColumn.width
} }
......
...@@ -8,651 +8,722 @@ ...@@ -8,651 +8,722 @@
****************************************************************************/ ****************************************************************************/
#include "PlanMasterController.h" #include "PlanMasterController.h"
#include "QGCApplication.h"
#include "QGCCorePlugin.h"
#include "MultiVehicleManager.h"
#include "SettingsManager.h"
#include "AppSettings.h" #include "AppSettings.h"
#include "BlankPlanCreator.h"
#include "CorridorScanPlanCreator.h"
#include "JsonHelper.h" #include "JsonHelper.h"
#include "MissionManager.h"
#include "KMLPlanDomDocument.h" #include "KMLPlanDomDocument.h"
#include "SurveyPlanCreator.h" #include "MeasurementPlanCreator.h"
#include "MissionManager.h"
#include "MultiVehicleManager.h"
#include "QGCApplication.h"
#include "QGCCorePlugin.h"
#include "SettingsManager.h"
#include "StructureScanPlanCreator.h" #include "StructureScanPlanCreator.h"
#include "CorridorScanPlanCreator.h" #include "SurveyPlanCreator.h"
#include "BlankPlanCreator.h"
#if defined(QGC_AIRMAP_ENABLED) #if defined(QGC_AIRMAP_ENABLED)
#include "AirspaceFlightPlanProvider.h" #include "AirspaceFlightPlanProvider.h"
#endif #endif
#include <QDomDocument> #include <QDomDocument>
#include <QJsonDocument>
#include <QFileInfo> #include <QFileInfo>
#include <QJsonDocument>
QGC_LOGGING_CATEGORY(PlanMasterControllerLog, "PlanMasterControllerLog") QGC_LOGGING_CATEGORY(PlanMasterControllerLog, "PlanMasterControllerLog")
const int PlanMasterController::kPlanFileVersion = 1; const int PlanMasterController::kPlanFileVersion = 1;
const char* PlanMasterController::kPlanFileType = "Plan"; const char *PlanMasterController::kPlanFileType = "Plan";
const char* PlanMasterController::kJsonMissionObjectKey = "mission"; const char *PlanMasterController::kJsonMissionObjectKey = "mission";
const char* PlanMasterController::kJsonGeoFenceObjectKey = "geoFence"; const char *PlanMasterController::kJsonGeoFenceObjectKey = "geoFence";
const char* PlanMasterController::kJsonRallyPointsObjectKey = "rallyPoints"; const char *PlanMasterController::kJsonRallyPointsObjectKey = "rallyPoints";
PlanMasterController::PlanMasterController(QObject* parent) PlanMasterController::PlanMasterController(QObject *parent)
: QObject (parent) : QObject(parent),
, _multiVehicleMgr (qgcApp()->toolbox()->multiVehicleManager()) _multiVehicleMgr(qgcApp()->toolbox()->multiVehicleManager()),
, _controllerVehicle (new Vehicle(Vehicle::MAV_AUTOPILOT_TRACK, Vehicle::MAV_TYPE_TRACK, qgcApp()->toolbox()->firmwarePluginManager(), this)) _controllerVehicle(
, _managerVehicle (_controllerVehicle) new Vehicle(Vehicle::MAV_AUTOPILOT_TRACK, Vehicle::MAV_TYPE_TRACK,
, _missionController (this) qgcApp()->toolbox()->firmwarePluginManager(), this)),
, _geoFenceController (this) _managerVehicle(_controllerVehicle), _missionController(this),
, _rallyPointController (this) _geoFenceController(this), _rallyPointController(this) {
{ _commonInit();
_commonInit();
} }
#ifdef QT_DEBUG #ifdef QT_DEBUG
PlanMasterController::PlanMasterController(MAV_AUTOPILOT firmwareType, MAV_TYPE vehicleType, QObject* parent) PlanMasterController::PlanMasterController(MAV_AUTOPILOT firmwareType,
: QObject (parent) MAV_TYPE vehicleType,
, _multiVehicleMgr (qgcApp()->toolbox()->multiVehicleManager()) QObject *parent)
, _controllerVehicle (new Vehicle(firmwareType, vehicleType, qgcApp()->toolbox()->firmwarePluginManager())) : QObject(parent),
, _managerVehicle (_controllerVehicle) _multiVehicleMgr(qgcApp()->toolbox()->multiVehicleManager()),
, _missionController (this) _controllerVehicle(
, _geoFenceController (this) new Vehicle(firmwareType, vehicleType,
, _rallyPointController (this) qgcApp()->toolbox()->firmwarePluginManager())),
{ _managerVehicle(_controllerVehicle), _missionController(this),
_commonInit(); _geoFenceController(this), _rallyPointController(this) {
_commonInit();
} }
#endif #endif
void PlanMasterController::_commonInit(void) void PlanMasterController::_commonInit(void) {
{ connect(&_missionController, &MissionController::dirtyChanged, this,
connect(&_missionController, &MissionController::dirtyChanged, this, &PlanMasterController::dirtyChanged); &PlanMasterController::dirtyChanged);
connect(&_geoFenceController, &GeoFenceController::dirtyChanged, this, &PlanMasterController::dirtyChanged); connect(&_geoFenceController, &GeoFenceController::dirtyChanged, this,
connect(&_rallyPointController, &RallyPointController::dirtyChanged, this, &PlanMasterController::dirtyChanged); &PlanMasterController::dirtyChanged);
connect(&_rallyPointController, &RallyPointController::dirtyChanged, this,
&PlanMasterController::dirtyChanged);
connect(&_missionController, &MissionController::containsItemsChanged, this, &PlanMasterController::containsItemsChanged); connect(&_missionController, &MissionController::containsItemsChanged, this,
connect(&_geoFenceController, &GeoFenceController::containsItemsChanged, this, &PlanMasterController::containsItemsChanged); &PlanMasterController::containsItemsChanged);
connect(&_rallyPointController, &RallyPointController::containsItemsChanged, this, &PlanMasterController::containsItemsChanged); connect(&_geoFenceController, &GeoFenceController::containsItemsChanged, this,
&PlanMasterController::containsItemsChanged);
connect(&_rallyPointController, &RallyPointController::containsItemsChanged,
this, &PlanMasterController::containsItemsChanged);
connect(&_missionController, &MissionController::syncInProgressChanged, this, &PlanMasterController::syncInProgressChanged); connect(&_missionController, &MissionController::syncInProgressChanged, this,
connect(&_geoFenceController, &GeoFenceController::syncInProgressChanged, this, &PlanMasterController::syncInProgressChanged); &PlanMasterController::syncInProgressChanged);
connect(&_rallyPointController, &RallyPointController::syncInProgressChanged, this, &PlanMasterController::syncInProgressChanged); connect(&_geoFenceController, &GeoFenceController::syncInProgressChanged,
this, &PlanMasterController::syncInProgressChanged);
connect(&_rallyPointController, &RallyPointController::syncInProgressChanged,
this, &PlanMasterController::syncInProgressChanged);
// Offline vehicle can change firmware/vehicle type // Offline vehicle can change firmware/vehicle type
connect(_controllerVehicle, &Vehicle::vehicleTypeChanged, this, &PlanMasterController::_updatePlanCreatorsList); connect(_controllerVehicle, &Vehicle::vehicleTypeChanged, this,
&PlanMasterController::_updatePlanCreatorsList);
} }
PlanMasterController::~PlanMasterController() {}
PlanMasterController::~PlanMasterController() void PlanMasterController::start(void) {
{ _missionController.start(_flyView);
_geoFenceController.start(_flyView);
} _rallyPointController.start(_flyView);
void PlanMasterController::start(void)
{
_missionController.start (_flyView);
_geoFenceController.start (_flyView);
_rallyPointController.start (_flyView);
_activeVehicleChanged(_multiVehicleMgr->activeVehicle()); _activeVehicleChanged(_multiVehicleMgr->activeVehicle());
connect(_multiVehicleMgr, &MultiVehicleManager::activeVehicleChanged, this, &PlanMasterController::_activeVehicleChanged); connect(_multiVehicleMgr, &MultiVehicleManager::activeVehicleChanged, this,
&PlanMasterController::_activeVehicleChanged);
_updatePlanCreatorsList(); _updatePlanCreatorsList();
#if defined(QGC_AIRMAP_ENABLED) #if defined(QGC_AIRMAP_ENABLED)
//-- This assumes there is one single instance of PlanMasterController in edit mode. //-- This assumes there is one single instance of PlanMasterController in edit
if(!flyView) { //mode.
// Wait for signal confirming AirMap client connection before starting flight planning if (!flyView) {
connect(qgcApp()->toolbox()->airspaceManager(), &AirspaceManager::connectStatusChanged, this, &PlanMasterController::_startFlightPlanning); // Wait for signal confirming AirMap client connection before starting
} // flight planning
connect(qgcApp()->toolbox()->airspaceManager(),
&AirspaceManager::connectStatusChanged, this,
&PlanMasterController::_startFlightPlanning);
}
#endif #endif
} }
void PlanMasterController::startStaticActiveVehicle(Vehicle* vehicle, bool deleteWhenSendCompleted) void PlanMasterController::startStaticActiveVehicle(
{ Vehicle *vehicle, bool deleteWhenSendCompleted) {
_flyView = true; _flyView = true;
_deleteWhenSendCompleted = deleteWhenSendCompleted; _deleteWhenSendCompleted = deleteWhenSendCompleted;
_missionController.start(_flyView); _missionController.start(_flyView);
_geoFenceController.start(_flyView); _geoFenceController.start(_flyView);
_rallyPointController.start(_flyView); _rallyPointController.start(_flyView);
_activeVehicleChanged(vehicle); _activeVehicleChanged(vehicle);
} }
void PlanMasterController::_activeVehicleChanged(Vehicle* activeVehicle) void PlanMasterController::_activeVehicleChanged(Vehicle *activeVehicle) {
{ if (_managerVehicle == activeVehicle) {
if (_managerVehicle == activeVehicle) { // We are already setup for this vehicle
// We are already setup for this vehicle return;
return; }
}
qCDebug(PlanMasterControllerLog) << "_activeVehicleChanged" << activeVehicle;
qCDebug(PlanMasterControllerLog) << "_activeVehicleChanged" << activeVehicle;
if (_managerVehicle) {
if (_managerVehicle) { // Disconnect old vehicle. Be careful of wildcarding disconnect too much
// Disconnect old vehicle. Be careful of wildcarding disconnect too much since _managerVehicle may equal _controllerVehicle // since _managerVehicle may equal _controllerVehicle
disconnect(_managerVehicle->missionManager(), nullptr, nullptr, nullptr); disconnect(_managerVehicle->missionManager(), nullptr, nullptr, nullptr);
disconnect(_managerVehicle->geoFenceManager(), nullptr, nullptr, nullptr); disconnect(_managerVehicle->geoFenceManager(), nullptr, nullptr, nullptr);
disconnect(_managerVehicle->rallyPointManager(), nullptr, nullptr, nullptr); disconnect(_managerVehicle->rallyPointManager(), nullptr, nullptr, nullptr);
} }
bool newOffline = false; bool newOffline = false;
if (activeVehicle == nullptr) { if (activeVehicle == nullptr) {
// Since there is no longer an active vehicle we use the offline controller vehicle as the manager vehicle // Since there is no longer an active vehicle we use the offline controller
_managerVehicle = _controllerVehicle; // vehicle as the manager vehicle
newOffline = true; _managerVehicle = _controllerVehicle;
newOffline = true;
} else {
newOffline = false;
_managerVehicle = activeVehicle;
// Update controllerVehicle to the currently connected vehicle
AppSettings *appSettings =
qgcApp()->toolbox()->settingsManager()->appSettings();
appSettings->offlineEditingFirmwareClass()->setRawValue(
QGCMAVLink::firmwareClass(_managerVehicle->firmwareType()));
appSettings->offlineEditingVehicleClass()->setRawValue(
QGCMAVLink::vehicleClass(_managerVehicle->vehicleType()));
// We use these signals to sequence upload and download to the multiple
// controller/managers
connect(_managerVehicle->missionManager(),
&MissionManager::newMissionItemsAvailable, this,
&PlanMasterController::_loadMissionComplete);
connect(_managerVehicle->geoFenceManager(), &GeoFenceManager::loadComplete,
this, &PlanMasterController::_loadGeoFenceComplete);
connect(_managerVehicle->rallyPointManager(),
&RallyPointManager::loadComplete, this,
&PlanMasterController::_loadRallyPointsComplete);
connect(_managerVehicle->missionManager(), &MissionManager::sendComplete,
this, &PlanMasterController::_sendMissionComplete);
connect(_managerVehicle->geoFenceManager(), &GeoFenceManager::sendComplete,
this, &PlanMasterController::_sendGeoFenceComplete);
connect(_managerVehicle->rallyPointManager(),
&RallyPointManager::sendComplete, this,
&PlanMasterController::_sendRallyPointsComplete);
}
_offline = newOffline;
emit offlineChanged(offline());
emit managerVehicleChanged(_managerVehicle);
if (_flyView) {
// We are in the Fly View
if (newOffline) {
// No active vehicle, clear mission
qCDebug(PlanMasterControllerLog)
<< "_activeVehicleChanged: Fly View - No active vehicle, clearing "
"stale plan";
removeAll();
} else { } else {
newOffline = false; // Fly view has changed to a new active vehicle, update to show correct
_managerVehicle = activeVehicle; // mission
qCDebug(PlanMasterControllerLog)
// Update controllerVehicle to the currently connected vehicle << "_activeVehicleChanged: Fly View - New active vehicle, loading "
AppSettings* appSettings = qgcApp()->toolbox()->settingsManager()->appSettings(); "new plan from manager vehicle";
appSettings->offlineEditingFirmwareClass()->setRawValue(QGCMAVLink::firmwareClass(_managerVehicle->firmwareType())); _showPlanFromManagerVehicle();
appSettings->offlineEditingVehicleClass()->setRawValue(QGCMAVLink::vehicleClass(_managerVehicle->vehicleType())); }
} else {
// We use these signals to sequence upload and download to the multiple controller/managers // We are in the Plan view.
connect(_managerVehicle->missionManager(), &MissionManager::newMissionItemsAvailable, this, &PlanMasterController::_loadMissionComplete); if (containsItems()) {
connect(_managerVehicle->geoFenceManager(), &GeoFenceManager::loadComplete, this, &PlanMasterController::_loadGeoFenceComplete); // The plan view has a stale plan in it
connect(_managerVehicle->rallyPointManager(), &RallyPointManager::loadComplete, this, &PlanMasterController::_loadRallyPointsComplete); if (dirty()) {
connect(_managerVehicle->missionManager(), &MissionManager::sendComplete, this, &PlanMasterController::_sendMissionComplete); // Plan is dirty, the user must decide what to do in all cases
connect(_managerVehicle->geoFenceManager(), &GeoFenceManager::sendComplete, this, &PlanMasterController::_sendGeoFenceComplete); qCDebug(PlanMasterControllerLog)
connect(_managerVehicle->rallyPointManager(), &RallyPointManager::sendComplete, this, &PlanMasterController::_sendRallyPointsComplete); << "_activeVehicleChanged: Plan View - Previous dirty plan exists, "
} "no new active vehicle, sending "
"promptForPlanUsageOnVehicleChange signal";
_offline = newOffline; emit promptForPlanUsageOnVehicleChange();
emit offlineChanged(offline()); } else {
emit managerVehicleChanged(_managerVehicle); // Plan is not dirty
if (_flyView) {
// We are in the Fly View
if (newOffline) { if (newOffline) {
// No active vehicle, clear mission // The active vehicle went away with no new active vehicle
qCDebug(PlanMasterControllerLog) << "_activeVehicleChanged: Fly View - No active vehicle, clearing stale plan"; qCDebug(PlanMasterControllerLog)
removeAll(); << "_activeVehicleChanged: Plan View - Previous clean plan "
"exists, no new active vehicle, clear stale plan";
removeAll();
} else { } else {
// Fly view has changed to a new active vehicle, update to show correct mission // We are transitioning from one active vehicle to another. Show the
qCDebug(PlanMasterControllerLog) << "_activeVehicleChanged: Fly View - New active vehicle, loading new plan from manager vehicle"; // plan from the new vehicle.
_showPlanFromManagerVehicle(); qCDebug(PlanMasterControllerLog)
<< "_activeVehicleChanged: Plan View - Previous clean plan "
"exists, new active vehicle, loading from new manager vehicle";
_showPlanFromManagerVehicle();
} }
}
} else { } else {
// We are in the Plan view. // There is no previous Plan in the view
if (containsItems()) { if (newOffline) {
// The plan view has a stale plan in it // Nothing special to do in this case
if (dirty()) { qCDebug(PlanMasterControllerLog)
// Plan is dirty, the user must decide what to do in all cases << "_activeVehicleChanged: Plan View - No previous plan, no longer "
qCDebug(PlanMasterControllerLog) << "_activeVehicleChanged: Plan View - Previous dirty plan exists, no new active vehicle, sending promptForPlanUsageOnVehicleChange signal"; "connected to vehicle, nothing to do";
emit promptForPlanUsageOnVehicleChange(); } else {
} else { // Just show the plan from the new vehicle
// Plan is not dirty qCDebug(PlanMasterControllerLog)
if (newOffline) { << "_activeVehicleChanged: Plan View - No previous plan, new "
// The active vehicle went away with no new active vehicle "active vehicle, loading from new manager vehicle";
qCDebug(PlanMasterControllerLog) << "_activeVehicleChanged: Plan View - Previous clean plan exists, no new active vehicle, clear stale plan"; _showPlanFromManagerVehicle();
removeAll(); }
} else { }
// We are transitioning from one active vehicle to another. Show the plan from the new vehicle. }
qCDebug(PlanMasterControllerLog) << "_activeVehicleChanged: Plan View - Previous clean plan exists, new active vehicle, loading from new manager vehicle";
_showPlanFromManagerVehicle(); // Vehicle changed so we need to signal everything
} emit containsItemsChanged(containsItems());
} emit syncInProgressChanged();
} else { emit dirtyChanged(dirty());
// There is no previous Plan in the view
if (newOffline) { _updatePlanCreatorsList();
// Nothing special to do in this case }
qCDebug(PlanMasterControllerLog) << "_activeVehicleChanged: Plan View - No previous plan, no longer connected to vehicle, nothing to do";
} else { void PlanMasterController::loadFromVehicle(void) {
// Just show the plan from the new vehicle if (_managerVehicle->vehicleLinkManager()
qCDebug(PlanMasterControllerLog) << "_activeVehicleChanged: Plan View - No previous plan, new active vehicle, loading from new manager vehicle"; ->primaryLink()
_showPlanFromManagerVehicle(); ->linkConfiguration()
} ->isHighLatency()) {
} qgcApp()->showAppMessage(
} tr("Download not supported on high latency links."));
return;
// Vehicle changed so we need to signal everything }
emit containsItemsChanged(containsItems());
emit syncInProgressChanged(); if (offline()) {
emit dirtyChanged(dirty()); qCWarning(PlanMasterControllerLog)
<< "PlanMasterController::loadFromVehicle called while offline";
_updatePlanCreatorsList(); } else if (_flyView) {
} qCWarning(PlanMasterControllerLog)
<< "PlanMasterController::loadFromVehicle called from Fly view";
void PlanMasterController::loadFromVehicle(void) } else if (syncInProgress()) {
{ qCWarning(PlanMasterControllerLog)
if (_managerVehicle->vehicleLinkManager()->primaryLink()->linkConfiguration()->isHighLatency()) { << "PlanMasterController::loadFromVehicle called while syncInProgress";
qgcApp()->showAppMessage(tr("Download not supported on high latency links.")); } else {
return; _loadGeoFence = true;
} qCDebug(PlanMasterControllerLog)
<< "PlanMasterController::loadFromVehicle calling "
if (offline()) { "_missionController.loadFromVehicle";
qCWarning(PlanMasterControllerLog) << "PlanMasterController::loadFromVehicle called while offline"; _missionController.loadFromVehicle();
} else if (_flyView) { setDirty(false);
qCWarning(PlanMasterControllerLog) << "PlanMasterController::loadFromVehicle called from Fly view"; }
} else if (syncInProgress()) { }
qCWarning(PlanMasterControllerLog) << "PlanMasterController::loadFromVehicle called while syncInProgress";
void PlanMasterController::_loadMissionComplete(void) {
if (!_flyView && _loadGeoFence) {
_loadGeoFence = false;
_loadRallyPoints = true;
if (_geoFenceController.supported()) {
qCDebug(PlanMasterControllerLog)
<< "PlanMasterController::_loadMissionComplete calling "
"_geoFenceController.loadFromVehicle";
_geoFenceController.loadFromVehicle();
} else { } else {
_loadGeoFence = true; qCDebug(PlanMasterControllerLog)
qCDebug(PlanMasterControllerLog) << "PlanMasterController::loadFromVehicle calling _missionController.loadFromVehicle"; << "PlanMasterController::_loadMissionComplete GeoFence not "
_missionController.loadFromVehicle(); "supported skipping";
setDirty(false); _geoFenceController.removeAll();
} _loadGeoFenceComplete();
} }
setDirty(false);
}
void PlanMasterController::_loadMissionComplete(void) }
{
if (!_flyView && _loadGeoFence) { void PlanMasterController::_loadGeoFenceComplete(void) {
_loadGeoFence = false; if (!_flyView && _loadRallyPoints) {
_loadRallyPoints = true; _loadRallyPoints = false;
if (_geoFenceController.supported()) { if (_rallyPointController.supported()) {
qCDebug(PlanMasterControllerLog) << "PlanMasterController::_loadMissionComplete calling _geoFenceController.loadFromVehicle"; qCDebug(PlanMasterControllerLog)
_geoFenceController.loadFromVehicle(); << "PlanMasterController::_loadGeoFenceComplete calling "
} else { "_rallyPointController.loadFromVehicle";
qCDebug(PlanMasterControllerLog) << "PlanMasterController::_loadMissionComplete GeoFence not supported skipping"; _rallyPointController.loadFromVehicle();
_geoFenceController.removeAll(); } else {
_loadGeoFenceComplete(); qCDebug(PlanMasterControllerLog)
} << "PlanMasterController::_loadMissionComplete Rally Points not "
setDirty(false); "supported skipping";
} _rallyPointController.removeAll();
} _loadRallyPointsComplete();
void PlanMasterController::_loadGeoFenceComplete(void)
{
if (!_flyView && _loadRallyPoints) {
_loadRallyPoints = false;
if (_rallyPointController.supported()) {
qCDebug(PlanMasterControllerLog) << "PlanMasterController::_loadGeoFenceComplete calling _rallyPointController.loadFromVehicle";
_rallyPointController.loadFromVehicle();
} else {
qCDebug(PlanMasterControllerLog) << "PlanMasterController::_loadMissionComplete Rally Points not supported skipping";
_rallyPointController.removeAll();
_loadRallyPointsComplete();
}
setDirty(false);
} }
setDirty(false);
}
} }
void PlanMasterController::_loadRallyPointsComplete(void) void PlanMasterController::_loadRallyPointsComplete(void) {
{ qCDebug(PlanMasterControllerLog)
qCDebug(PlanMasterControllerLog) << "PlanMasterController::_loadRallyPointsComplete"; << "PlanMasterController::_loadRallyPointsComplete";
} }
void PlanMasterController::_sendMissionComplete(void) void PlanMasterController::_sendMissionComplete(void) {
{ if (_sendGeoFence) {
if (_sendGeoFence) { _sendGeoFence = false;
_sendGeoFence = false; _sendRallyPoints = true;
_sendRallyPoints = true; if (_geoFenceController.supported()) {
if (_geoFenceController.supported()) { qCDebug(PlanMasterControllerLog)
qCDebug(PlanMasterControllerLog) << "PlanMasterController::sendToVehicle start GeoFence sendToVehicle"; << "PlanMasterController::sendToVehicle start GeoFence sendToVehicle";
_geoFenceController.sendToVehicle(); _geoFenceController.sendToVehicle();
} else { } else {
qCDebug(PlanMasterControllerLog) << "PlanMasterController::sendToVehicle GeoFence not supported skipping"; qCDebug(PlanMasterControllerLog) << "PlanMasterController::sendToVehicle "
_sendGeoFenceComplete(); "GeoFence not supported skipping";
} _sendGeoFenceComplete();
setDirty(false);
} }
setDirty(false);
}
} }
void PlanMasterController::_sendGeoFenceComplete(void) void PlanMasterController::_sendGeoFenceComplete(void) {
{ if (_sendRallyPoints) {
if (_sendRallyPoints) { _sendRallyPoints = false;
_sendRallyPoints = false; if (_rallyPointController.supported()) {
if (_rallyPointController.supported()) { qCDebug(PlanMasterControllerLog)
qCDebug(PlanMasterControllerLog) << "PlanMasterController::sendToVehicle start rally sendToVehicle"; << "PlanMasterController::sendToVehicle start rally sendToVehicle";
_rallyPointController.sendToVehicle(); _rallyPointController.sendToVehicle();
} else { } else {
qCDebug(PlanMasterControllerLog) << "PlanMasterController::sendToVehicle Rally Points not support skipping"; qCDebug(PlanMasterControllerLog) << "PlanMasterController::sendToVehicle "
_sendRallyPointsComplete(); "Rally Points not support skipping";
} _sendRallyPointsComplete();
} }
}
} }
void PlanMasterController::_sendRallyPointsComplete(void) void PlanMasterController::_sendRallyPointsComplete(void) {
{ qCDebug(PlanMasterControllerLog)
qCDebug(PlanMasterControllerLog) << "PlanMasterController::sendToVehicle Rally Point send complete"; << "PlanMasterController::sendToVehicle Rally Point send complete";
if (_deleteWhenSendCompleted) { if (_deleteWhenSendCompleted) {
this->deleteLater(); this->deleteLater();
} }
} }
#if defined(QGC_AIRMAP_ENABLED) #if defined(QGC_AIRMAP_ENABLED)
void PlanMasterController::_startFlightPlanning(void) { void PlanMasterController::_startFlightPlanning(void) {
if (qgcApp()->toolbox()->airspaceManager()->connected()) { if (qgcApp()->toolbox()->airspaceManager()->connected()) {
qCDebug(PlanMasterControllerLog) << "PlanMasterController::_startFlightPlanning client connected, start flight planning"; qCDebug(PlanMasterControllerLog)
qgcApp()->toolbox()->airspaceManager()->flightPlan()->startFlightPlanning(this); << "PlanMasterController::_startFlightPlanning client connected, start "
} "flight planning";
qgcApp()->toolbox()->airspaceManager()->flightPlan()->startFlightPlanning(
this);
}
} }
#endif #endif
void PlanMasterController::sendToVehicle(void) void PlanMasterController::sendToVehicle(void) {
{ if (_managerVehicle->vehicleLinkManager()
if (_managerVehicle->vehicleLinkManager()->primaryLink()->linkConfiguration()->isHighLatency()) { ->primaryLink()
qgcApp()->showAppMessage(tr("Upload not supported on high latency links.")); ->linkConfiguration()
return; ->isHighLatency()) {
} qgcApp()->showAppMessage(tr("Upload not supported on high latency links."));
return;
if (offline()) { }
qCWarning(PlanMasterControllerLog) << "PlanMasterController::sendToVehicle called while offline";
} else if (syncInProgress()) { if (offline()) {
qCWarning(PlanMasterControllerLog) << "PlanMasterController::sendToVehicle called while syncInProgress"; qCWarning(PlanMasterControllerLog)
<< "PlanMasterController::sendToVehicle called while offline";
} else if (syncInProgress()) {
qCWarning(PlanMasterControllerLog)
<< "PlanMasterController::sendToVehicle called while syncInProgress";
} else {
qCDebug(PlanMasterControllerLog)
<< "PlanMasterController::sendToVehicle start mission sendToVehicle";
_sendGeoFence = true;
_missionController.sendToVehicle();
setDirty(false);
}
}
void PlanMasterController::loadFromFile(const QString &filename) {
QString errorString;
QString errorMessage =
tr("Error loading Plan file (%1). %2").arg(filename).arg("%1");
if (filename.isEmpty()) {
return;
}
QFileInfo fileInfo(filename);
QFile file(filename);
if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) {
errorString = file.errorString() + QStringLiteral(" ") + filename;
qgcApp()->showAppMessage(errorMessage.arg(errorString));
return;
}
bool success = false;
if (fileInfo.suffix() == AppSettings::planFileExtension) {
QJsonDocument jsonDoc;
QByteArray bytes = file.readAll();
if (!JsonHelper::isJsonFile(bytes, jsonDoc, errorString)) {
qgcApp()->showAppMessage(errorMessage.arg(errorString));
return;
}
QJsonObject json = jsonDoc.object();
//-- Allow plugins to pre process the load
qgcApp()->toolbox()->corePlugin()->preLoadFromJson(this, json);
int version;
if (!JsonHelper::validateExternalQGCJsonFile(
json, kPlanFileType, kPlanFileVersion, kPlanFileVersion, version,
errorString)) {
qgcApp()->showAppMessage(errorMessage.arg(errorString));
return;
}
QList<JsonHelper::KeyValidateInfo> rgKeyInfo = {
{kJsonMissionObjectKey, QJsonValue::Object, true},
{kJsonGeoFenceObjectKey, QJsonValue::Object, true},
{kJsonRallyPointsObjectKey, QJsonValue::Object, true},
};
if (!JsonHelper::validateKeys(json, rgKeyInfo, errorString)) {
qgcApp()->showAppMessage(errorMessage.arg(errorString));
return;
}
if (!_missionController.load(json[kJsonMissionObjectKey].toObject(),
errorString) ||
!_geoFenceController.load(json[kJsonGeoFenceObjectKey].toObject(),
errorString) ||
!_rallyPointController.load(json[kJsonRallyPointsObjectKey].toObject(),
errorString)) {
qgcApp()->showAppMessage(errorMessage.arg(errorString));
} else { } else {
qCDebug(PlanMasterControllerLog) << "PlanMasterController::sendToVehicle start mission sendToVehicle"; //-- Allow plugins to post process the load
_sendGeoFence = true; qgcApp()->toolbox()->corePlugin()->postLoadFromJson(this, json);
_missionController.sendToVehicle(); success = true;
setDirty(false);
}
}
void PlanMasterController::loadFromFile(const QString& filename)
{
QString errorString;
QString errorMessage = tr("Error loading Plan file (%1). %2").arg(filename).arg("%1");
if (filename.isEmpty()) {
return;
} }
} else if (fileInfo.suffix() == AppSettings::missionFileExtension) {
QFileInfo fileInfo(filename); if (!_missionController.loadJsonFile(file, errorString)) {
QFile file(filename); qgcApp()->showAppMessage(errorMessage.arg(errorString));
if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) {
errorString = file.errorString() + QStringLiteral(" ") + filename;
qgcApp()->showAppMessage(errorMessage.arg(errorString));
return;
}
bool success = false;
if(fileInfo.suffix() == AppSettings::planFileExtension) {
QJsonDocument jsonDoc;
QByteArray bytes = file.readAll();
if (!JsonHelper::isJsonFile(bytes, jsonDoc, errorString)) {
qgcApp()->showAppMessage(errorMessage.arg(errorString));
return;
}
QJsonObject json = jsonDoc.object();
//-- Allow plugins to pre process the load
qgcApp()->toolbox()->corePlugin()->preLoadFromJson(this, json);
int version;
if (!JsonHelper::validateExternalQGCJsonFile(json, kPlanFileType, kPlanFileVersion, kPlanFileVersion, version, errorString)) {
qgcApp()->showAppMessage(errorMessage.arg(errorString));
return;
}
QList<JsonHelper::KeyValidateInfo> rgKeyInfo = {
{ kJsonMissionObjectKey, QJsonValue::Object, true },
{ kJsonGeoFenceObjectKey, QJsonValue::Object, true },
{ kJsonRallyPointsObjectKey, QJsonValue::Object, true },
};
if (!JsonHelper::validateKeys(json, rgKeyInfo, errorString)) {
qgcApp()->showAppMessage(errorMessage.arg(errorString));
return;
}
if (!_missionController.load(json[kJsonMissionObjectKey].toObject(), errorString) ||
!_geoFenceController.load(json[kJsonGeoFenceObjectKey].toObject(), errorString) ||
!_rallyPointController.load(json[kJsonRallyPointsObjectKey].toObject(), errorString)) {
qgcApp()->showAppMessage(errorMessage.arg(errorString));
} else {
//-- Allow plugins to post process the load
qgcApp()->toolbox()->corePlugin()->postLoadFromJson(this, json);
success = true;
}
} else if (fileInfo.suffix() == AppSettings::missionFileExtension) {
if (!_missionController.loadJsonFile(file, errorString)) {
qgcApp()->showAppMessage(errorMessage.arg(errorString));
} else {
success = true;
}
} else if (fileInfo.suffix() == AppSettings::waypointsFileExtension || fileInfo.suffix() == QStringLiteral("txt")) {
if (!_missionController.loadTextFile(file, errorString)) {
qgcApp()->showAppMessage(errorMessage.arg(errorString));
} else {
success = true;
}
} else { } else {
//-- TODO: What then? success = true;
} }
} else if (fileInfo.suffix() == AppSettings::waypointsFileExtension ||
if(success){ fileInfo.suffix() == QStringLiteral("txt")) {
_currentPlanFile = QString::asprintf("%s/%s.%s", fileInfo.path().toLocal8Bit().data(), fileInfo.completeBaseName().toLocal8Bit().data(), AppSettings::planFileExtension); if (!_missionController.loadTextFile(file, errorString)) {
qgcApp()->showAppMessage(errorMessage.arg(errorString));
} else { } else {
_currentPlanFile.clear(); success = true;
} }
} else {
//-- TODO: What then?
}
if (success) {
_currentPlanFile =
QString::asprintf("%s/%s.%s", fileInfo.path().toLocal8Bit().data(),
fileInfo.completeBaseName().toLocal8Bit().data(),
AppSettings::planFileExtension);
} else {
_currentPlanFile.clear();
}
emit currentPlanFileChanged();
if (!offline()) {
setDirty(true);
}
}
QJsonDocument PlanMasterController::saveToJson() {
QJsonObject planJson;
qgcApp()->toolbox()->corePlugin()->preSaveToJson(this, planJson);
QJsonObject missionJson;
QJsonObject fenceJson;
QJsonObject rallyJson;
JsonHelper::saveQGCJsonFileHeader(planJson, kPlanFileType, kPlanFileVersion);
//-- Allow plugin to preemptly add its own keys to mission
qgcApp()->toolbox()->corePlugin()->preSaveToMissionJson(this, missionJson);
_missionController.save(missionJson);
//-- Allow plugin to add its own keys to mission
qgcApp()->toolbox()->corePlugin()->postSaveToMissionJson(this, missionJson);
_geoFenceController.save(fenceJson);
_rallyPointController.save(rallyJson);
planJson[kJsonMissionObjectKey] = missionJson;
planJson[kJsonGeoFenceObjectKey] = fenceJson;
planJson[kJsonRallyPointsObjectKey] = rallyJson;
qgcApp()->toolbox()->corePlugin()->postSaveToJson(this, planJson);
return QJsonDocument(planJson);
}
void PlanMasterController::saveToCurrent() {
if (!_currentPlanFile.isEmpty()) {
saveToFile(_currentPlanFile);
}
}
void PlanMasterController::saveToFile(const QString &filename) {
if (filename.isEmpty()) {
return;
}
QString planFilename = filename;
if (!QFileInfo(filename).fileName().contains(".")) {
planFilename += QString(".%1").arg(fileExtension());
}
QFile file(planFilename);
if (!file.open(QIODevice::WriteOnly | QIODevice::Text)) {
qgcApp()->showAppMessage(
tr("Plan save error %1 : %2").arg(filename).arg(file.errorString()));
_currentPlanFile.clear();
emit currentPlanFileChanged(); emit currentPlanFileChanged();
} else {
if (!offline()) { QJsonDocument saveDoc = saveToJson();
setDirty(true); file.write(saveDoc.toJson());
} if (_currentPlanFile != planFilename) {
} _currentPlanFile = planFilename;
emit currentPlanFileChanged();
QJsonDocument PlanMasterController::saveToJson() }
{ }
QJsonObject planJson;
qgcApp()->toolbox()->corePlugin()->preSaveToJson(this, planJson); // Only clear dirty bit if we are offline
QJsonObject missionJson; if (offline()) {
QJsonObject fenceJson; setDirty(false);
QJsonObject rallyJson; }
JsonHelper::saveQGCJsonFileHeader(planJson, kPlanFileType, kPlanFileVersion); }
//-- Allow plugin to preemptly add its own keys to mission
qgcApp()->toolbox()->corePlugin()->preSaveToMissionJson(this, missionJson); void PlanMasterController::saveToKml(const QString &filename) {
_missionController.save(missionJson); if (filename.isEmpty()) {
//-- Allow plugin to add its own keys to mission return;
qgcApp()->toolbox()->corePlugin()->postSaveToMissionJson(this, missionJson); }
_geoFenceController.save(fenceJson);
_rallyPointController.save(rallyJson); QString kmlFilename = filename;
planJson[kJsonMissionObjectKey] = missionJson; if (!QFileInfo(filename).fileName().contains(".")) {
planJson[kJsonGeoFenceObjectKey] = fenceJson; kmlFilename += QString(".%1").arg(kmlFileExtension());
planJson[kJsonRallyPointsObjectKey] = rallyJson; }
qgcApp()->toolbox()->corePlugin()->postSaveToJson(this, planJson);
return QJsonDocument(planJson); QFile file(kmlFilename);
}
if (!file.open(QIODevice::WriteOnly | QIODevice::Text)) {
void qgcApp()->showAppMessage(
PlanMasterController::saveToCurrent() tr("KML save error %1 : %2").arg(filename).arg(file.errorString()));
{ } else {
if(!_currentPlanFile.isEmpty()) { KMLPlanDomDocument planKML;
saveToFile(_currentPlanFile); _missionController.addMissionToKML(planKML);
} QTextStream stream(&file);
} stream << planKML.toString();
file.close();
void PlanMasterController::saveToFile(const QString& filename) }
{ }
if (filename.isEmpty()) {
return; void PlanMasterController::removeAll(void) {
} _missionController.removeAll();
_geoFenceController.removeAll();
QString planFilename = filename; _rallyPointController.removeAll();
if (!QFileInfo(filename).fileName().contains(".")) { if (_offline) {
planFilename += QString(".%1").arg(fileExtension()); _missionController.setDirty(false);
} _geoFenceController.setDirty(false);
_rallyPointController.setDirty(false);
QFile file(planFilename); _currentPlanFile.clear();
emit currentPlanFileChanged();
if (!file.open(QIODevice::WriteOnly | QIODevice::Text)) { }
qgcApp()->showAppMessage(tr("Plan save error %1 : %2").arg(filename).arg(file.errorString()));
_currentPlanFile.clear();
emit currentPlanFileChanged();
} else {
QJsonDocument saveDoc = saveToJson();
file.write(saveDoc.toJson());
if(_currentPlanFile != planFilename) {
_currentPlanFile = planFilename;
emit currentPlanFileChanged();
}
}
// Only clear dirty bit if we are offline
if (offline()) {
setDirty(false);
}
}
void PlanMasterController::saveToKml(const QString& filename)
{
if (filename.isEmpty()) {
return;
}
QString kmlFilename = filename;
if (!QFileInfo(filename).fileName().contains(".")) {
kmlFilename += QString(".%1").arg(kmlFileExtension());
}
QFile file(kmlFilename);
if (!file.open(QIODevice::WriteOnly | QIODevice::Text)) {
qgcApp()->showAppMessage(tr("KML save error %1 : %2").arg(filename).arg(file.errorString()));
} else {
KMLPlanDomDocument planKML;
_missionController.addMissionToKML(planKML);
QTextStream stream(&file);
stream << planKML.toString();
file.close();
}
} }
void PlanMasterController::removeAll(void) void PlanMasterController::removeAllFromVehicle(void) {
{ if (!offline()) {
_missionController.removeAll(); _missionController.removeAllFromVehicle();
_geoFenceController.removeAll(); if (_geoFenceController.supported()) {
_rallyPointController.removeAll(); _geoFenceController.removeAllFromVehicle();
if (_offline) {
_missionController.setDirty(false);
_geoFenceController.setDirty(false);
_rallyPointController.setDirty(false);
_currentPlanFile.clear();
emit currentPlanFileChanged();
} }
} if (_rallyPointController.supported()) {
_rallyPointController.removeAllFromVehicle();
void PlanMasterController::removeAllFromVehicle(void)
{
if (!offline()) {
_missionController.removeAllFromVehicle();
if (_geoFenceController.supported()) {
_geoFenceController.removeAllFromVehicle();
}
if (_rallyPointController.supported()) {
_rallyPointController.removeAllFromVehicle();
}
setDirty(false);
} else {
qWarning() << "PlanMasterController::removeAllFromVehicle called while offline";
} }
setDirty(false);
} else {
qWarning()
<< "PlanMasterController::removeAllFromVehicle called while offline";
}
} }
bool PlanMasterController::containsItems(void) const bool PlanMasterController::containsItems(void) const {
{ return _missionController.containsItems() ||
return _missionController.containsItems() || _geoFenceController.containsItems() || _rallyPointController.containsItems(); _geoFenceController.containsItems() ||
_rallyPointController.containsItems();
} }
bool PlanMasterController::dirty(void) const bool PlanMasterController::dirty(void) const {
{ return _missionController.dirty() || _geoFenceController.dirty() ||
return _missionController.dirty() || _geoFenceController.dirty() || _rallyPointController.dirty(); _rallyPointController.dirty();
} }
void PlanMasterController::setDirty(bool dirty) void PlanMasterController::setDirty(bool dirty) {
{ _missionController.setDirty(dirty);
_missionController.setDirty(dirty); _geoFenceController.setDirty(dirty);
_geoFenceController.setDirty(dirty); _rallyPointController.setDirty(dirty);
_rallyPointController.setDirty(dirty);
} }
QString PlanMasterController::fileExtension(void) const QString PlanMasterController::fileExtension(void) const {
{ return AppSettings::planFileExtension;
return AppSettings::planFileExtension;
} }
QString PlanMasterController::kmlFileExtension(void) const QString PlanMasterController::kmlFileExtension(void) const {
{ return AppSettings::kmlFileExtension;
return AppSettings::kmlFileExtension;
} }
QStringList PlanMasterController::loadNameFilters(void) const QStringList PlanMasterController::loadNameFilters(void) const {
{ QStringList filters;
QStringList filters;
filters << tr("Supported types (*.%1 *.%2 *.%3 *.%4)").arg(AppSettings::planFileExtension).arg(AppSettings::missionFileExtension).arg(AppSettings::waypointsFileExtension).arg("txt") << filters << tr("Supported types (*.%1 *.%2 *.%3 *.%4)")
tr("All Files (*.*)"); .arg(AppSettings::planFileExtension)
return filters; .arg(AppSettings::missionFileExtension)
.arg(AppSettings::waypointsFileExtension)
.arg("txt")
<< tr("All Files (*.*)");
return filters;
} }
QStringList PlanMasterController::saveNameFilters(void) const {
QStringList filters;
QStringList PlanMasterController::saveNameFilters(void) const filters << tr("Plan Files (*.%1)").arg(fileExtension())
{ << tr("All Files (*.*)");
QStringList filters; return filters;
filters << tr("Plan Files (*.%1)").arg(fileExtension()) << tr("All Files (*.*)");
return filters;
} }
void PlanMasterController::sendPlanToVehicle(Vehicle* vehicle, const QString& filename) void PlanMasterController::sendPlanToVehicle(Vehicle *vehicle,
{ const QString &filename) {
// Use a transient PlanMasterController to accomplish this // Use a transient PlanMasterController to accomplish this
PlanMasterController* controller = new PlanMasterController(); PlanMasterController *controller = new PlanMasterController();
controller->startStaticActiveVehicle(vehicle, true /* deleteWhenSendCompleted */); controller->startStaticActiveVehicle(vehicle,
controller->loadFromFile(filename); true /* deleteWhenSendCompleted */);
controller->sendToVehicle(); controller->loadFromFile(filename);
controller->sendToVehicle();
} }
void PlanMasterController::_showPlanFromManagerVehicle(void) void PlanMasterController::_showPlanFromManagerVehicle(void) {
{ if (!_managerVehicle->initialPlanRequestComplete() && !syncInProgress()) {
if (!_managerVehicle->initialPlanRequestComplete() && !syncInProgress()) { // Something went wrong with initial load. All controllers are idle, so just
// Something went wrong with initial load. All controllers are idle, so just force it off // force it off
_managerVehicle->forceInitialPlanRequestComplete(); _managerVehicle->forceInitialPlanRequestComplete();
} }
// The crazy if structure is to handle the load propagating by itself through the system // The crazy if structure is to handle the load propagating by itself through
if (!_missionController.showPlanFromManagerVehicle()) { // the system
if (!_geoFenceController.showPlanFromManagerVehicle()) { if (!_missionController.showPlanFromManagerVehicle()) {
_rallyPointController.showPlanFromManagerVehicle(); if (!_geoFenceController.showPlanFromManagerVehicle()) {
} _rallyPointController.showPlanFromManagerVehicle();
} }
}
} }
bool PlanMasterController::syncInProgress(void) const bool PlanMasterController::syncInProgress(void) const {
{ return _missionController.syncInProgress() ||
return _missionController.syncInProgress() || _geoFenceController.syncInProgress() ||
_geoFenceController.syncInProgress() || _rallyPointController.syncInProgress();
_rallyPointController.syncInProgress();
} }
bool PlanMasterController::isEmpty(void) const bool PlanMasterController::isEmpty(void) const {
{ return _missionController.isEmpty() && _geoFenceController.isEmpty() &&
return _missionController.isEmpty() && _rallyPointController.isEmpty();
_geoFenceController.isEmpty() &&
_rallyPointController.isEmpty();
} }
void PlanMasterController::_updatePlanCreatorsList(void) void PlanMasterController::_updatePlanCreatorsList(void) {
{ if (!_flyView) {
if (!_flyView) { if (!_planCreators) {
if (!_planCreators) { _planCreators = new QmlObjectListModel(this);
_planCreators = new QmlObjectListModel(this); _planCreators->append(new BlankPlanCreator(this, this));
_planCreators->append(new BlankPlanCreator(this, this)); _planCreators->append(new SurveyPlanCreator(this, this));
_planCreators->append(new SurveyPlanCreator(this, this)); _planCreators->append(new CorridorScanPlanCreator(this, this));
_planCreators->append(new CorridorScanPlanCreator(this, this)); _planCreators->append(new MeasurementPlanCreator(this, this));
emit planCreatorsChanged(_planCreators); emit planCreatorsChanged(_planCreators);
}
if (_managerVehicle->fixedWing()) {
if (_planCreators->count() == 4) {
_planCreators->removeAt(_planCreators->count() - 1);
}
} else {
if (_planCreators->count() != 4) {
_planCreators->append(new StructureScanPlanCreator(this, this));
}
}
} }
}
void PlanMasterController::showPlanFromManagerVehicle(void) if (_managerVehicle->fixedWing()) {
{ if (_planCreators->count() == 5) {
if (offline()) { _planCreators->removeAt(_planCreators->count() - 1);
// There is no new vehicle so clear any previous plan }
qCDebug(PlanMasterControllerLog) << "showPlanFromManagerVehicle: Plan View - No new vehicle, clear any previous plan";
removeAll();
} else { } else {
// We have a new active vehicle, show the plan from that if (_planCreators->count() != 5) {
qCDebug(PlanMasterControllerLog) << "showPlanFromManagerVehicle: Plan View - New vehicle available, show plan from new manager vehicle"; _planCreators->append(new StructureScanPlanCreator(this, this));
_showPlanFromManagerVehicle(); }
} }
}
}
void PlanMasterController::showPlanFromManagerVehicle(void) {
if (offline()) {
// There is no new vehicle so clear any previous plan
qCDebug(PlanMasterControllerLog)
<< "showPlanFromManagerVehicle: Plan View - No new vehicle, clear any "
"previous plan";
removeAll();
} else {
// We have a new active vehicle, show the plan from that
qCDebug(PlanMasterControllerLog)
<< "showPlanFromManagerVehicle: Plan View - New vehicle available, "
"show plan from new manager vehicle";
_showPlanFromManagerVehicle();
}
} }
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