Commit 97ac36f9 authored by Don Gagne's avatar Don Gagne Committed by GitHub

Merge pull request #5034 from DonLakeFlyer/FileLoadSupport

Plan: Add back loading of older mission file formats
parents 994c6198 3d7fdaeb
...@@ -204,7 +204,7 @@ void MissionController::loadFromVehicle(void) ...@@ -204,7 +204,7 @@ void MissionController::loadFromVehicle(void)
void MissionController::sendToVehicle(void) void MissionController::sendToVehicle(void)
{ {
sendItemsToVehicle(_activeVehicle, _visualItems); sendItemsToVehicle(_activeVehicle, _visualItems);
_visualItems->setDirty(false); setDirty(false);
} }
/// Converts from visual items to MissionItems /// Converts from visual items to MissionItems
...@@ -322,7 +322,7 @@ void MissionController::removeMissionItem(int index) ...@@ -322,7 +322,7 @@ void MissionController::removeMissionItem(int index)
item->deleteLater(); item->deleteLater();
_recalcAll(); _recalcAll();
_visualItems->setDirty(true); setDirty(true);
} }
void MissionController::removeAll(void) void MissionController::removeAll(void)
...@@ -334,7 +334,7 @@ void MissionController::removeAll(void) ...@@ -334,7 +334,7 @@ void MissionController::removeAll(void)
_visualItems = new QmlObjectListModel(this); _visualItems = new QmlObjectListModel(this);
_addMissionSettings(_activeVehicle, _visualItems, false /* addToCenter */); _addMissionSettings(_activeVehicle, _visualItems, false /* addToCenter */);
_initAllVisualItems(); _initAllVisualItems();
_visualItems->setDirty(true); setDirty(true);
_resetMissionFlightStatus(); _resetMissionFlightStatus();
} }
} }
...@@ -579,7 +579,6 @@ bool MissionController::_loadJsonMissionFileV2(Vehicle* vehicle, const QJsonObje ...@@ -579,7 +579,6 @@ bool MissionController::_loadJsonMissionFileV2(Vehicle* vehicle, const QJsonObje
return true; return true;
} }
#if 0
bool MissionController::_loadItemsFromJson(const QJsonObject& json, QmlObjectListModel* visualItems, QString& errorString) bool MissionController::_loadItemsFromJson(const QJsonObject& json, QmlObjectListModel* visualItems, QString& errorString)
{ {
// V1 file format has no file type key and version key is string. Convert to new format. // V1 file format has no file type key and version key is string. Convert to new format.
...@@ -588,14 +587,12 @@ bool MissionController::_loadItemsFromJson(const QJsonObject& json, QmlObjectLis ...@@ -588,14 +587,12 @@ bool MissionController::_loadItemsFromJson(const QJsonObject& json, QmlObjectLis
} }
int fileVersion; int fileVersion;
if (!JsonHelper::validateQGCJsonFile(json, JsonHelper::validateQGCJsonFile(json,
_jsonFileTypeValue, // expected file type _jsonFileTypeValue, // expected file type
1, // minimum supported version 1, // minimum supported version
2, // maximum supported version 2, // maximum supported version
fileVersion, fileVersion,
errorString)) { errorString);
return false;
}
if (fileVersion == 1) { if (fileVersion == 1) {
return _loadJsonMissionFileV1(_activeVehicle, json, visualItems, errorString); return _loadJsonMissionFileV1(_activeVehicle, json, visualItems, errorString);
...@@ -603,11 +600,11 @@ bool MissionController::_loadItemsFromJson(const QJsonObject& json, QmlObjectLis ...@@ -603,11 +600,11 @@ bool MissionController::_loadItemsFromJson(const QJsonObject& json, QmlObjectLis
return _loadJsonMissionFileV2(_activeVehicle, json, visualItems, errorString); return _loadJsonMissionFileV2(_activeVehicle, json, visualItems, errorString);
} }
} }
#endif
bool MissionController::_loadTextMissionFile(Vehicle* vehicle, QTextStream& stream, QmlObjectListModel* visualItems, QString& errorString) bool MissionController::_loadTextMissionFile(Vehicle* vehicle, QTextStream& stream, QmlObjectListModel* visualItems, QString& errorString)
{ {
bool addPlannedHomePosition = false; bool firstItem = true;
bool plannedHomePositionInFile = false;
QString firstLine = stream.readLine(); QString firstLine = stream.readLine();
const QStringList& version = firstLine.split(" "); const QStringList& version = firstLine.split(" ");
...@@ -617,19 +614,29 @@ bool MissionController::_loadTextMissionFile(Vehicle* vehicle, QTextStream& stre ...@@ -617,19 +614,29 @@ bool MissionController::_loadTextMissionFile(Vehicle* vehicle, QTextStream& stre
if (version[2] == "110") { if (version[2] == "110") {
// ArduPilot file, planned home position is already in position 0 // ArduPilot file, planned home position is already in position 0
versionOk = true; versionOk = true;
plannedHomePositionInFile = true;
} else if (version[2] == "120") { } else if (version[2] == "120") {
// Old QGC file, no planned home position // Old QGC file, no planned home position
versionOk = true; versionOk = true;
addPlannedHomePosition = true; plannedHomePositionInFile = false;
} }
} }
if (versionOk) { if (versionOk) {
// Start with planned home in center
_addMissionSettings(vehicle, visualItems, true /* addToCenter */);
MissionSettingsItem* settingsItem = visualItems->value<MissionSettingsItem*>(0);
while (!stream.atEnd()) { while (!stream.atEnd()) {
SimpleMissionItem* item = new SimpleMissionItem(vehicle, visualItems); SimpleMissionItem* item = new SimpleMissionItem(vehicle, visualItems);
if (item->load(stream)) { if (item->load(stream)) {
visualItems->append(item); if (firstItem && plannedHomePositionInFile) {
settingsItem->setCoordinate(item->coordinate());
} else {
visualItems->append(item);
}
firstItem = false;
} else { } else {
errorString = QStringLiteral("The mission file is corrupted."); errorString = QStringLiteral("The mission file is corrupted.");
return false; return false;
...@@ -640,9 +647,7 @@ bool MissionController::_loadTextMissionFile(Vehicle* vehicle, QTextStream& stre ...@@ -640,9 +647,7 @@ bool MissionController::_loadTextMissionFile(Vehicle* vehicle, QTextStream& stre
return false; return false;
} }
if (addPlannedHomePosition || visualItems->count() == 0) { if (!plannedHomePositionInFile) {
_addMissionSettings(vehicle, visualItems, true /* addToCenter */);
// Update sequence numbers in DO_JUMP commands to take into account added home position in index 0 // Update sequence numbers in DO_JUMP commands to take into account added home position in index 0
for (int i=1; i<visualItems->count(); i++) { for (int i=1; i<visualItems->count(); i++) {
SimpleMissionItem* item = qobject_cast<SimpleMissionItem*>(visualItems->get(i)); SimpleMissionItem* item = qobject_cast<SimpleMissionItem*>(visualItems->get(i));
...@@ -655,24 +660,15 @@ bool MissionController::_loadTextMissionFile(Vehicle* vehicle, QTextStream& stre ...@@ -655,24 +660,15 @@ bool MissionController::_loadTextMissionFile(Vehicle* vehicle, QTextStream& stre
return true; return true;
} }
bool MissionController::load(const QJsonObject& json, QString& errorString) void MissionController::_initLoadedVisualItems(QmlObjectListModel* loadedVisualItems)
{ {
QString errorStr;
QString errorMessage = tr("Mission: %1");
QmlObjectListModel* newVisualItems = new QmlObjectListModel(this);
if (!_loadJsonMissionFileV2(_activeVehicle, json, newVisualItems, errorStr)) {
errorString = errorMessage.arg(errorStr);
return false;
}
if (_visualItems) { if (_visualItems) {
_deinitAllVisualItems(); _deinitAllVisualItems();
_visualItems->deleteLater(); _visualItems->deleteLater();
_settingsItem = NULL; _settingsItem = NULL;
} }
_visualItems = newVisualItems; _visualItems = loadedVisualItems;
if (_visualItems->count() == 0) { if (_visualItems->count() == 0) {
_addMissionSettings(_activeVehicle, _visualItems, true /* addToCenter */); _addMissionSettings(_activeVehicle, _visualItems, true /* addToCenter */);
...@@ -681,12 +677,62 @@ bool MissionController::load(const QJsonObject& json, QString& errorString) ...@@ -681,12 +677,62 @@ bool MissionController::load(const QJsonObject& json, QString& errorString)
MissionController::_scanForAdditionalSettings(_visualItems, _activeVehicle); MissionController::_scanForAdditionalSettings(_visualItems, _activeVehicle);
_initAllVisualItems(); _initAllVisualItems();
}
if (!_activeVehicle->isOfflineEditingVehicle()) { bool MissionController::load(const QJsonObject& json, QString& errorString)
// Needs a sync to vehicle {
setDirty(true); QString errorStr;
QString errorMessage = tr("Mission: %1");
QmlObjectListModel* loadedVisualItems = new QmlObjectListModel(this);
if (!_loadJsonMissionFileV2(_activeVehicle, json, loadedVisualItems, errorStr)) {
errorString = errorMessage.arg(errorStr);
return false;
}
_initLoadedVisualItems(loadedVisualItems);
return true;
}
bool MissionController::loadJsonFile(QFile& file, QString& errorString)
{
QString errorStr;
QString errorMessage = tr("Mission: %1");
QJsonDocument jsonDoc;
QByteArray bytes = file.readAll();
if (!JsonHelper::isJsonFile(bytes, jsonDoc, errorStr)) {
errorString = errorMessage.arg(errorStr);
return false;
}
QJsonObject json = jsonDoc.object();
QmlObjectListModel* loadedVisualItems = new QmlObjectListModel(this);
if (!_loadItemsFromJson(json, loadedVisualItems, errorStr)) {
errorString = errorMessage.arg(errorStr);
return false;
} }
_initLoadedVisualItems(loadedVisualItems);
return true;
}
bool MissionController::loadTextFile(QFile& file, QString& errorString)
{
QString errorStr;
QString errorMessage = tr("Mission: %1");
QByteArray bytes = file.readAll();
QTextStream stream(bytes);
QmlObjectListModel* loadedVisualItems = new QmlObjectListModel(this);
if (!_loadTextMissionFile(_activeVehicle, stream, loadedVisualItems, errorStr)) {
errorString = errorMessage.arg(errorStr);
return false;
}
_initLoadedVisualItems(loadedVisualItems);
return true; return true;
} }
...@@ -1196,7 +1242,7 @@ void MissionController::_initAllVisualItems(void) ...@@ -1196,7 +1242,7 @@ void MissionController::_initAllVisualItems(void)
emit containsItemsChanged(containsItems()); emit containsItemsChanged(containsItems());
emit plannedHomePositionChanged(plannedHomePosition()); emit plannedHomePositionChanged(plannedHomePosition());
_visualItems->setDirty(false); setDirty(false);
} }
void MissionController::_deinitAllVisualItems(void) void MissionController::_deinitAllVisualItems(void)
...@@ -1214,7 +1260,7 @@ void MissionController::_deinitAllVisualItems(void) ...@@ -1214,7 +1260,7 @@ void MissionController::_deinitAllVisualItems(void)
void MissionController::_initVisualItem(VisualMissionItem* visualItem) void MissionController::_initVisualItem(VisualMissionItem* visualItem)
{ {
_visualItems->setDirty(false); setDirty(false);
connect(visualItem, &VisualMissionItem::specifiesCoordinateChanged, this, &MissionController::_recalcWaypointLines); connect(visualItem, &VisualMissionItem::specifiesCoordinateChanged, this, &MissionController::_recalcWaypointLines);
connect(visualItem, &VisualMissionItem::coordinateHasRelativeAltitudeChanged, this, &MissionController::_recalcWaypointLines); connect(visualItem, &VisualMissionItem::coordinateHasRelativeAltitudeChanged, this, &MissionController::_recalcWaypointLines);
...@@ -1270,6 +1316,7 @@ void MissionController::activeVehicleBeingRemoved(void) ...@@ -1270,6 +1316,7 @@ void MissionController::activeVehicleBeingRemoved(void)
// We always remove all items on vehicle change. This leaves a user model hole: // 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 // If the user has unsaved changes in the Plan view they will lose them
removeAll(); removeAll();
setDirty(false);
_activeVehicle = NULL; _activeVehicle = NULL;
} }
...@@ -1281,6 +1328,7 @@ void MissionController::activeVehicleSet(Vehicle* activeVehicle) ...@@ -1281,6 +1328,7 @@ void MissionController::activeVehicleSet(Vehicle* activeVehicle)
// We always remove all items on vehicle change. This leaves a user model hole: // 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 // If the user has unsaved changes in the Plan view they will lose them
removeAll(); removeAll();
setDirty(false);
MissionManager* missionManager = _activeVehicle->missionManager(); MissionManager* missionManager = _activeVehicle->missionManager();
......
...@@ -103,6 +103,9 @@ public: ...@@ -103,6 +103,9 @@ public:
Q_INVOKABLE void clearCameraPoints(void); Q_INVOKABLE void clearCameraPoints(void);
bool loadJsonFile(QFile& file, QString& errorString);
bool loadTextFile(QFile& file, QString& errorString);
// Overrides from PlanElementController // Overrides from PlanElementController
void start (bool editMode) final; void start (bool editMode) final;
void startStaticActiveVehicle (Vehicle* vehicle) final; void startStaticActiveVehicle (Vehicle* vehicle) final;
...@@ -110,9 +113,6 @@ public: ...@@ -110,9 +113,6 @@ public:
bool load (const QJsonObject& json, QString& errorString) final; bool load (const QJsonObject& json, QString& errorString) final;
void loadFromVehicle (void) final; void loadFromVehicle (void) final;
void sendToVehicle (void) final; void sendToVehicle (void) final;
#if 0
void loadFromFile (const QString& filename) final;
#endif
void removeAll (void) final; void removeAll (void) final;
void removeAllFromVehicle (void) final; void removeAllFromVehicle (void) final;
bool syncInProgress (void) const final; bool syncInProgress (void) const final;
...@@ -202,6 +202,7 @@ private: ...@@ -202,6 +202,7 @@ private:
void _addCruiseTime(double cruiseTime, double cruiseDistance, int wayPointIndex); void _addCruiseTime(double cruiseTime, double cruiseDistance, int wayPointIndex);
void _updateBatteryInfo(int waypointIndex); void _updateBatteryInfo(int waypointIndex);
bool _loadItemsFromJson(const QJsonObject& json, QmlObjectListModel* visualItems, QString& errorString); bool _loadItemsFromJson(const QJsonObject& json, QmlObjectListModel* visualItems, QString& errorString);
void _initLoadedVisualItems(QmlObjectListModel* loadedVisualItems);
private: private:
QmlObjectListModel* _visualItems; QmlObjectListModel* _visualItems;
......
...@@ -123,38 +123,52 @@ void PlanMasterController::loadFromFile(const QString& filename) ...@@ -123,38 +123,52 @@ void PlanMasterController::loadFromFile(const QString& filename)
return; return;
} }
QJsonDocument jsonDoc; QString fileExtension(".%1");
QByteArray bytes = file.readAll(); if (filename.endsWith(fileExtension.arg(AppSettings::planFileExtension))) {
QJsonDocument jsonDoc;
if (!JsonHelper::isJsonFile(bytes, jsonDoc, errorString)) { QByteArray bytes = file.readAll();
qgcApp()->showMessage(errorMessage.arg(errorString));
return; if (!JsonHelper::isJsonFile(bytes, jsonDoc, errorString)) {
} qgcApp()->showMessage(errorMessage.arg(errorString));
return;
int version; }
QJsonObject json = jsonDoc.object();
if (!JsonHelper::validateQGCJsonFile(json, _planFileType, _planFileVersion, _planFileVersion, version, errorString)) { int version;
qgcApp()->showMessage(errorMessage.arg(errorString)); QJsonObject json = jsonDoc.object();
return; if (!JsonHelper::validateQGCJsonFile(json, _planFileType, _planFileVersion, _planFileVersion, version, errorString)) {
qgcApp()->showMessage(errorMessage.arg(errorString));
return;
}
QList<JsonHelper::KeyValidateInfo> rgKeyInfo = {
{ _jsonMissionObjectKey, QJsonValue::Object, true },
{ _jsonGeoFenceObjectKey, QJsonValue::Object, true },
{ _jsonRallyPointsObjectKey, QJsonValue::Object, true },
};
if (!JsonHelper::validateKeys(json, rgKeyInfo, errorString)) {
qgcApp()->showMessage(errorMessage.arg(errorString));
return;
}
if (!_missionController.load(json[_jsonMissionObjectKey].toObject(), errorString) ||
!_geoFenceController.load(json[_jsonGeoFenceObjectKey].toObject(), errorString) ||
!_rallyPointController.load(json[_jsonRallyPointsObjectKey].toObject(), errorString)) {
qgcApp()->showMessage(errorMessage.arg(errorString));
}
} else if (filename.endsWith(fileExtension.arg(AppSettings::missionFileExtension))) {
if (!_missionController.loadJsonFile(file, errorString)) {
qgcApp()->showMessage(errorMessage.arg(errorString));
}
} else if (filename.endsWith(fileExtension.arg(AppSettings::waypointsFileExtension)) ||
filename.endsWith(fileExtension.arg(QStringLiteral("txt")))) {
if (!_missionController.loadTextFile(file, errorString)) {
qgcApp()->showMessage(errorMessage.arg(errorString));
}
} }
QList<JsonHelper::KeyValidateInfo> rgKeyInfo = { if (!_activeVehicle->isOfflineEditingVehicle()) {
{ _jsonMissionObjectKey, QJsonValue::Object, true }, setDirty(true);
{ _jsonGeoFenceObjectKey, QJsonValue::Object, true },
{ _jsonRallyPointsObjectKey, QJsonValue::Object, true },
};
if (!JsonHelper::validateKeys(json, rgKeyInfo, errorString)) {
qgcApp()->showMessage(errorMessage.arg(errorString));
return;
}
if (!_missionController.load(json[_jsonMissionObjectKey].toObject(), errorString) ||
!_geoFenceController.load(json[_jsonGeoFenceObjectKey].toObject(), errorString) ||
!_rallyPointController.load(json[_jsonRallyPointsObjectKey].toObject(), errorString)) {
qgcApp()->showMessage(errorMessage.arg(errorString));
return;
} }
setDirty(true);
} }
void PlanMasterController::saveToFile(const QString& filename) void PlanMasterController::saveToFile(const QString& filename)
...@@ -239,9 +253,7 @@ QStringList PlanMasterController::loadNameFilters(void) const ...@@ -239,9 +253,7 @@ QStringList PlanMasterController::loadNameFilters(void) const
{ {
QStringList filters; QStringList filters;
filters << tr("Plan Files (*.%1)").arg(AppSettings::planFileExtension) << filters << tr("Supported types (*.%1 *.%2 *.%3 *.%4)").arg(AppSettings::planFileExtension).arg(AppSettings::missionFileExtension).arg(AppSettings::waypointsFileExtension).arg("*.txt") <<
tr("Mission Files (*.%1)").arg(AppSettings::missionFileExtension) <<
tr("Waypoint Files (*.waypoints)") <<
tr("All Files (*.*)"); tr("All Files (*.*)");
return filters; return filters;
} }
......
...@@ -396,9 +396,9 @@ QGCView { ...@@ -396,9 +396,9 @@ QGCView {
color: qgcPal.window color: qgcPal.window
title: qsTr("Plan") title: qsTr("Plan")
z: QGroundControl.zOrderWidgets z: QGroundControl.zOrderWidgets
showAlternateIcon: [ false, false, !_autoSync && masterController.dirty, false, false, false ] showAlternateIcon: [ false, false, masterController.dirty, false, false, false ]
rotateImage: [ false, false, masterController.syncInProgress, false, false, false ] rotateImage: [ false, false, masterController.syncInProgress, false, false, false ]
animateImage: [ false, false, !_autoSync && masterController.dirty, false, false, false ] animateImage: [ false, false, masterController.dirty, false, false, false ]
buttonEnabled: [ true, true, !masterController.syncInProgress, true, true, true ] buttonEnabled: [ true, true, !masterController.syncInProgress, true, true, true ]
buttonVisible: [ true, true, true, true, _showZoom, _showZoom ] buttonVisible: [ true, true, true, true, _showZoom, _showZoom ]
maxHeight: mapScale.y - toolStrip.y maxHeight: mapScale.y - toolStrip.y
......
...@@ -36,6 +36,7 @@ const char* AppSettings::automaticMissionUploadName = "Automat ...@@ -36,6 +36,7 @@ const char* AppSettings::automaticMissionUploadName = "Automat
const char* AppSettings::parameterFileExtension = "params"; const char* AppSettings::parameterFileExtension = "params";
const char* AppSettings::planFileExtension = "plan"; const char* AppSettings::planFileExtension = "plan";
const char* AppSettings::missionFileExtension = "mission"; const char* AppSettings::missionFileExtension = "mission";
const char* AppSettings::waypointsFileExtension = "waypoints";
const char* AppSettings::fenceFileExtension = "fence"; const char* AppSettings::fenceFileExtension = "fence";
const char* AppSettings::rallyPointFileExtension = "rally"; const char* AppSettings::rallyPointFileExtension = "rally";
const char* AppSettings::telemetryFileExtension = "tlog"; const char* AppSettings::telemetryFileExtension = "tlog";
......
...@@ -42,6 +42,7 @@ public: ...@@ -42,6 +42,7 @@ public:
Q_PROPERTY(QString planFileExtension MEMBER planFileExtension CONSTANT) Q_PROPERTY(QString planFileExtension MEMBER planFileExtension CONSTANT)
Q_PROPERTY(QString missionFileExtension MEMBER missionFileExtension CONSTANT) Q_PROPERTY(QString missionFileExtension MEMBER missionFileExtension CONSTANT)
Q_PROPERTY(QString waypointsFileExtension MEMBER waypointsFileExtension CONSTANT)
Q_PROPERTY(QString parameterFileExtension MEMBER parameterFileExtension CONSTANT) Q_PROPERTY(QString parameterFileExtension MEMBER parameterFileExtension CONSTANT)
Q_PROPERTY(QString telemetryFileExtension MEMBER telemetryFileExtension CONSTANT) Q_PROPERTY(QString telemetryFileExtension MEMBER telemetryFileExtension CONSTANT)
...@@ -89,6 +90,7 @@ public: ...@@ -89,6 +90,7 @@ public:
static const char* parameterFileExtension; static const char* parameterFileExtension;
static const char* planFileExtension; static const char* planFileExtension;
static const char* missionFileExtension; static const char* missionFileExtension;
static const char* waypointsFileExtension;
static const char* fenceFileExtension; static const char* fenceFileExtension;
static const char* rallyPointFileExtension; static const char* rallyPointFileExtension;
static const char* telemetryFileExtension; static const char* telemetryFileExtension;
......
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