Commit 6ce56c5d authored by DonLakeFlyer's avatar DonLakeFlyer

Plan supports transition from offline<->online without losing data

parent c1a14c56
......@@ -34,13 +34,16 @@ QGC_LOGGING_CATEGORY(GeoFenceControllerLog, "GeoFenceControllerLog")
const char* GeoFenceController::_jsonFileTypeValue = "GeoFence";
const char* GeoFenceController::_jsonBreachReturnKey = "breachReturn";
GeoFenceController::GeoFenceController(QObject* parent)
: PlanElementController(parent)
GeoFenceController::GeoFenceController(PlanMasterController* masterController, QObject* parent)
: PlanElementController(masterController, parent)
, _geoFenceManager(_managerVehicle->geoFenceManager())
, _dirty(false)
, _mapPolygon(this)
{
connect(_mapPolygon.qmlPathModel(), &QmlObjectListModel::countChanged, this, &GeoFenceController::_updateContainsItems);
connect(_mapPolygon.qmlPathModel(), &QmlObjectListModel::dirtyChanged, this, &GeoFenceController::_polygonDirtyChanged);
managerVehicleChanged(_managerVehicle);
}
GeoFenceController::~GeoFenceController()
......@@ -56,14 +59,6 @@ void GeoFenceController::start(bool editMode)
_init();
}
void GeoFenceController::startStaticActiveVehicle(Vehicle* vehicle)
{
qCDebug(GeoFenceControllerLog) << "startStaticActiveVehicle";
PlanElementController::startStaticActiveVehicle(vehicle);
_init();
}
void GeoFenceController::_init(void)
{
......@@ -89,26 +84,31 @@ void GeoFenceController::_signalAll(void)
emit dirtyChanged(dirty());
}
void GeoFenceController::activeVehicleBeingRemoved(void)
void GeoFenceController::managerVehicleChanged(Vehicle* managerVehicle)
{
_activeVehicle->geoFenceManager()->disconnect(this);
_activeVehicle = NULL;
}
if (_managerVehicle) {
_geoFenceManager->disconnect(this);
_managerVehicle = NULL;
_geoFenceManager = NULL;
}
void GeoFenceController::activeVehicleSet(Vehicle* vehicle)
{
_activeVehicle = vehicle;
GeoFenceManager* geoFenceManager = _activeVehicle->geoFenceManager();
connect(geoFenceManager, &GeoFenceManager::breachReturnSupportedChanged, this, &GeoFenceController::breachReturnSupportedChanged);
connect(geoFenceManager, &GeoFenceManager::circleEnabledChanged, this, &GeoFenceController::circleEnabledChanged);
connect(geoFenceManager, &GeoFenceManager::circleRadiusFactChanged, this, &GeoFenceController::circleRadiusFactChanged);
connect(geoFenceManager, &GeoFenceManager::polygonEnabledChanged, this, &GeoFenceController::polygonEnabledChanged);
connect(geoFenceManager, &GeoFenceManager::polygonSupportedChanged, this, &GeoFenceController::polygonSupportedChanged);
connect(geoFenceManager, &GeoFenceManager::loadComplete, this, &GeoFenceController::_loadComplete);
connect(geoFenceManager, &GeoFenceManager::inProgressChanged, this, &GeoFenceController::syncInProgressChanged);
if (!geoFenceManager->inProgress()) {
_loadComplete(geoFenceManager->breachReturnPoint(), geoFenceManager->polygon());
_managerVehicle = managerVehicle;
if (!_managerVehicle) {
qWarning() << "GeoFenceController::managerVehicleChanged managerVehicle=NULL";
return;
}
_geoFenceManager = _managerVehicle->geoFenceManager();
connect(_geoFenceManager, &GeoFenceManager::breachReturnSupportedChanged, this, &GeoFenceController::breachReturnSupportedChanged);
connect(_geoFenceManager, &GeoFenceManager::circleEnabledChanged, this, &GeoFenceController::circleEnabledChanged);
connect(_geoFenceManager, &GeoFenceManager::circleRadiusFactChanged, this, &GeoFenceController::circleRadiusFactChanged);
connect(_geoFenceManager, &GeoFenceManager::polygonEnabledChanged, this, &GeoFenceController::polygonEnabledChanged);
connect(_geoFenceManager, &GeoFenceManager::polygonSupportedChanged, this, &GeoFenceController::polygonSupportedChanged);
connect(_geoFenceManager, &GeoFenceManager::loadComplete, this, &GeoFenceController::_loadComplete);
connect(_geoFenceManager, &GeoFenceManager::inProgressChanged, this, &GeoFenceController::syncInProgressChanged);
if (!_geoFenceManager->inProgress()) {
_loadComplete(_geoFenceManager->breachReturnPoint(), _geoFenceManager->polygon());
}
_signalAll();
......@@ -158,27 +158,23 @@ void GeoFenceController::removeAll(void)
void GeoFenceController::loadFromVehicle(void)
{
if (_activeVehicle->parameterManager()->parametersReady() && !syncInProgress()) {
_activeVehicle->geoFenceManager()->loadFromVehicle();
if (!syncInProgress()) {
_geoFenceManager->loadFromVehicle();
} else {
qCWarning(GeoFenceControllerLog) << "GeoFenceController::loadFromVehicle call at wrong time" << _activeVehicle->parameterManager()->parametersReady() << syncInProgress();
qCWarning(GeoFenceControllerLog) << "GeoFenceController::loadFromVehicle call while syncInProgress";
}
}
void GeoFenceController::sendToVehicle(void)
{
if (_activeVehicle->parameterManager()->parametersReady() && !syncInProgress()) {
_activeVehicle->geoFenceManager()->sendToVehicle(_breachReturnPoint, _mapPolygon.pathModel());
_mapPolygon.setDirty(false);
setDirty(false);
} else {
qCWarning(GeoFenceControllerLog) << "GeoFenceController::loadFromVehicle call at wrong time" << _activeVehicle->parameterManager()->parametersReady() << syncInProgress();
}
_geoFenceManager->sendToVehicle(_breachReturnPoint, _mapPolygon.pathModel());
_mapPolygon.setDirty(false);
setDirty(false);
}
bool GeoFenceController::syncInProgress(void) const
{
return _activeVehicle->geoFenceManager()->inProgress();
return _geoFenceManager->inProgress();
}
bool GeoFenceController::dirty(void) const
......@@ -207,37 +203,37 @@ void GeoFenceController::_polygonDirtyChanged(bool dirty)
bool GeoFenceController::breachReturnSupported(void) const
{
return _activeVehicle->geoFenceManager()->breachReturnSupported();
return _geoFenceManager->breachReturnSupported();
}
bool GeoFenceController::circleEnabled(void) const
{
return _activeVehicle->geoFenceManager()->circleEnabled();
return _geoFenceManager->circleEnabled();
}
Fact* GeoFenceController::circleRadiusFact(void) const
{
return _activeVehicle->geoFenceManager()->circleRadiusFact();
return _geoFenceManager->circleRadiusFact();
}
bool GeoFenceController::polygonSupported(void) const
{
return _activeVehicle->geoFenceManager()->polygonSupported();
return _geoFenceManager->polygonSupported();
}
bool GeoFenceController::polygonEnabled(void) const
{
return _activeVehicle->geoFenceManager()->polygonEnabled();
return _geoFenceManager->polygonEnabled();
}
QVariantList GeoFenceController::params(void) const
{
return _activeVehicle->geoFenceManager()->params();
return _geoFenceManager->params();
}
QStringList GeoFenceController::paramLabels(void) const
{
return _activeVehicle->geoFenceManager()->paramLabels();
return _geoFenceManager->paramLabels();
}
void GeoFenceController::_setDirty(void)
......@@ -280,5 +276,5 @@ void GeoFenceController::_updateContainsItems(void)
void GeoFenceController::removeAllFromVehicle(void)
{
_activeVehicle->geoFenceManager()->removeAll();
_geoFenceManager->removeAll();
}
......@@ -26,7 +26,7 @@ class GeoFenceController : public PlanElementController
Q_OBJECT
public:
GeoFenceController(QObject* parent = NULL);
GeoFenceController(PlanMasterController* masterController, QObject* parent = NULL);
~GeoFenceController();
Q_PROPERTY(QGCMapPolygon* mapPolygon READ mapPolygon CONSTANT)
......@@ -45,7 +45,6 @@ public:
Q_INVOKABLE void removePolygon (void) { _mapPolygon.clear(); }
void start (bool editMode) final;
void startStaticActiveVehicle (Vehicle* vehicle) final;
void save (QJsonObject& json) final;
bool load (const QJsonObject& json, QString& errorString) final;
void loadFromVehicle (void) final;
......@@ -56,8 +55,7 @@ public:
bool dirty (void) const final;
void setDirty (bool dirty) final;
bool containsItems (void) const final;
void activeVehicleBeingRemoved (void) final;
void activeVehicleSet (Vehicle* vehicle) final;
void managerVehicleChanged (Vehicle* managerVehicle) final;
bool circleEnabled (void) const;
Fact* circleRadiusFact (void) const;
......@@ -96,9 +94,10 @@ private:
void _init(void);
void _signalAll(void);
bool _dirty;
QGCMapPolygon _mapPolygon;
QGeoCoordinate _breachReturnPoint;
GeoFenceManager* _geoFenceManager;
bool _dirty;
QGCMapPolygon _mapPolygon;
QGeoCoordinate _breachReturnPoint;
static const char* _jsonFileTypeValue;
static const char* _jsonBreachReturnKey;
......
......@@ -24,6 +24,7 @@
#include "AppSettings.h"
#include "MissionSettingsItem.h"
#include "QGCQGeoCoordinate.h"
#include "PlanMasterController.h"
#ifndef __mobile__
#include "MainWindow.h"
......@@ -48,8 +49,9 @@ const char* MissionController::_jsonMavAutopilotKey = "MAV_AUTOPILOT";
const int MissionController::_missionFileVersion = 2;
MissionController::MissionController(QObject *parent)
: PlanElementController(parent)
MissionController::MissionController(PlanMasterController* masterController, QObject *parent)
: PlanElementController(masterController, parent)
, _missionManager(_managerVehicle->missionManager())
, _visualItems(NULL)
, _settingsItem(NULL)
, _firstItemsFromVehicle(false)
......@@ -60,6 +62,7 @@ MissionController::MissionController(QObject *parent)
, _progressPct(0)
{
_resetMissionFlightStatus();
managerVehicleChanged(_managerVehicle);
}
MissionController::~MissionController()
......@@ -76,9 +79,9 @@ void MissionController::_resetMissionFlightStatus(void)
_missionFlightStatus.cruiseTime = 0.0;
_missionFlightStatus.hoverDistance = 0.0;
_missionFlightStatus.cruiseDistance = 0.0;
_missionFlightStatus.cruiseSpeed = _activeVehicle ? _activeVehicle->defaultCruiseSpeed() : std::numeric_limits<double>::quiet_NaN();
_missionFlightStatus.hoverSpeed = _activeVehicle ? _activeVehicle->defaultHoverSpeed() : std::numeric_limits<double>::quiet_NaN();
_missionFlightStatus.vehicleSpeed = _activeVehicle ? (_activeVehicle->multiRotor() || _activeVehicle->vtol() ? _missionFlightStatus.hoverSpeed : _missionFlightStatus.cruiseSpeed) : std::numeric_limits<double>::quiet_NaN();
_missionFlightStatus.cruiseSpeed = _controllerVehicle->defaultCruiseSpeed();
_missionFlightStatus.hoverSpeed = _controllerVehicle->defaultHoverSpeed();
_missionFlightStatus.vehicleSpeed = _controllerVehicle->multiRotor() || _managerVehicle->vtol() ? _missionFlightStatus.hoverSpeed : _missionFlightStatus.cruiseSpeed;
_missionFlightStatus.vehicleYaw = 0.0;
_missionFlightStatus.gimbalYaw = std::numeric_limits<double>::quiet_NaN();
......@@ -93,12 +96,10 @@ void MissionController::_resetMissionFlightStatus(void)
_missionFlightStatus.batteryChangePoint = -1;
_missionFlightStatus.batteriesRequired = -1;
if (_activeVehicle) {
_activeVehicle->firmwarePlugin()->batteryConsumptionData(_activeVehicle, _missionFlightStatus.mAhBattery, _missionFlightStatus.hoverAmps, _missionFlightStatus.cruiseAmps);
if (_missionFlightStatus.mAhBattery != 0) {
double batteryPercentRemainingAnnounce = qgcApp()->toolbox()->settingsManager()->appSettings()->batteryPercentRemainingAnnounce()->rawValue().toDouble();
_missionFlightStatus.ampMinutesAvailable = (double)_missionFlightStatus.mAhBattery / 1000.0 * 60.0 * ((100.0 - batteryPercentRemainingAnnounce) / 100.0);
}
_controllerVehicle->firmwarePlugin()->batteryConsumptionData(_controllerVehicle, _missionFlightStatus.mAhBattery, _missionFlightStatus.hoverAmps, _missionFlightStatus.cruiseAmps);
if (_missionFlightStatus.mAhBattery != 0) {
double batteryPercentRemainingAnnounce = qgcApp()->toolbox()->settingsManager()->appSettings()->batteryPercentRemainingAnnounce()->rawValue().toDouble();
_missionFlightStatus.ampMinutesAvailable = (double)_missionFlightStatus.mAhBattery / 1000.0 * 60.0 * ((100.0 - batteryPercentRemainingAnnounce) / 100.0);
}
emit missionDistanceChanged(_missionFlightStatus.totalDistance);
......@@ -121,19 +122,11 @@ void MissionController::start(bool editMode)
_init();
}
void MissionController::startStaticActiveVehicle(Vehicle *vehicle)
{
qCDebug(MissionControllerLog) << "startStaticActiveVehicle";
PlanElementController::startStaticActiveVehicle(vehicle);
_init();
}
void MissionController::_init(void)
{
// We start with an empty mission
_visualItems = new QmlObjectListModel(this);
_addMissionSettings(_activeVehicle, _visualItems, false /* addToCenter */);
_addMissionSettings(_controllerVehicle, _visualItems, false /* addToCenter */);
_initAllVisualItems();
}
......@@ -151,13 +144,13 @@ void MissionController::_newMissionItemsAvailableFromVehicle(bool removeAllReque
// - Remove all way requested from Fly view (clear mission on flight end)
QmlObjectListModel* newControllerMissionItems = new QmlObjectListModel(this);
const QList<MissionItem*>& newMissionItems = _activeVehicle->missionManager()->missionItems();
const QList<MissionItem*>& newMissionItems = _missionManager->missionItems();
qCDebug(MissionControllerLog) << "loading from vehicle: count"<< newMissionItems.count();
int i = 0;
if (_activeVehicle->firmwarePlugin()->sendHomePositionToVehicle() && newMissionItems.count() != 0) {
if (_controllerVehicle->firmwarePlugin()->sendHomePositionToVehicle() && newMissionItems.count() != 0) {
// First item is fake home position
_addMissionSettings(_activeVehicle, newControllerMissionItems, false /* addToCenter */);
_addMissionSettings(_controllerVehicle, newControllerMissionItems, false /* addToCenter */);
MissionSettingsItem* settingsItem = newControllerMissionItems->value<MissionSettingsItem*>(0);
if (!settingsItem) {
qWarning() << "First item is not settings item";
......@@ -169,7 +162,7 @@ void MissionController::_newMissionItemsAvailableFromVehicle(bool removeAllReque
for (; i<newMissionItems.count(); i++) {
const MissionItem* missionItem = newMissionItems[i];
newControllerMissionItems->append(new SimpleMissionItem(_activeVehicle, *missionItem, this));
newControllerMissionItems->append(new SimpleMissionItem(_controllerVehicle, *missionItem, this));
}
_deinitAllVisualItems();
......@@ -177,14 +170,14 @@ void MissionController::_newMissionItemsAvailableFromVehicle(bool removeAllReque
_settingsItem = NULL;
_visualItems = newControllerMissionItems;
if (!_activeVehicle->firmwarePlugin()->sendHomePositionToVehicle() || _visualItems->count() == 0) {
_addMissionSettings(_activeVehicle, _visualItems, _editMode && _visualItems->count() > 0 /* addToCenter */);
if (!_controllerVehicle->firmwarePlugin()->sendHomePositionToVehicle() || _visualItems->count() == 0) {
_addMissionSettings(_controllerVehicle, _visualItems, _editMode && _visualItems->count() > 0 /* addToCenter */);
}
_missionItemsRequested = false;
if (_editMode) {
MissionController::_scanForAdditionalSettings(_visualItems, _activeVehicle);
MissionController::_scanForAdditionalSettings(_visualItems, _controllerVehicle);
}
_initAllVisualItems();
......@@ -194,17 +187,13 @@ void MissionController::_newMissionItemsAvailableFromVehicle(bool removeAllReque
void MissionController::loadFromVehicle(void)
{
Vehicle* activeVehicle = qgcApp()->toolbox()->multiVehicleManager()->activeVehicle();
if (activeVehicle) {
_missionItemsRequested = true;
activeVehicle->missionManager()->requestMissionItems();
}
_missionItemsRequested = true;
_managerVehicle->missionManager()->requestMissionItems();
}
void MissionController::sendToVehicle(void)
{
sendItemsToVehicle(_activeVehicle, _visualItems);
sendItemsToVehicle(_managerVehicle, _visualItems);
setDirty(false);
}
......@@ -266,13 +255,13 @@ int MissionController::_nextSequenceNumber(void)
int MissionController::insertSimpleMissionItem(QGeoCoordinate coordinate, int i)
{
int sequenceNumber = _nextSequenceNumber();
SimpleMissionItem * newItem = new SimpleMissionItem(_activeVehicle, this);
SimpleMissionItem * newItem = new SimpleMissionItem(_controllerVehicle, this);
newItem->setSequenceNumber(sequenceNumber);
newItem->setCoordinate(coordinate);
newItem->setCommand(MavlinkQmlSingleton::MAV_CMD_NAV_WAYPOINT);
_initVisualItem(newItem);
if (_visualItems->count() == 1) {
newItem->setCommand(_activeVehicle->vtol() ? MavlinkQmlSingleton::MAV_CMD_NAV_VTOL_TAKEOFF : MavlinkQmlSingleton::MAV_CMD_NAV_TAKEOFF);
newItem->setCommand(_controllerVehicle->vtol() ? MavlinkQmlSingleton::MAV_CMD_NAV_VTOL_TAKEOFF : MavlinkQmlSingleton::MAV_CMD_NAV_TAKEOFF);
}
newItem->setDefaultsForCommand();
if ((MAV_CMD)newItem->command() == MAV_CMD_NAV_WAYPOINT) {
......@@ -297,10 +286,10 @@ int MissionController::insertComplexMissionItem(QString itemName, QGeoCoordinate
int sequenceNumber = _nextSequenceNumber();
if (itemName == _surveyMissionItemName) {
newItem = new SurveyMissionItem(_activeVehicle, _visualItems);
newItem = new SurveyMissionItem(_controllerVehicle, _visualItems);
newItem->setCoordinate(mapCenterCoordinate);
} else if (itemName == _fwLandingMissionItemName) {
newItem = new FixedWingLandingComplexItem(_activeVehicle, _visualItems);
newItem = new FixedWingLandingComplexItem(_controllerVehicle, _visualItems);
} else {
qWarning() << "Internal error: Unknown complex item:" << itemName;
return sequenceNumber;
......@@ -333,14 +322,14 @@ void MissionController::removeAll(void)
_visualItems->deleteLater();
_settingsItem = NULL;
_visualItems = new QmlObjectListModel(this);
_addMissionSettings(_activeVehicle, _visualItems, false /* addToCenter */);
_addMissionSettings(_controllerVehicle, _visualItems, false /* addToCenter */);
_initAllVisualItems();
setDirty(true);
_resetMissionFlightStatus();
}
}
bool MissionController::_loadJsonMissionFileV1(Vehicle* vehicle, const QJsonObject& json, QmlObjectListModel* visualItems, QString& errorString)
bool MissionController::_loadJsonMissionFileV1(const QJsonObject& json, QmlObjectListModel* visualItems, QString& errorString)
{
// Validate root object keys
QList<JsonHelper::KeyValidateInfo> rootKeyInfoList = {
......@@ -365,7 +354,7 @@ bool MissionController::_loadJsonMissionFileV1(Vehicle* vehicle, const QJsonObje
return false;
}
SurveyMissionItem* item = new SurveyMissionItem(vehicle, visualItems);
SurveyMissionItem* item = new SurveyMissionItem(_controllerVehicle, visualItems);
const QJsonObject itemObject = itemValue.toObject();
if (item->load(itemObject, itemObject["id"].toInt(), errorString)) {
surveyItems.append(item);
......@@ -408,7 +397,7 @@ bool MissionController::_loadJsonMissionFileV1(Vehicle* vehicle, const QJsonObje
}
const QJsonObject itemObject = itemValue.toObject();
SimpleMissionItem* item = new SimpleMissionItem(vehicle, visualItems);
SimpleMissionItem* item = new SimpleMissionItem(_controllerVehicle, visualItems);
if (item->load(itemObject, itemObject["id"].toInt(), errorString)) {
qCDebug(MissionControllerLog) << "Json load: adding simple item expectedSequence:actualSequence" << nextSequenceNumber << item->sequenceNumber();
nextSequenceNumber = item->lastSequenceNumber() + 1;
......@@ -420,10 +409,10 @@ bool MissionController::_loadJsonMissionFileV1(Vehicle* vehicle, const QJsonObje
} while (nextSimpleItemIndex < itemArray.count() || nextComplexItemIndex < surveyItems.count());
if (json.contains(_jsonPlannedHomePositionKey)) {
SimpleMissionItem* item = new SimpleMissionItem(vehicle, visualItems);
SimpleMissionItem* item = new SimpleMissionItem(_controllerVehicle, visualItems);
if (item->load(json[_jsonPlannedHomePositionKey].toObject(), 0, errorString)) {
MissionSettingsItem* settingsItem = new MissionSettingsItem(vehicle, visualItems);
MissionSettingsItem* settingsItem = new MissionSettingsItem(_controllerVehicle, visualItems);
settingsItem->setCoordinate(item->coordinate());
visualItems->insert(0, settingsItem);
item->deleteLater();
......@@ -431,20 +420,20 @@ bool MissionController::_loadJsonMissionFileV1(Vehicle* vehicle, const QJsonObje
return false;
}
} else {
_addMissionSettings(vehicle, visualItems, true /* addToCenter */);
_addMissionSettings(_controllerVehicle, visualItems, true /* addToCenter */);
}
return true;
}
bool MissionController::_loadJsonMissionFileV2(Vehicle* vehicle, const QJsonObject& json, QmlObjectListModel* visualItems, QString& errorString)
bool MissionController::_loadJsonMissionFileV2(const QJsonObject& json, QmlObjectListModel* visualItems, QString& errorString)
{
// Validate root object keys
QList<JsonHelper::KeyValidateInfo> rootKeyInfoList = {
{ _jsonPlannedHomePositionKey, QJsonValue::Array, true },
{ _jsonItemsKey, QJsonValue::Array, true },
{ _jsonFirmwareTypeKey, QJsonValue::Double, true },
{ _jsonVehicleTypeKey, QJsonValue::Double, false },
{ _jsonVehicleTypeKey, QJsonValue::Double, true },
{ _jsonCruiseSpeedKey, QJsonValue::Double, false },
{ _jsonHoverSpeedKey, QJsonValue::Double, false },
};
......@@ -455,14 +444,10 @@ bool MissionController::_loadJsonMissionFileV2(Vehicle* vehicle, const QJsonObje
qCDebug(MissionControllerLog) << "MissionController::_loadJsonMissionFileV2 itemCount:" << json[_jsonItemsKey].toArray().count();
// Mission Settings
QGeoCoordinate homeCoordinate;
AppSettings* appSettings = qgcApp()->toolbox()->settingsManager()->appSettings();
if (!JsonHelper::loadGeoCoordinate(json[_jsonPlannedHomePositionKey], true /* altitudeRequired */, homeCoordinate, errorString)) {
return false;
}
if (json.contains(_jsonVehicleTypeKey) && vehicle->isOfflineEditingVehicle()) {
appSettings->offlineEditingVehicleType()->setRawValue(json[_jsonVehicleTypeKey].toDouble());
}
appSettings->offlineEditingFirmwareType()->setRawValue(AppSettings::offlineEditingFirmwareTypeFromFirmwareType((MAV_AUTOPILOT)(json[_jsonVehicleTypeKey].toDouble())));
appSettings->offlineEditingVehicleType()->setRawValue(AppSettings::offlineEditingVehicleTypeFromVehicleType((MAV_TYPE)json[_jsonVehicleTypeKey].toDouble()));
if (json.contains(_jsonCruiseSpeedKey)) {
appSettings->offlineEditingCruiseSpeed()->setRawValue(json[_jsonCruiseSpeedKey].toDouble());
}
......@@ -470,7 +455,11 @@ bool MissionController::_loadJsonMissionFileV2(Vehicle* vehicle, const QJsonObje
appSettings->offlineEditingHoverSpeed()->setRawValue(json[_jsonHoverSpeedKey].toDouble());
}
MissionSettingsItem* settingsItem = new MissionSettingsItem(vehicle, visualItems);
QGeoCoordinate homeCoordinate;
if (!JsonHelper::loadGeoCoordinate(json[_jsonPlannedHomePositionKey], true /* altitudeRequired */, homeCoordinate, errorString)) {
return false;
}
MissionSettingsItem* settingsItem = new MissionSettingsItem(_controllerVehicle, visualItems);
settingsItem->setCoordinate(homeCoordinate);
visualItems->insert(0, settingsItem);
qCDebug(MissionControllerLog) << "plannedHomePosition" << homeCoordinate;
......@@ -499,7 +488,7 @@ bool MissionController::_loadJsonMissionFileV2(Vehicle* vehicle, const QJsonObje
QString itemType = itemObject[VisualMissionItem::jsonTypeKey].toString();
if (itemType == VisualMissionItem::jsonTypeSimpleItemValue) {
SimpleMissionItem* simpleItem = new SimpleMissionItem(vehicle, visualItems);
SimpleMissionItem* simpleItem = new SimpleMissionItem(_controllerVehicle, visualItems);
if (simpleItem->load(itemObject, nextSequenceNumber, errorString)) {
qCDebug(MissionControllerLog) << "Loading simple item: nextSequenceNumber:command" << nextSequenceNumber << simpleItem->command();
nextSequenceNumber = simpleItem->lastSequenceNumber() + 1;
......@@ -518,7 +507,7 @@ bool MissionController::_loadJsonMissionFileV2(Vehicle* vehicle, const QJsonObje
if (complexItemType == SurveyMissionItem::jsonComplexItemTypeValue) {
qCDebug(MissionControllerLog) << "Loading Survey: nextSequenceNumber" << nextSequenceNumber;
SurveyMissionItem* surveyItem = new SurveyMissionItem(vehicle, visualItems);
SurveyMissionItem* surveyItem = new SurveyMissionItem(_controllerVehicle, visualItems);
if (!surveyItem->load(itemObject, nextSequenceNumber++, errorString)) {
return false;
}
......@@ -527,7 +516,7 @@ bool MissionController::_loadJsonMissionFileV2(Vehicle* vehicle, const QJsonObje
visualItems->append(surveyItem);
} else if (complexItemType == FixedWingLandingComplexItem::jsonComplexItemTypeValue) {
qCDebug(MissionControllerLog) << "Loading Fixed Wing Landing Pattern: nextSequenceNumber" << nextSequenceNumber;
FixedWingLandingComplexItem* landingItem = new FixedWingLandingComplexItem(vehicle, visualItems);
FixedWingLandingComplexItem* landingItem = new FixedWingLandingComplexItem(_controllerVehicle, visualItems);
if (!landingItem->load(itemObject, nextSequenceNumber++, errorString)) {
return false;
}
......@@ -536,7 +525,7 @@ bool MissionController::_loadJsonMissionFileV2(Vehicle* vehicle, const QJsonObje
visualItems->append(landingItem);
} else if (complexItemType == MissionSettingsItem::jsonComplexItemTypeValue) {
qCDebug(MissionControllerLog) << "Loading Mission Settings: nextSequenceNumber" << nextSequenceNumber;
MissionSettingsItem* settingsItem = new MissionSettingsItem(vehicle, visualItems);
MissionSettingsItem* settingsItem = new MissionSettingsItem(_controllerVehicle, visualItems);
if (!settingsItem->load(itemObject, nextSequenceNumber++, errorString)) {
return false;
}
......@@ -596,13 +585,13 @@ bool MissionController::_loadItemsFromJson(const QJsonObject& json, QmlObjectLis
errorString);
if (fileVersion == 1) {
return _loadJsonMissionFileV1(_activeVehicle, json, visualItems, errorString);
return _loadJsonMissionFileV1(json, visualItems, errorString);
} else {
return _loadJsonMissionFileV2(_activeVehicle, json, visualItems, errorString);
return _loadJsonMissionFileV2(json, visualItems, errorString);
}
}
bool MissionController::_loadTextMissionFile(Vehicle* vehicle, QTextStream& stream, QmlObjectListModel* visualItems, QString& errorString)
bool MissionController::_loadTextMissionFile(QTextStream& stream, QmlObjectListModel* visualItems, QString& errorString)
{
bool firstItem = true;
bool plannedHomePositionInFile = false;
......@@ -625,11 +614,11 @@ bool MissionController::_loadTextMissionFile(Vehicle* vehicle, QTextStream& stre
if (versionOk) {
// Start with planned home in center
_addMissionSettings(vehicle, visualItems, true /* addToCenter */);
_addMissionSettings(_controllerVehicle, visualItems, true /* addToCenter */);
MissionSettingsItem* settingsItem = visualItems->value<MissionSettingsItem*>(0);
while (!stream.atEnd()) {
SimpleMissionItem* item = new SimpleMissionItem(vehicle, visualItems);
SimpleMissionItem* item = new SimpleMissionItem(_controllerVehicle, visualItems);
if (item->load(stream)) {
if (firstItem && plannedHomePositionInFile) {
......@@ -672,10 +661,10 @@ void MissionController::_initLoadedVisualItems(QmlObjectListModel* loadedVisualI
_visualItems = loadedVisualItems;
if (_visualItems->count() == 0) {
_addMissionSettings(_activeVehicle, _visualItems, true /* addToCenter */);
_addMissionSettings(_controllerVehicle, _visualItems, true /* addToCenter */);
}
MissionController::_scanForAdditionalSettings(_visualItems, _activeVehicle);
MissionController::_scanForAdditionalSettings(_visualItems, _controllerVehicle);
_initAllVisualItems();
}
......@@ -686,7 +675,7 @@ bool MissionController::load(const QJsonObject& json, QString& errorString)
QString errorMessage = tr("Mission: %1");
QmlObjectListModel* loadedVisualItems = new QmlObjectListModel(this);
if (!_loadJsonMissionFileV2(_activeVehicle, json, loadedVisualItems, errorStr)) {
if (!_loadJsonMissionFileV2(json, loadedVisualItems, errorStr)) {
errorString = errorMessage.arg(errorStr);
return false;
}
......@@ -727,7 +716,7 @@ bool MissionController::loadTextFile(QFile& file, QString& errorString)
QTextStream stream(bytes);
QmlObjectListModel* loadedVisualItems = new QmlObjectListModel(this);
if (!_loadTextMissionFile(_activeVehicle, stream, loadedVisualItems, errorStr)) {
if (!_loadTextMissionFile(stream, loadedVisualItems, errorStr)) {
errorString = errorMessage.arg(errorStr);
return false;
}
......@@ -751,10 +740,10 @@ void MissionController::save(QJsonObject& json)
QJsonValue coordinateValue;
JsonHelper::saveGeoCoordinate(settingsItem->coordinate(), true /* writeAltitude */, coordinateValue);
json[_jsonPlannedHomePositionKey] = coordinateValue;
json[_jsonFirmwareTypeKey] = _activeVehicle->firmwareType();
json[_jsonVehicleTypeKey] = _activeVehicle->vehicleType();
json[_jsonCruiseSpeedKey] = _activeVehicle->defaultCruiseSpeed();
json[_jsonHoverSpeedKey] = _activeVehicle->defaultHoverSpeed();
json[_jsonFirmwareTypeKey] = _controllerVehicle->firmwareType();
json[_jsonVehicleTypeKey] = _controllerVehicle->vehicleType();
json[_jsonCruiseSpeedKey] = _controllerVehicle->defaultCruiseSpeed();
json[_jsonHoverSpeedKey] = _controllerVehicle->defaultHoverSpeed();
// Save the visual items
......@@ -969,9 +958,9 @@ void MissionController::_recalcMissionFlightStatus()
// Look for speed changed
double newSpeed = item->specifiedFlightSpeed();
if (!qIsNaN(newSpeed)) {
if (_activeVehicle->multiRotor()) {
if (_controllerVehicle->multiRotor()) {
_missionFlightStatus.hoverSpeed = newSpeed;
} else if (_activeVehicle->vtol()) {
} else if (_controllerVehicle->vtol()) {
if (vtolInHover) {
_missionFlightStatus.hoverSpeed = newSpeed;
} else {
......@@ -984,7 +973,7 @@ void MissionController::_recalcMissionFlightStatus()
}
// Look for gimbal change
if (_activeVehicle->vehicleYawsToNextWaypointInMission()) {
if (_controllerVehicle->vehicleYawsToNextWaypointInMission()) {
// We current only support gimbal display in this mode
double gimbalYaw = item->specifiedGimbalYaw();
if (!qIsNaN(gimbalYaw)) {
......@@ -1005,7 +994,7 @@ void MissionController::_recalcMissionFlightStatus()
}
// Update VTOL state
if (simpleItem && _activeVehicle->vtol()) {
if (simpleItem && _controllerVehicle->vtol()) {
switch (simpleItem->command()) {
case MavlinkQmlSingleton::MAV_CMD_NAV_TAKEOFF:
vtolInHover = false;
......@@ -1069,14 +1058,14 @@ void MissionController::_recalcMissionFlightStatus()
// Calculate time/distance
double hoverTime = distance / _missionFlightStatus.hoverSpeed;
double cruiseTime = distance / _missionFlightStatus.cruiseSpeed;
if (_activeVehicle->vtol()) {
if (_controllerVehicle->vtol()) {
if (vtolInHover) {
_addHoverTime(hoverTime, distance, item->sequenceNumber());
} else {
_addCruiseTime(cruiseTime, distance, item->sequenceNumber());
}
} else {
if (_activeVehicle->multiRotor()) {
if (_controllerVehicle->multiRotor()) {
_addHoverTime(hoverTime, distance, item->sequenceNumber());
} else {
_addCruiseTime(cruiseTime, distance, item->sequenceNumber());
......@@ -1091,14 +1080,14 @@ void MissionController::_recalcMissionFlightStatus()
double hoverTime = distance / _missionFlightStatus.hoverSpeed;
double cruiseTime = distance / _missionFlightStatus.cruiseSpeed;
if (_activeVehicle->vtol()) {
if (_controllerVehicle->vtol()) {
if (vtolInHover) {
_addHoverTime(hoverTime, distance, item->sequenceNumber());
} else {
_addCruiseTime(cruiseTime, distance, item->sequenceNumber());
}
} else {
if (_activeVehicle->multiRotor()) {
if (_controllerVehicle->multiRotor()) {
_addHoverTime(hoverTime, distance, item->sequenceNumber());
} else {
_addCruiseTime(cruiseTime, distance, item->sequenceNumber());
......@@ -1222,8 +1211,8 @@ void MissionController::_initAllVisualItems(void)
_settingsItem->setIsCurrentItem(true);
}
if (!_editMode && _activeVehicle) {
_settingsItem->setCoordinate(_activeVehicle->homePosition());
if (!_editMode && _controllerVehicle) {
_settingsItem->setCoordinate(_controllerVehicle->homePosition());
}
connect(_settingsItem, &MissionSettingsItem::coordinateChanged, this, &MissionController::_recalcAll);
......@@ -1236,7 +1225,7 @@ void MissionController::_initAllVisualItems(void)
_recalcAll();
connect(_visualItems, &QmlObjectListModel::dirtyChanged, this, &MissionController::dirtyChanged);
connect(_visualItems, &QmlObjectListModel::dirtyChanged, this, &MissionController::_visualItemsDirtyChanged);
connect(_visualItems, &QmlObjectListModel::countChanged, this, &MissionController::_updateContainsItems);
emit visualItemsChanged();
......@@ -1300,65 +1289,43 @@ void MissionController::_itemCommandChanged(void)
_recalcWaypointLines();
}
void MissionController::activeVehicleBeingRemoved(void)
{
qCDebug(MissionControllerLog) << "MissionController::_activeVehicleBeingRemoved";
MissionManager* missionManager = _activeVehicle->missionManager();
disconnect(missionManager, &MissionManager::newMissionItemsAvailable, this, &MissionController::_newMissionItemsAvailableFromVehicle);
disconnect(missionManager, &MissionManager::inProgressChanged, this, &MissionController::_inProgressChanged);
disconnect(missionManager, &MissionManager::progressPct, this, &MissionController::_progressPctChanged);
disconnect(missionManager, &MissionManager::currentIndexChanged, this, &MissionController::_currentMissionIndexChanged);
disconnect(missionManager, &MissionManager::lastCurrentIndexChanged, this, &MissionController::resumeMissionIndexChanged);
disconnect(missionManager, &MissionManager::resumeMissionReady, this, &MissionController::resumeMissionReady);
disconnect(missionManager, &MissionManager::cameraFeedback, this, &MissionController::_cameraFeedback);
disconnect(_activeVehicle, &Vehicle::homePositionChanged, this, &MissionController::_activeVehicleHomePositionChanged);
// We always remove all items on vehicle change. This leaves a user model hole:
// If the user has unsaved changes in the Plan view they will lose them
removeAll();
setDirty(false);
_activeVehicle = NULL;
}
void MissionController::activeVehicleSet(Vehicle* activeVehicle)
void MissionController::managerVehicleChanged(Vehicle* managerVehicle)
{
_activeVehicle = activeVehicle;
// We always remove all items on vehicle change. This leaves a user model hole:
// If the user has unsaved changes in the Plan view they will lose them
removeAll();
setDirty(false);
if (_managerVehicle) {
_missionManager->disconnect(this);
_managerVehicle->disconnect(this);
_managerVehicle = NULL;
_missionManager = NULL;
}
MissionManager* missionManager = _activeVehicle->missionManager();
_managerVehicle = managerVehicle;
if (!_managerVehicle) {
qWarning() << "RallyPointController::managerVehicleChanged managerVehicle=NULL";
return;
}
connect(missionManager, &MissionManager::newMissionItemsAvailable, this, &MissionController::_newMissionItemsAvailableFromVehicle);
connect(missionManager, &MissionManager::inProgressChanged, this, &MissionController::_inProgressChanged);
connect(missionManager, &MissionManager::progressPct, this, &MissionController::_progressPctChanged);
connect(missionManager, &MissionManager::currentIndexChanged, this, &MissionController::_currentMissionIndexChanged);
connect(missionManager, &MissionManager::lastCurrentIndexChanged, this, &MissionController::resumeMissionIndexChanged);
connect(missionManager, &MissionManager::resumeMissionReady, this, &MissionController::resumeMissionReady);
connect(missionManager, &MissionManager::cameraFeedback, this, &MissionController::_cameraFeedback);
connect(_activeVehicle, &Vehicle::homePositionChanged, this, &MissionController::_activeVehicleHomePositionChanged);
connect(_activeVehicle, &Vehicle::defaultCruiseSpeedChanged, this, &MissionController::_recalcMissionFlightStatus);
connect(_activeVehicle, &Vehicle::defaultHoverSpeedChanged, this, &MissionController::_recalcMissionFlightStatus);
connect(_activeVehicle, &Vehicle::vehicleTypeChanged, this, &MissionController::complexMissionItemNamesChanged);
_missionManager = _managerVehicle->missionManager();
connect(_missionManager, &MissionManager::newMissionItemsAvailable, this, &MissionController::_newMissionItemsAvailableFromVehicle);
connect(_missionManager, &MissionManager::inProgressChanged, this, &MissionController::_inProgressChanged);
connect(_missionManager, &MissionManager::progressPct, this, &MissionController::_progressPctChanged);
connect(_missionManager, &MissionManager::currentIndexChanged, this, &MissionController::_currentMissionIndexChanged);
connect(_missionManager, &MissionManager::lastCurrentIndexChanged, this, &MissionController::resumeMissionIndexChanged);
connect(_missionManager, &MissionManager::resumeMissionReady, this, &MissionController::resumeMissionReady);
connect(_missionManager, &MissionManager::cameraFeedback, this, &MissionController::_cameraFeedback);
connect(_managerVehicle, &Vehicle::homePositionChanged, this, &MissionController::_managerVehicleHomePositionChanged);
connect(_managerVehicle, &Vehicle::defaultCruiseSpeedChanged, this, &MissionController::_recalcMissionFlightStatus);
connect(_managerVehicle, &Vehicle::defaultHoverSpeedChanged, this, &MissionController::_recalcMissionFlightStatus);
connect(_managerVehicle, &Vehicle::vehicleTypeChanged, this, &MissionController::complexMissionItemNamesChanged);
if (_activeVehicle->parameterManager()->parametersReady() && !syncInProgress()) {
// We are switching between two previously existing vehicles. We have to manually ask for the items from the Vehicle.
// We don't request mission items for new vehicles since that will happen autamatically.
loadFromVehicle();
if (!_masterController->offline()) {
_managerVehicleHomePositionChanged(_managerVehicle->homePosition());
}
_activeVehicleHomePositionChanged(_activeVehicle->homePosition());
emit complexMissionItemNamesChanged();
emit resumeMissionIndexChanged();
}
void MissionController::_activeVehicleHomePositionChanged(const QGeoCoordinate& homePosition)
void MissionController::_managerVehicleHomePositionChanged(const QGeoCoordinate& homePosition)
{
if (_visualItems) {
MissionSettingsItem* settingsItem = qobject_cast<MissionSettingsItem*>(_visualItems->get(0));
......@@ -1367,6 +1334,10 @@ void MissionController::_activeVehicleHomePositionChanged(const QGeoCoordinate&
} else {
qWarning() << "First item is not MissionSettingsItem";
}
if (_visualItems->count() == 1) {
// Don't let this trip the dirty bit
_visualItems->setDirty(false);
}
}
}
......@@ -1472,7 +1443,7 @@ int MissionController::resumeMissionIndex(void) const
int resumeIndex = 0;
if (!_editMode) {
resumeIndex = _activeVehicle->missionManager()->lastCurrentIndex() + (_activeVehicle->firmwarePlugin()->sendHomePositionToVehicle() ? 0 : 1);
resumeIndex = _missionManager->lastCurrentIndex() + (_controllerVehicle->firmwarePlugin()->sendHomePositionToVehicle() ? 0 : 1);
if (resumeIndex > 1 && resumeIndex != _visualItems->value<VisualMissionItem*>(_visualItems->count() - 1)->sequenceNumber()) {
// Resume at the item previous to the item we were heading towards
resumeIndex--;
......@@ -1481,14 +1452,13 @@ int MissionController::resumeMissionIndex(void) const
}
}
qDebug() << "resumeIndex" << resumeIndex;
return resumeIndex;
}
void MissionController::_currentMissionIndexChanged(int sequenceNumber)
{
if (!_editMode) {
if (!_activeVehicle->firmwarePlugin()->sendHomePositionToVehicle()) {
if (!_controllerVehicle->firmwarePlugin()->sendHomePositionToVehicle()) {
sequenceNumber++;
}
......@@ -1501,7 +1471,7 @@ void MissionController::_currentMissionIndexChanged(int sequenceNumber)
bool MissionController::syncInProgress(void) const
{
return _activeVehicle ? _activeVehicle->missionManager()->inProgress() : false;
return _missionManager->inProgress();
}
bool MissionController::dirty(void) const
......@@ -1559,7 +1529,7 @@ bool MissionController::containsItems(void) const
void MissionController::removeAllFromVehicle(void)
{
_missionItemsRequested = true;
_activeVehicle->missionManager()->removeAll();
_missionManager->removeAll();
}
QStringList MissionController::complexMissionItemNames(void) const
......@@ -1567,7 +1537,7 @@ QStringList MissionController::complexMissionItemNames(void) const
QStringList complexItems;
complexItems.append(_surveyMissionItemName);
if (_activeVehicle->fixedWing()) {
if (_controllerVehicle->fixedWing()) {
complexItems.append(_fwLandingMissionItemName);
}
......@@ -1576,10 +1546,10 @@ QStringList MissionController::complexMissionItemNames(void) const
void MissionController::resumeMission(int resumeIndex)
{
if (!_activeVehicle->firmwarePlugin()->sendHomePositionToVehicle()) {
if (!_controllerVehicle->firmwarePlugin()->sendHomePositionToVehicle()) {
resumeIndex--;
}
_activeVehicle->missionManager()->generateResumeMission(resumeIndex);
_missionManager->generateResumeMission(resumeIndex);
}
QGeoCoordinate MissionController::plannedHomePosition(void) const
......@@ -1621,3 +1591,9 @@ void MissionController::_progressPctChanged(double progressPct)
emit progressPctChanged(progressPct);
}
}
void MissionController::_visualItemsDirtyChanged(bool dirty)
{
// We could connect signal to signal and not need this but this is handy for setting a breakpoint on
emit dirtyChanged(dirty);
}
......@@ -24,17 +24,19 @@ class VisualMissionItem;
class MissionItem;
class MissionSettingsItem;
class AppSettings;
class MissionManager;
Q_DECLARE_LOGGING_CATEGORY(MissionControllerLog)
typedef QPair<VisualMissionItem*,VisualMissionItem*> VisualItemPair;
typedef QHash<VisualItemPair, CoordinateVector*> CoordVectHashTable;
class MissionController : public PlanElementController
{
Q_OBJECT
public:
MissionController(QObject* parent = NULL);
MissionController(PlanMasterController* masterController, QObject* parent = NULL);
~MissionController();
typedef struct {
......@@ -110,7 +112,6 @@ public:
// Overrides from PlanElementController
void start (bool editMode) final;
void startStaticActiveVehicle (Vehicle* vehicle) final;
void save (QJsonObject& json) final;
bool load (const QJsonObject& json, QString& errorString) final;
void loadFromVehicle (void) final;
......@@ -121,8 +122,7 @@ public:
bool dirty (void) const final;
void setDirty (bool dirty) final;
bool containsItems (void) const final;
void activeVehicleBeingRemoved (void) final;
void activeVehicleSet (Vehicle* vehicle) final;
void managerVehicleChanged (Vehicle* managerVehicle) final;
// Property accessors
......@@ -169,7 +169,7 @@ signals:
private slots:
void _newMissionItemsAvailableFromVehicle(bool removeAllRequested);
void _itemCommandChanged(void);
void _activeVehicleHomePositionChanged(const QGeoCoordinate& homePosition);
void _managerVehicleHomePositionChanged(const QGeoCoordinate& homePosition);
void _inProgressChanged(bool inProgress);
void _currentMissionIndexChanged(int sequenceNumber);
void _recalcWaypointLines(void);
......@@ -177,6 +177,7 @@ private slots:
void _updateContainsItems(void);
void _cameraFeedback(QGeoCoordinate imageCoordinate, int index);
void _progressPctChanged(double progressPct);
void _visualItemsDirtyChanged(bool dirty);
private:
void _init(void);
......@@ -194,10 +195,10 @@ private:
static double _normalizeLat(double lat);
static double _normalizeLon(double lon);
static void _addMissionSettings(Vehicle* vehicle, QmlObjectListModel* visualItems, bool addToCenter);
static bool _loadJsonMissionFile(Vehicle* vehicle, const QByteArray& bytes, QmlObjectListModel* visualItems, QString& errorString);
static bool _loadJsonMissionFileV1(Vehicle* vehicle, const QJsonObject& json, QmlObjectListModel* visualItems, QString& errorString);
static bool _loadJsonMissionFileV2(Vehicle* vehicle, const QJsonObject& json, QmlObjectListModel* visualItems, QString& errorString);
static bool _loadTextMissionFile(Vehicle* vehicle, QTextStream& stream, QmlObjectListModel* visualItems, QString& errorString);
bool _loadJsonMissionFile(const QByteArray& bytes, QmlObjectListModel* visualItems, QString& errorString);
bool _loadJsonMissionFileV1(const QJsonObject& json, QmlObjectListModel* visualItems, QString& errorString);
bool _loadJsonMissionFileV2(const QJsonObject& json, QmlObjectListModel* visualItems, QString& errorString);
bool _loadTextMissionFile(QTextStream& stream, QmlObjectListModel* visualItems, QString& errorString);
int _nextSequenceNumber(void);
static void _scanForAdditionalSettings(QmlObjectListModel* visualItems, Vehicle* vehicle);
static bool _convertToMissionItems(QmlObjectListModel* visualMissionItems, QList<MissionItem*>& rgMissionItems, QObject* missionItemParent);
......@@ -210,6 +211,7 @@ private:
void _initLoadedVisualItems(QmlObjectListModel* loadedVisualItems);
private:
MissionManager* _missionManager;
QmlObjectListModel* _visualItems;
MissionSettingsItem* _settingsItem;
QmlObjectListModel _waypointLines;
......
......@@ -13,6 +13,9 @@
#include "MultiVehicleManager.h"
#include "SimpleMissionItem.h"
#include "MissionSettingsItem.h"
#include "QGCApplication.h"
#include "SettingsManager.h"
#include "AppSettings.h"
MissionControllerTest::MissionControllerTest(void)
: _multiSpyMissionController(NULL)
......@@ -24,8 +27,8 @@ MissionControllerTest::MissionControllerTest(void)
void MissionControllerTest::cleanup(void)
{
delete _missionController;
_missionController = NULL;
delete _masterController;
_masterController = NULL;
delete _multiSpyMissionController;
_multiSpyMissionController = NULL;
......@@ -38,8 +41,6 @@ void MissionControllerTest::cleanup(void)
void MissionControllerTest::_initForFirmwareType(MAV_AUTOPILOT firmwareType)
{
bool startController = false;
MissionControllerManagerTest::_initForFirmwareType(firmwareType);
// VisualMissionItem signals
......@@ -49,19 +50,16 @@ void MissionControllerTest::_initForFirmwareType(MAV_AUTOPILOT firmwareType)
_rgMissionControllerSignals[visualItemsChangedSignalIndex] = SIGNAL(visualItemsChanged());
_rgMissionControllerSignals[waypointLinesChangedSignalIndex] = SIGNAL(waypointLinesChanged());
if (!_missionController) {
startController = true;
_missionController = new MissionController();
Q_CHECK_PTR(_missionController);
}
// Master controller pulls offline vehicle info from settings
qgcApp()->toolbox()->settingsManager()->appSettings()->offlineEditingFirmwareType()->setRawValue(firmwareType);
_masterController = new PlanMasterController(this);
_missionController = _masterController->missionController();
_multiSpyMissionController = new MultiSignalSpy();
Q_CHECK_PTR(_multiSpyMissionController);
QCOMPARE(_multiSpyMissionController->init(_missionController, _rgMissionControllerSignals, _cMissionControllerSignals), true);
if (startController) {
_missionController->start(true /* editMode */);
}
_masterController->start(true /* editMode */);
// All signals should some through on start
QCOMPARE(_multiSpyMissionController->checkOnlySignalsByMask(visualItemsChangedSignalMask | waypointLinesChangedSignalMask), true);
......@@ -162,6 +160,7 @@ void MissionControllerTest::_testAddWayppointPX4(void)
_testAddWaypointWorker(MAV_AUTOPILOT_PX4);
}
#if 0
void MissionControllerTest::_testOfflineToOnlineWorker(MAV_AUTOPILOT firmwareType)
{
// Start offline and add item
......@@ -191,6 +190,7 @@ void MissionControllerTest::_testOfflineToOnlinePX4(void)
{
_testOfflineToOnlineWorker(MAV_AUTOPILOT_PX4);
}
#endif
void MissionControllerTest::_setupVisualItemSignals(VisualMissionItem* visualItem)
{
......
......@@ -16,6 +16,7 @@
#include "MissionManager.h"
#include "MultiSignalSpy.h"
#include "MissionControllerManagerTest.h"
#include "PlanMasterController.h"
#include "MissionController.h"
#include "SimpleMissionItem.h"
......@@ -38,14 +39,18 @@ private:
void _testEmptyVehiclePX4(void);
void _testAddWayppointAPM(void);
void _testAddWayppointPX4(void);
#if 0
void _testOfflineToOnlineAPM(void);
void _testOfflineToOnlinePX4(void);
#endif
private:
void _initForFirmwareType(MAV_AUTOPILOT firmwareType);
void _testEmptyVehicleWorker(MAV_AUTOPILOT firmwareType);
void _testAddWaypointWorker(MAV_AUTOPILOT firmwareType);
#if 0
void _testOfflineToOnlineWorker(MAV_AUTOPILOT firmwareType);
#endif
void _setupVisualItemSignals(VisualMissionItem* visualItem);
// MissiomItems signals
......@@ -81,7 +86,8 @@ private:
static const size_t _cVisualItemSignals = visualItemMaxSignalIndex;
const char* _rgVisualItemSignals[_cVisualItemSignals];
MissionController* _missionController;
PlanMasterController* _masterController;
MissionController* _missionController;
};
#endif
......@@ -8,13 +8,17 @@
****************************************************************************/
#include "PlanElementController.h"
#include "PlanMasterController.h"
#include "QGCApplication.h"
#include "MultiVehicleManager.h"
#include "SettingsManager.h"
#include "AppSettings.h"
PlanElementController::PlanElementController(QObject* parent)
PlanElementController::PlanElementController(PlanMasterController* masterController, QObject* parent)
: QObject(parent)
, _multiVehicleMgr(qgcApp()->toolbox()->multiVehicleManager())
, _activeVehicle(_multiVehicleMgr->offlineEditingVehicle())
, _masterController(masterController)
, _controllerVehicle(masterController->controllerVehicle())
, _managerVehicle(masterController->managerVehicle())
, _editMode(false)
{
......@@ -29,9 +33,3 @@ void PlanElementController::start(bool editMode)
{
_editMode = editMode;
}
void PlanElementController::startStaticActiveVehicle(Vehicle* vehicle)
{
Q_UNUSED(vehicle);
_editMode = false;
}
......@@ -15,6 +15,8 @@
#include "Vehicle.h"
#include "MultiVehicleManager.h"
class PlanMasterController;
/// This is the abstract base clas for Plan Element controllers.
/// Examples of plan elements are: missions (MissionController), geofence (GeoFenceController)
class PlanElementController : public QObject
......@@ -22,21 +24,17 @@ class PlanElementController : public QObject
Q_OBJECT
public:
PlanElementController(QObject* parent = NULL);
PlanElementController(PlanMasterController* masterController, QObject* parent = NULL);
~PlanElementController();
Q_PROPERTY(bool containsItems READ containsItems NOTIFY containsItemsChanged) ///< true: Elemement is non-empty
Q_PROPERTY(bool syncInProgress READ syncInProgress NOTIFY syncInProgressChanged) ///< true: information is currently being saved/sent, false: no active save/send in progress
Q_PROPERTY(bool dirty READ dirty WRITE setDirty NOTIFY dirtyChanged) ///< true: unsaved/sent changes are present, false: no changes since last save/send
Q_PROPERTY(Vehicle* vehicle READ vehicle NOTIFY vehicleChanged)
Q_PROPERTY(bool containsItems READ containsItems NOTIFY containsItemsChanged) ///< true: Elemement is non-empty
Q_PROPERTY(bool syncInProgress READ syncInProgress NOTIFY syncInProgressChanged) ///< true: information is currently being saved/sent, false: no active save/send in progress
Q_PROPERTY(bool dirty READ dirty WRITE setDirty NOTIFY dirtyChanged) ///< true: unsaved/sent changes are present, false: no changes since last save/send
/// Should be called immediately upon Component.onCompleted.
/// @param editMode true: controller being used in Plan view, false: controller being used in Fly view
virtual void start(bool editMode);
/// Starts the controller using a single static active vehicle. Will not track global active vehicle changes.
virtual void startStaticActiveVehicle(Vehicle* vehicle);
virtual void save(QJsonObject& json) = 0;
virtual bool load(const QJsonObject& json, QString& errorString) = 0;
virtual void loadFromVehicle(void) = 0;
......@@ -49,13 +47,8 @@ public:
virtual bool dirty (void) const = 0;
virtual void setDirty (bool dirty) = 0;
/// Called when the current active vehicle is about to be removed. Derived classes should override to implement custom behavior.
virtual void activeVehicleBeingRemoved(void) = 0;
/// Called when a new active vehicle has been set. Derived classes should override to implement custom behavior.
virtual void activeVehicleSet(Vehicle* activeVehicle) = 0;
Vehicle* vehicle(void) { return _activeVehicle; }
/// Called when a new manager vehicle has been set. Derived classes should override to implement custom behavior.
virtual void managerVehicleChanged(Vehicle* managerVehicle) = 0;
signals:
void containsItemsChanged (bool containsItems);
......@@ -64,8 +57,9 @@ signals:
void vehicleChanged (Vehicle* vehicle);
protected:
MultiVehicleManager* _multiVehicleMgr;
Vehicle* _activeVehicle; ///< Currently active vehicle, can be disconnected offline editing vehicle
PlanMasterController* _masterController;
Vehicle* _controllerVehicle;
Vehicle* _managerVehicle;
bool _editMode;
};
......
......@@ -10,6 +10,7 @@
#include "PlanMasterController.h"
#include "QGCApplication.h"
#include "MultiVehicleManager.h"
#include "SettingsManager.h"
#include "AppSettings.h"
#include "JsonHelper.h"
......@@ -25,8 +26,13 @@ const char* PlanMasterController::_jsonRallyPointsObjectKey = "rallyPoints";
PlanMasterController::PlanMasterController(QObject* parent)
: QObject(parent)
, _multiVehicleMgr(qgcApp()->toolbox()->multiVehicleManager())
, _activeVehicle(_multiVehicleMgr->offlineEditingVehicle())
, _controllerVehicle(new Vehicle((MAV_AUTOPILOT)qgcApp()->toolbox()->settingsManager()->appSettings()->offlineEditingFirmwareType()->rawValue().toInt(), (MAV_TYPE)qgcApp()->toolbox()->settingsManager()->appSettings()->offlineEditingVehicleType()->rawValue().toInt(), qgcApp()->toolbox()->firmwarePluginManager()))
, _managerVehicle(_controllerVehicle)
, _editMode(false)
, _offline(true)
, _missionController(this)
, _geoFenceController(this)
, _rallyPointController(this)
{
connect(&_missionController, &MissionController::dirtyChanged, this, &PlanMasterController::dirtyChanged);
connect(&_geoFenceController, &GeoFenceController::dirtyChanged, this, &PlanMasterController::dirtyChanged);
......@@ -60,34 +66,42 @@ void PlanMasterController::start(bool editMode)
void PlanMasterController::startStaticActiveVehicle(Vehicle* vehicle)
{
_editMode = false;
_missionController.startStaticActiveVehicle(vehicle);
_geoFenceController.startStaticActiveVehicle(vehicle);
_rallyPointController.startStaticActiveVehicle(vehicle);
_activeVehicleChanged(vehicle);
}
void PlanMasterController::_activeVehicleChanged(Vehicle* activeVehicle)
{
if (_activeVehicle) {
_missionController.activeVehicleBeingRemoved();
_geoFenceController.activeVehicleBeingRemoved();
_rallyPointController.activeVehicleBeingRemoved();
_activeVehicle = NULL;
if (_managerVehicle == activeVehicle) {
// We are already setup for this vehicle
return;
}
if (activeVehicle) {
_activeVehicle = activeVehicle;
bool newOffline = false;
if (activeVehicle == NULL) {
// Since there is no longer an active vehicle we use the offline controller vehicle as the manager vehicle
_managerVehicle = _controllerVehicle;
newOffline = true;
} else {
_activeVehicle = _multiVehicleMgr->offlineEditingVehicle();
// FIXME: Check for vehicle compatibility. (edit mode only)
_managerVehicle = activeVehicle;
newOffline = false;
}
if (newOffline != _offline) {
_offline = newOffline;
emit offlineEditingChanged(newOffline);
}
_missionController.activeVehicleSet(_activeVehicle);
_geoFenceController.activeVehicleSet(_activeVehicle);
_rallyPointController.activeVehicleSet(_activeVehicle);
// Whenever vehicle changes we need to update syncInProgress
emit syncInProgressChanged(syncInProgress());
_missionController.managerVehicleChanged(_managerVehicle);
_geoFenceController.managerVehicleChanged(_managerVehicle);
_rallyPointController.managerVehicleChanged(_managerVehicle);
emit vehicleChanged(_activeVehicle);
if (!_editMode && _offline) {
// Fly view has changed to a new active vehicle
loadFromVehicle();
}
// Whenever manager changes we need to update syncInProgress
emit syncInProgressChanged(syncInProgress());
}
void PlanMasterController::loadFromVehicle(void)
......@@ -96,6 +110,7 @@ void PlanMasterController::loadFromVehicle(void)
_missionController.loadFromVehicle();
_geoFenceController.loadFromVehicle();
_rallyPointController.loadFromVehicle();
setDirty(false);
}
void PlanMasterController::sendToVehicle(void)
......@@ -104,6 +119,7 @@ void PlanMasterController::sendToVehicle(void)
_missionController.sendToVehicle();
_geoFenceController.sendToVehicle();
_rallyPointController.sendToVehicle();
setDirty(false);
}
......@@ -166,7 +182,7 @@ void PlanMasterController::loadFromFile(const QString& filename)
}
}
if (!_activeVehicle->isOfflineEditingVehicle()) {
if (!offline()) {
setDirty(true);
}
}
......@@ -204,8 +220,8 @@ void PlanMasterController::saveToFile(const QString& filename)
file.write(saveDoc.toJson());
}
// If we are connected to a real vehicle, don't clear dirty bit on saving to file since vehicle is still out of date
if (_activeVehicle->isOfflineEditingVehicle()) {
// Only clear dirty bit if we are offline
if (offline()) {
setDirty(false);
}
}
......@@ -234,6 +250,7 @@ bool PlanMasterController::syncInProgress(void) const
bool PlanMasterController::dirty(void) const
{
qDebug() << _editMode << _missionController.dirty() << _geoFenceController.dirty() << _rallyPointController.dirty();
return _missionController.dirty() || _geoFenceController.dirty() || _rallyPointController.dirty();
}
......
......@@ -30,13 +30,14 @@ public:
Q_PROPERTY(GeoFenceController* geoFenceController READ geoFenceController CONSTANT)
Q_PROPERTY(RallyPointController* rallyPointController READ rallyPointController CONSTANT)
Q_PROPERTY(bool containsItems READ containsItems NOTIFY containsItemsChanged) ///< true: Elemement is non-empty
Q_PROPERTY(bool syncInProgress READ syncInProgress NOTIFY syncInProgressChanged) ///< true: Information is currently being saved/sent, false: no active save/send in progress
Q_PROPERTY(bool dirty READ dirty WRITE setDirty NOTIFY dirtyChanged) ///< true: Unsaved/sent changes are present, false: no changes since last save/send
Q_PROPERTY(Vehicle* vehicle READ vehicle NOTIFY vehicleChanged)
Q_PROPERTY(QString fileExtension READ fileExtension CONSTANT) ///< File extention for missions
Q_PROPERTY(QStringList loadNameFilters READ loadNameFilters CONSTANT) ///< File filter list loading plan files
Q_PROPERTY(QStringList saveNameFilters READ saveNameFilters CONSTANT) ///< File filter list saving plan files
Q_PROPERTY(Vehicle* controllerVehicle MEMBER _controllerVehicle CONSTANT)
Q_PROPERTY(bool offline READ offline NOTIFY offlineEditingChanged) ///< true: controller is not connected to an active vehicle
Q_PROPERTY(bool containsItems READ containsItems NOTIFY containsItemsChanged) ///< true: Elemement is non-empty
Q_PROPERTY(bool syncInProgress READ syncInProgress NOTIFY syncInProgressChanged) ///< true: Information is currently being saved/sent, false: no active save/send in progress
Q_PROPERTY(bool dirty READ dirty WRITE setDirty NOTIFY dirtyChanged) ///< true: Unsaved/sent changes are present, false: no changes since last save/send
Q_PROPERTY(QString fileExtension READ fileExtension CONSTANT) ///< File extention for missions
Q_PROPERTY(QStringList loadNameFilters READ loadNameFilters CONSTANT) ///< File filter list loading plan files
Q_PROPERTY(QStringList saveNameFilters READ saveNameFilters CONSTANT) ///< File filter list saving plan files
/// Should be called immediately upon Component.onCompleted.
/// @param editMode true: controller being used in Plan view, false: controller being used in Fly view
......@@ -61,6 +62,7 @@ public:
GeoFenceController* geoFenceController(void) { return &_geoFenceController; }
RallyPointController* rallyPointController(void) { return &_rallyPointController; }
bool offline (void) const { return _offline; }
bool containsItems (void) const;
bool syncInProgress (void) const;
bool dirty (void) const;
......@@ -69,21 +71,25 @@ public:
QStringList loadNameFilters (void) const;
QStringList saveNameFilters (void) const;
Vehicle* vehicle(void) { return _activeVehicle; }
Vehicle* controllerVehicle(void) { return _controllerVehicle; }
Vehicle* managerVehicle(void) { return _managerVehicle; }
signals:
void containsItemsChanged (bool containsItems);
void syncInProgressChanged (bool syncInProgress);
void dirtyChanged (bool dirty);
void vehicleChanged (Vehicle* vehicle);
void offlineEditingChanged (bool offlineEditing);
private slots:
void _activeVehicleChanged(Vehicle* activeVehicle);
private:
MultiVehicleManager* _multiVehicleMgr;
Vehicle* _activeVehicle; ///< Currently active vehicle, can be disconnected offline editing vehicle
Vehicle* _controllerVehicle;
Vehicle* _managerVehicle;
bool _editMode;
bool _offline;
MissionController _missionController;
GeoFenceController _geoFenceController;
RallyPointController _rallyPointController;
......
......@@ -36,12 +36,15 @@ QGC_LOGGING_CATEGORY(RallyPointControllerLog, "RallyPointControllerLog")
const char* RallyPointController::_jsonFileTypeValue = "RallyPoints";
const char* RallyPointController::_jsonPointsKey = "points";
RallyPointController::RallyPointController(QObject* parent)
: PlanElementController(parent)
RallyPointController::RallyPointController(PlanMasterController* masterController, QObject* parent)
: PlanElementController(masterController, parent)
, _rallyPointManager(_managerVehicle->rallyPointManager())
, _dirty(false)
, _currentRallyPoint(NULL)
{
connect(&_points, &QmlObjectListModel::countChanged, this, &RallyPointController::_updateContainsItems);
managerVehicleChanged(_managerVehicle);
}
RallyPointController::~RallyPointController()
......@@ -49,22 +52,26 @@ RallyPointController::~RallyPointController()
}
void RallyPointController::activeVehicleBeingRemoved(void)
void RallyPointController::managerVehicleChanged(Vehicle* managerVehicle)
{
_activeVehicle->rallyPointManager()->disconnect(this);
_points.clearAndDeleteContents();
_activeVehicle = NULL;
}
if (_managerVehicle) {
_rallyPointManager->disconnect(this);
_managerVehicle = NULL;
_rallyPointManager = NULL;
}
void RallyPointController::activeVehicleSet(Vehicle* activeVehicle)
{
_activeVehicle = activeVehicle;
RallyPointManager* rallyPointManager = _activeVehicle->rallyPointManager();
connect(rallyPointManager, &RallyPointManager::loadComplete, this, &RallyPointController::_loadComplete);
connect(rallyPointManager, &RallyPointManager::inProgressChanged, this, &RallyPointController::syncInProgressChanged);
_managerVehicle = managerVehicle;
if (!_managerVehicle) {
qWarning() << "RallyPointController::managerVehicleChanged managerVehicle=NULL";
return;
}
_rallyPointManager = _managerVehicle->rallyPointManager();
connect(_rallyPointManager, &RallyPointManager::loadComplete, this, &RallyPointController::_loadComplete);
connect(_rallyPointManager, &RallyPointManager::inProgressChanged, this, &RallyPointController::syncInProgressChanged);
if (!rallyPointManager->inProgress()) {
_loadComplete(rallyPointManager->points());
if (!syncInProgress()) {
_loadComplete(_rallyPointManager->points());
}
emit rallyPointsSupportedChanged(rallyPointsSupported());
}
......@@ -121,10 +128,10 @@ void RallyPointController::removeAll(void)
void RallyPointController::loadFromVehicle(void)
{
if (_activeVehicle->parameterManager()->parametersReady() && !syncInProgress()) {
_activeVehicle->rallyPointManager()->loadFromVehicle();
if (!syncInProgress()) {
_rallyPointManager->loadFromVehicle();
} else {
qCWarning(RallyPointControllerLog) << "RallyPointController::loadFromVehicle call at wrong time" << _activeVehicle->parameterManager()->parametersReady() << syncInProgress();
qCWarning(RallyPointControllerLog) << "RallyPointController::loadFromVehicle call while syncInProgress";
}
}
......@@ -136,15 +143,15 @@ void RallyPointController::sendToVehicle(void)
for (int i=0; i<_points.count(); i++) {
rgPoints.append(qobject_cast<RallyPoint*>(_points[i])->coordinate());
}
_activeVehicle->rallyPointManager()->sendToVehicle(rgPoints);
_rallyPointManager->sendToVehicle(rgPoints);
} else {
qCWarning(RallyPointControllerLog) << "RallyPointController::loadFromVehicle call at wrong time" << _activeVehicle->parameterManager()->parametersReady() << syncInProgress();
qCWarning(RallyPointControllerLog) << "RallyPointController::loadFromVehicle while syncInProgress";
}
}
bool RallyPointController::syncInProgress(void) const
{
return _activeVehicle->rallyPointManager()->inProgress();
return _rallyPointManager->inProgress();
}
void RallyPointController::setDirty(bool dirty)
......@@ -157,7 +164,7 @@ void RallyPointController::setDirty(bool dirty)
QString RallyPointController::editorQml(void) const
{
return _activeVehicle->rallyPointManager()->editorQml();
return _rallyPointManager->editorQml();
}
void RallyPointController::_loadComplete(const QList<QGeoCoordinate> rgPoints)
......@@ -190,7 +197,7 @@ void RallyPointController::addPoint(QGeoCoordinate point)
bool RallyPointController::rallyPointsSupported(void) const
{
return _activeVehicle->rallyPointManager()->rallyPointsSupported();
return _rallyPointManager->rallyPointsSupported();
}
void RallyPointController::removePoint(QObject* rallyPoint)
......@@ -237,5 +244,5 @@ void RallyPointController::_updateContainsItems(void)
void RallyPointController::removeAllFromVehicle(void)
{
_activeVehicle->rallyPointManager()->removeAll();
_rallyPointManager->removeAll();
}
......@@ -26,7 +26,7 @@ class RallyPointController : public PlanElementController
Q_OBJECT
public:
RallyPointController(QObject* parent = NULL);
RallyPointController(PlanMasterController* masterController, QObject* parent = NULL);
~RallyPointController();
Q_PROPERTY(bool rallyPointsSupported READ rallyPointsSupported NOTIFY rallyPointsSupportedChanged)
......@@ -47,8 +47,7 @@ public:
bool dirty (void) const final { return _dirty; }
void setDirty (bool dirty) final;
bool containsItems (void) const final;
void activeVehicleBeingRemoved (void) final;
void activeVehicleSet (Vehicle* vehicle) final;
void managerVehicleChanged (Vehicle* managerVehicle) final;
bool rallyPointsSupported (void) const;
QmlObjectListModel* points (void) { return &_points; }
......@@ -68,6 +67,7 @@ private slots:
void _updateContainsItems(void);
private:
RallyPointManager* _rallyPointManager;
bool _dirty;
QmlObjectListModel _points;
QObject* _currentRallyPoint;
......
......@@ -20,7 +20,7 @@ Rectangle {
radius: _radius
property var map ///< Map control
property var missionController
property var masterController
property var missionItem ///< MissionItem associated with this editor
property bool readOnly ///< true: read only view, false: full editing view
property var rootQgcView
......@@ -30,11 +30,13 @@ Rectangle {
signal insertWaypoint
signal insertComplexItem(string complexItemName)
property var _masterController: masterController
property var _missionController: _masterController.missionController
property bool _currentItem: missionItem.isCurrentItem
property color _outerTextColor: _currentItem ? qgcPal.primaryButtonText : qgcPal.text
property bool _noMissionItemsAdded: ListView.view.model.count === 1
property real _sectionSpacer: ScreenTools.defaultFontPixelWidth / 2 // spacing between section headings
property bool _singleComplexItem: missionController.complexMissionItemNames.length === 1
property bool _singleComplexItem: _missionController.complexMissionItemNames.length === 1
readonly property real _editFieldWidth: Math.min(width - _margin * 2, ScreenTools.defaultFontPixelWidth * 12)
readonly property real _margin: ScreenTools.defaultFontPixelWidth / 2
......@@ -105,7 +107,7 @@ Rectangle {
visible: !_singleComplexItem
Instantiator {
model: missionController.complexMissionItemNames
model: _missionController.complexMissionItemNames
onObjectAdded: patternMenu.insertItem(index, object)
onObjectRemoved: patternMenu.removeItem(object)
......@@ -118,9 +120,9 @@ Rectangle {
}
MenuItem {
text: qsTr("Insert ") + missionController.complexMissionItemNames[0]
text: qsTr("Insert ") + _missionController.complexMissionItemNames[0]
visible: _singleComplexItem
onTriggered: insertComplexItem(missionController.complexMissionItemNames[0])
onTriggered: insertComplexItem(_missionController.complexMissionItemNames[0])
}
MenuItem {
......@@ -203,7 +205,8 @@ Rectangle {
item.visible = Qt.binding(function() { return _currentItem; })
}
property real availableWidth: _root.width - (_margin * 2) ///< How wide the editor should be
property var editorRoot: _root
property var masterController: _masterController
property real availableWidth: _root.width - (_margin * 2) ///< How wide the editor should be
property var editorRoot: _root
}
} // Rectangle
......@@ -20,7 +20,9 @@ Rectangle {
visible: missionItem.isCurrentItem
radius: _radius
property var _missionVehicle: missionController.vehicle
property var _masterControler: masterController
property var _missionController: _masterControler.missionController
property var _missionVehicle: _masterControler.controllerVehicle
property bool _vehicleHasHomePosition: _missionVehicle.homePosition.isValid
property bool _offlineEditing: _missionVehicle.isOfflineEditingVehicle
property bool _showOfflineVehicleCombos: _offlineEditing && _multipleFirmware && _noMissionItemsAdded
......@@ -32,7 +34,7 @@ Rectangle {
property var _savePath: QGroundControl.settingsManager.appSettings.missionSavePath
property var _fileExtension: QGroundControl.settingsManager.appSettings.missionFileExtension
property var _appSettings: QGroundControl.settingsManager.appSettings
property bool _waypointsOnlyMode: QGroundControl.corePlugin.options.missionWaypointsOnly
property bool _waypointsOnlyMode: QGroundControl.corePlugin.options.missionWaypointsOnly
readonly property string _firmwareLabel: qsTr("Firmware")
readonly property string _vehicleLabel: qsTr("Vehicle")
......
......@@ -273,8 +273,8 @@ Rectangle {
anchors.right: parent.right
anchors.verticalCenter: parent.verticalCenter
text: _controllerDirty ? qsTr("Upload Required") : qsTr("Upload")
enabled: _activeVehicle && !_controllerSyncInProgress
visible: _activeVehicle
enabled: !_controllerSyncInProgress
visible: !planMasterController.offline
onClicked: planMasterController.upload()
PropertyAnimation on opacity {
......
......@@ -557,7 +557,7 @@ QGCView {
delegate: MissionItemEditor {
map: editorMap
missionController: _missionController
masterController: _planMasterController
missionItem: object
width: parent.width
readOnly: false
......@@ -734,7 +734,7 @@ QGCView {
QGCButton {
text: qsTr("Upload")
Layout.fillWidth: true
enabled: _activeVehicle && !masterController.syncInProgress
enabled: !masterController.offline && !masterController.syncInProgress
onClicked: {
dropPanel.hide()
masterController.upload()
......@@ -744,7 +744,7 @@ QGCView {
QGCButton {
text: qsTr("Download")
Layout.fillWidth: true
enabled: _activeVehicle && !masterController.syncInProgress
enabled: !masterController.offline && !masterController.syncInProgress
onClicked: {
dropPanel.hide()
if (masterController.dirty) {
......
......@@ -378,14 +378,14 @@ void QGCApplication::_initCommon(void)
qmlRegisterUncreatableType<Joystick> ("QGroundControl.JoystickManager", 1, 0, "Joystick", "Reference only");
qmlRegisterUncreatableType<QGCPositionManager> ("QGroundControl.QGCPositionManager", 1, 0, "QGCPositionManager", "Reference only");
qmlRegisterUncreatableType<QGCMapPolygon> ("QGroundControl.FlightMap", 1, 0, "QGCMapPolygon", "Reference only");
qmlRegisterUncreatableType<MissionController> ("QGroundControl.Controllers", 1, 0, "MissionController", "Reference only");
qmlRegisterUncreatableType<GeoFenceController> ("QGroundControl.Controllers", 1, 0, "GeoFenceController", "Reference only");
qmlRegisterUncreatableType<RallyPointController>("QGroundControl.Controllers", 1, 0, "RallyPointController", "Reference only");
qmlRegisterType<ParameterEditorController> ("QGroundControl.Controllers", 1, 0, "ParameterEditorController");
qmlRegisterType<ESP8266ComponentController> ("QGroundControl.Controllers", 1, 0, "ESP8266ComponentController");
qmlRegisterType<ScreenToolsController> ("QGroundControl.Controllers", 1, 0, "ScreenToolsController");
qmlRegisterType<PlanMasterController> ("QGroundControl.Controllers", 1, 0, "PlanElemementMasterController");
qmlRegisterType<MissionController> ("QGroundControl.Controllers", 1, 0, "MissionController");
qmlRegisterType<GeoFenceController> ("QGroundControl.Controllers", 1, 0, "GeoFenceController");
qmlRegisterType<RallyPointController> ("QGroundControl.Controllers", 1, 0, "RallyPointController");
qmlRegisterType<ValuesWidgetController> ("QGroundControl.Controllers", 1, 0, "ValuesWidgetController");
qmlRegisterType<QFileDialogController> ("QGroundControl.Controllers", 1, 0, "QFileDialogController");
qmlRegisterType<RCChannelMonitorController> ("QGroundControl.Controllers", 1, 0, "RCChannelMonitorController");
......
......@@ -289,3 +289,26 @@ Fact* AppSettings::automaticMissionUpload(void)
return _automaticMissionUpload;
}
MAV_AUTOPILOT AppSettings::offlineEditingFirmwareTypeFromFirmwareType(MAV_AUTOPILOT firmwareType)
{
if (firmwareType != MAV_AUTOPILOT_PX4 && firmwareType != MAV_AUTOPILOT_ARDUPILOTMEGA) {
firmwareType = MAV_AUTOPILOT_GENERIC;
}
return firmwareType;
}
MAV_TYPE AppSettings::offlineEditingVehicleTypeFromVehicleType(MAV_TYPE vehicleType)
{
if (QGCMAVLink::isRover(vehicleType)) {
return MAV_TYPE_GROUND_ROVER;
} else if (QGCMAVLink::isSub(vehicleType)) {
return MAV_TYPE_SUBMARINE;
} else if (QGCMAVLink::isVTOL(vehicleType)) {
return MAV_TYPE_VTOL_QUADROTOR;
} else if (QGCMAVLink::isFixedWing(vehicleType)) {
return MAV_TYPE_FIXED_WING;
} else {
return MAV_TYPE_QUADROTOR;
}
}
......@@ -11,6 +11,7 @@
#define AppSettings_H
#include "SettingsGroup.h"
#include "QGCMAVLink.h"
class AppSettings : public SettingsGroup
{
......@@ -67,6 +68,9 @@ public:
QString parameterSavePath (void);
QString telemetrySavePath (void);
static MAV_AUTOPILOT offlineEditingFirmwareTypeFromFirmwareType(MAV_AUTOPILOT firmwareType);
static MAV_TYPE offlineEditingVehicleTypeFromVehicleType(MAV_TYPE vehicleType);
static const char* appSettingsGroupName;
static const char* offlineEditingFirmwareTypeSettingsName;
......
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