From 92b353bd7f0c6c51674828ee6ca115a8637e5f41 Mon Sep 17 00:00:00 2001 From: Don Gagne Date: Sat, 28 May 2016 18:15:12 -0700 Subject: [PATCH] Rework param loading --- qgroundcontrol.pro | 2 - .../APM/APMAirframeComponent.qml | 10 +- .../APM/APMAirframeComponentController.cc | 87 +++++++-- .../APM/APMAirframeComponentController.h | 15 +- .../APM/APMAutoPilotPlugin.cc | 1 - .../APM/APMRemoteParamsDownloader.cc | 180 ------------------ .../APM/APMRemoteParamsDownloader.h | 48 ----- 7 files changed, 80 insertions(+), 263 deletions(-) delete mode 100644 src/AutoPilotPlugins/APM/APMRemoteParamsDownloader.cc delete mode 100644 src/AutoPilotPlugins/APM/APMRemoteParamsDownloader.h diff --git a/qgroundcontrol.pro b/qgroundcontrol.pro index 68a33709c..d3265a21a 100644 --- a/qgroundcontrol.pro +++ b/qgroundcontrol.pro @@ -310,7 +310,6 @@ HEADERS += \ src/AutoPilotPlugins/PX4/PX4AirframeLoader.h \ src/AutoPilotPlugins/APM/APMAirframeLoader.h \ src/QmlControls/QGCImageProvider.h \ - src/AutoPilotPlugins/APM/APMRemoteParamsDownloader.h \ src/QtLocationPlugin/QMLControl/QGCMapEngineManager.h \ src/PositionManager/PositionManager.h @@ -463,7 +462,6 @@ SOURCES += \ src/AutoPilotPlugins/PX4/PX4AirframeLoader.cc \ src/AutoPilotPlugins/APM/APMAirframeLoader.cc \ src/QmlControls/QGCImageProvider.cc \ - src/AutoPilotPlugins/APM/APMRemoteParamsDownloader.cc \ src/QtLocationPlugin/QMLControl/QGCMapEngineManager.cc \ src/PositionManager/SimulatedPosition.cc \ src/PositionManager/PositionManager.cpp diff --git a/src/AutoPilotPlugins/APM/APMAirframeComponent.qml b/src/AutoPilotPlugins/APM/APMAirframeComponent.qml index 19c73883d..e0786e19a 100644 --- a/src/AutoPilotPlugins/APM/APMAirframeComponent.qml +++ b/src/AutoPilotPlugins/APM/APMAirframeComponent.qml @@ -61,9 +61,6 @@ QGCView { onCurrentAirframeTypeChanged: { airframePicker.model = controller.currentAirframeType.airframes; } - onCurrentAirframeChanged : { - hideDialog(); - } } QGCLabel { @@ -73,7 +70,7 @@ QGCView { anchors.right: parent.right anchors.margins: _margins wrapMode: Text.WordWrap - text: qsTr("Select you drone to load the default parameters for it. ") + text: qsTr("Select your drone to load the default parameters for it. ") } Flow { @@ -95,7 +92,10 @@ QGCView { height: (ScreenTools.defaultFontPixelHeight * 14) / 5 text: controller.currentAirframeType.airframes[index].name; - onClicked : controller.currentAirframe = controller.currentAirframeType.airframes[index] + onClicked : { + controller.loadParameters(controller.currentAirframeType.airframes[index].params) + hideDialog() + } } } } diff --git a/src/AutoPilotPlugins/APM/APMAirframeComponentController.cc b/src/AutoPilotPlugins/APM/APMAirframeComponentController.cc index e84640fc7..dcddd953b 100644 --- a/src/AutoPilotPlugins/APM/APMAirframeComponentController.cc +++ b/src/AutoPilotPlugins/APM/APMAirframeComponentController.cc @@ -26,16 +26,18 @@ #include "APMAirframeComponentController.h" #include "APMAirframeComponentAirframes.h" -#include "APMRemoteParamsDownloader.h" #include "QGCMAVLink.h" #include "MultiVehicleManager.h" #include "AutoPilotPluginManager.h" #include "QGCApplication.h" +#include "QGCFileDownload.h" #include #include #include #include +#include +#include bool APMAirframeComponentController::_typesRegistered = false; @@ -94,12 +96,14 @@ void APMAirframeComponentController::_fillAirFrames() emit loadAirframesCompleted(); } -void APMAirframeComponentController::_finishVehicleSetup() { - QDir dataLocation = QStandardPaths::standardLocations(QStandardPaths::AppDataLocation).at(0) - + QDir::separator() + qApp->applicationName(); - - QFile parametersFile(dataLocation.absoluteFilePath(_currentAirframe->params())); - parametersFile.open(QIODevice::ReadOnly); +void APMAirframeComponentController::_loadParametersFromDownloadFile(const QString& downloadedParamFile) +{ + QFile parametersFile(downloadedParamFile); + if (!parametersFile.open(QIODevice::ReadOnly | QIODevice::Text)) { + qWarning() << "Unable to open downloaded parameter file" << downloadedParamFile << parametersFile.errorString(); + qgcApp()->restoreOverrideCursor(); + return; + } QTextStream reader(¶metersFile); @@ -115,9 +119,7 @@ void APMAirframeComponentController::_finishVehicleSetup() { param->setRawValue(QVariant::fromValue(aux.at(1))); } } - qgcApp()->setOverrideCursor(Qt::ArrowCursor); - sender()->deleteLater(); - emit currentAirframeChanged(_currentAirframe); + qgcApp()->restoreOverrideCursor(); } APMAirframeType::APMAirframeType(const QString& name, const QString& imageResource, int type, QObject* parent) : @@ -193,23 +195,68 @@ QString APMAirframeComponentController::currentAirframeTypeName() const return _vehicle->vehicleTypeName(); } -APMAirframe *APMAirframeComponentController::currentAirframe() const +void APMAirframeComponentController::setCurrentAirframeType(APMAirframeType *t) { - return _currentAirframe; + Fact *param = getParameterFact(-1, QStringLiteral("FRAME")); + Q_ASSERT(param); + param->setRawValue(t->type()); } -void APMAirframeComponentController::setCurrentAirframe(APMAirframe *t) +void APMAirframeComponentController::loadParameters(const QString& paramFile) { - _currentAirframe = t; qgcApp()->setOverrideCursor(Qt::WaitCursor); - APMRemoteParamsDownloader *paramDownloader = new APMRemoteParamsDownloader(_currentAirframe->params()); - connect(paramDownloader, &APMRemoteParamsDownloader::finished, this, &APMAirframeComponentController::_finishVehicleSetup); + + QString paramFileUrl = QStringLiteral("https://api.github.com/repos/ArduPilot/ardupilot/contents/Tools/Frame_params/%1?ref=master"); + + QGCFileDownload* downloader = new QGCFileDownload(this); + connect(downloader, &QGCFileDownload::downloadFinished, this, &APMAirframeComponentController::_githubJsonDownloadFinished); + connect(downloader, &QGCFileDownload::error, this, &APMAirframeComponentController::_githubJsonDownloadError); + downloader->download(paramFileUrl.arg(paramFile)); } -void APMAirframeComponentController::setCurrentAirframeType(APMAirframeType *t) +void APMAirframeComponentController::_githubJsonDownloadFinished(QString remoteFile, QString localFile) { - Fact *param = getParameterFact(-1, QStringLiteral("FRAME")); - Q_ASSERT(param); - param->setRawValue(t->type()); + Q_UNUSED(remoteFile); + + QFile jsonFile(localFile); + if (!jsonFile.open(QIODevice::ReadOnly | QIODevice::Text)) { + qWarning() << "Unable to open github json file" << localFile << jsonFile.errorString(); + qgcApp()->restoreOverrideCursor(); + return; + } + QByteArray bytes = jsonFile.readAll(); + jsonFile.close(); + + QJsonParseError jsonParseError; + QJsonDocument doc = QJsonDocument::fromJson(bytes, &jsonParseError); + if (jsonParseError.error != QJsonParseError::NoError) { + qWarning() << "Unable to open json document" << localFile << jsonParseError.errorString(); + qgcApp()->restoreOverrideCursor(); + return; + } + QJsonObject json = doc.object(); + + QGCFileDownload* downloader = new QGCFileDownload(this); + connect(downloader, &QGCFileDownload::downloadFinished, this, &APMAirframeComponentController::_paramFileDownloadFinished); + connect(downloader, &QGCFileDownload::error, this, &APMAirframeComponentController::_paramFileDownloadError); + downloader->download(json["download_url"].toString()); +} + +void APMAirframeComponentController::_githubJsonDownloadError(QString errorMsg) +{ + qgcApp()->showMessage(tr("Param file github json download failed: % 1").arg(errorMsg)); + qgcApp()->restoreOverrideCursor(); } +void APMAirframeComponentController::_paramFileDownloadFinished(QString remoteFile, QString localFile) +{ + Q_UNUSED(remoteFile); + + _loadParametersFromDownloadFile(localFile); +} + +void APMAirframeComponentController::_paramFileDownloadError(QString errorMsg) +{ + qgcApp()->showMessage(tr("Param file download failed: % 1").arg(errorMsg)); + qgcApp()->restoreOverrideCursor(); +} diff --git a/src/AutoPilotPlugins/APM/APMAirframeComponentController.h b/src/AutoPilotPlugins/APM/APMAirframeComponentController.h index 613f55dc2..514420572 100644 --- a/src/AutoPilotPlugins/APM/APMAirframeComponentController.h +++ b/src/AutoPilotPlugins/APM/APMAirframeComponentController.h @@ -58,7 +58,8 @@ public: Q_PROPERTY(QmlObjectListModel* airframeTypesModel MEMBER _airframeTypesModel CONSTANT) Q_PROPERTY(APMAirframeType* currentAirframeType READ currentAirframeType WRITE setCurrentAirframeType NOTIFY currentAirframeTypeChanged) - Q_PROPERTY(APMAirframe* currentAirframe READ currentAirframe WRITE setCurrentAirframe NOTIFY currentAirframeChanged) + + Q_INVOKABLE void loadParameters(const QString& paramFile); int currentAirframeIndex(void); void setCurrentAirframeIndex(int newIndex); @@ -66,25 +67,25 @@ public: signals: void loadAirframesCompleted(); void currentAirframeTypeChanged(APMAirframeType* airframeType); - void currentAirframeChanged(APMAirframe* airframe); public slots: APMAirframeType *currentAirframeType() const; Q_INVOKABLE QString currentAirframeTypeName() const; - APMAirframe *currentAirframe() const; void setCurrentAirframeType(APMAirframeType *t); - void setCurrentAirframe(APMAirframe *t); private slots: void _fillAirFrames(void); - void _finishVehicleSetup(void); void _factFrameChanged(QVariant v); + void _githubJsonDownloadFinished(QString remoteFile, QString localFile); + void _githubJsonDownloadError(QString errorMsg); + void _paramFileDownloadFinished(QString remoteFile, QString localFile); + void _paramFileDownloadError(QString errorMsg); private: + void _loadParametersFromDownloadFile(const QString& downloadedParamFile); + static bool _typesRegistered; APMAirframeType *_currentAirframeType; - APMAirframe *_currentAirframe; - int _waitParamWriteSignalCount; QmlObjectListModel *_airframeTypesModel; }; diff --git a/src/AutoPilotPlugins/APM/APMAutoPilotPlugin.cc b/src/AutoPilotPlugins/APM/APMAutoPilotPlugin.cc index 0476d41f1..de6661354 100644 --- a/src/AutoPilotPlugins/APM/APMAutoPilotPlugin.cc +++ b/src/AutoPilotPlugins/APM/APMAutoPilotPlugin.cc @@ -32,7 +32,6 @@ #include "APMAirframeComponentAirframes.h" #include "APMAirframeComponentController.h" #include "APMAirframeLoader.h" -#include "APMRemoteParamsDownloader.h" #include "APMFlightModesComponent.h" #include "APMRadioComponent.h" #include "APMSafetyComponent.h" diff --git a/src/AutoPilotPlugins/APM/APMRemoteParamsDownloader.cc b/src/AutoPilotPlugins/APM/APMRemoteParamsDownloader.cc deleted file mode 100644 index 8ab34de35..000000000 --- a/src/AutoPilotPlugins/APM/APMRemoteParamsDownloader.cc +++ /dev/null @@ -1,180 +0,0 @@ -/*===================================================================== - - QGroundControl Open Source Ground Control Station - - (c) 2009 - 2014 QGROUNDCONTROL PROJECT - - This file is part of the QGROUNDCONTROL project - - QGROUNDCONTROL is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - QGROUNDCONTROL is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with QGROUNDCONTROL. If not, see . - - ======================================================================*/ - -#include "APMRemoteParamsDownloader.h" - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "APMRemoteParamsDownloader.h" - -#define FRAME_PARAMS_LIST QUrl("https://api.github.com/repos/diydrones/ardupilot/contents/Tools/Frame_params") -#define FRAME_PARAMS_URL "https://raw.github.com/diydrones/ardupilot/master/Tools/Frame_params/" - -static QString dataLocation; - -APMRemoteParamsDownloader::APMRemoteParamsDownloader(const QString& file) : - m_fileToDownload(file), - m_networkReply(NULL), - m_downloadedParamFile(NULL) -{ - dataLocation = QStandardPaths::standardLocations(QStandardPaths::AppDataLocation).at(0) - + QDir::separator() + qApp->applicationName(); - refreshParamList(); -} - -QString APMRemoteParamsDownloader::statusText() const -{ - return m_statusText; -} -void APMRemoteParamsDownloader::setStatusText(const QString& text) -{ - m_statusText = text; -} - -void APMRemoteParamsDownloader::refreshParamList() -{ - setStatusText(tr("Refresh Param file list")); - - QUrl url = FRAME_PARAMS_LIST; - m_networkReply->deleteLater(); - m_networkReply = m_networkAccessManager.get(QNetworkRequest(url)); - connect(m_networkReply, &QNetworkReply::finished, this, &APMRemoteParamsDownloader::httpParamListFinished); - connect(m_networkReply, &QNetworkReply::downloadProgress, this, &APMRemoteParamsDownloader::updateDataReadProgress); -} - -/* Returned Json Example - "_links": { - "git":"https://api.github.com/repos/diydrones/ardupilot/git/blobs/a7074e606d695566f9a8c87724ad52e5e3baba7d", - "html":"https://github.com/diydrones/ardupilot/blob/master/Tools/Frame_params/Parrot_Bebop.param", - "self":"https://api.github.com/repos/diydrones/ardupilot/contents/Tools/Frame_params/Parrot_Bebop.param?ref=master" - }, - "download_url":"https://raw.githubusercontent.com/diydrones/ardupilot/master/Tools/Frame_params/Parrot_Bebop.param", - "git_url":"https://api.github.com/repos/diydrones/ardupilot/git/blobs/a7074e606d695566f9a8c87724ad52e5e3baba7d", - "html_url":"https://github.com/diydrones/ardupilot/blob/master/Tools/Frame_params/Parrot_Bebop.param", - "name":"Parrot_Bebop.param","path":"Tools/Frame_params/Parrot_Bebop.param","" - "sha":"a7074e606d695566f9a8c87724ad52e5e3baba7d", - "size":533, - "type":"file", - "url":"https://api.github.com/repos/diydrones/ardupilot/contents/Tools/Frame_params/Parrot_Bebop.param?ref=master" -*/ -void APMRemoteParamsDownloader::startFileDownloadRequest() -{ - QUrl url; - - QJsonObject obj; - - // Find the correct file from the json file list. - while(curr != end) { - obj = (*curr).toObject(); - url = QUrl(obj["download_url"].toString()); - QString name = obj["name"].toString(); - if (name == m_fileToDownload) { - break; - } - curr++; - } - if (curr == end) - return; - - QDir parameterDir(dataLocation); - if (!parameterDir.exists()) - parameterDir.mkpath(dataLocation); - - QString filename = parameterDir.absoluteFilePath(obj["name"].toString()); - - if(m_downloadedParamFile) - m_downloadedParamFile->deleteLater(); - m_downloadedParamFile = new QFile(filename); - m_downloadedParamFile->open(QIODevice::WriteOnly); - - m_networkReply = m_networkAccessManager.get(QNetworkRequest(url)); - connect(m_networkReply, &QNetworkReply::finished, this, &APMRemoteParamsDownloader::httpFinished); - connect(m_networkReply, &QNetworkReply::readyRead, this, &APMRemoteParamsDownloader::httpReadyRead); - connect(m_networkReply, &QNetworkReply::downloadProgress, this, &APMRemoteParamsDownloader::updateDataReadProgress); - curr++; -} - -void APMRemoteParamsDownloader::httpFinished() -{ - m_downloadedParamFile->flush(); - m_downloadedParamFile->close(); - - if (m_networkReply->error()) { - m_downloadedParamFile->remove(); - setStatusText(tr("Download failed: %1.").arg(m_networkReply->errorString())); - } - - m_networkReply->deleteLater(); - m_networkReply = NULL; - delete m_downloadedParamFile; - m_downloadedParamFile = NULL; - - emit finished(); -} - -void APMRemoteParamsDownloader::httpReadyRead() -{ - if (m_downloadedParamFile) - m_downloadedParamFile->write(m_networkReply->readAll()); -} - -void APMRemoteParamsDownloader::updateDataReadProgress(qint64 bytesRead, qint64 totalBytes) -{ - Q_UNUSED(bytesRead); - Q_UNUSED(totalBytes); -} - -void APMRemoteParamsDownloader::httpParamListFinished() -{ - if (m_networkReply->error()) { - qDebug() << "Download failed:" << m_networkReply->errorString(); - return; - } - processDownloadedVersionObject(m_networkReply->readAll()); - startFileDownloadRequest(); -} - -void APMRemoteParamsDownloader::processDownloadedVersionObject(const QByteArray &listObject) -{ - QJsonParseError jsonErrorChecker; - QJsonDocument jsonDocument = QJsonDocument::fromJson(listObject, &jsonErrorChecker); - if (jsonErrorChecker.error != QJsonParseError::NoError) { - qDebug() << "Json error while parsing document:" << jsonErrorChecker.errorString(); - return; - } - - m_documentArray = jsonDocument.array(); - curr = m_documentArray.constBegin(); - end = m_documentArray.constEnd(); -} diff --git a/src/AutoPilotPlugins/APM/APMRemoteParamsDownloader.h b/src/AutoPilotPlugins/APM/APMRemoteParamsDownloader.h deleted file mode 100644 index e22a4b137..000000000 --- a/src/AutoPilotPlugins/APM/APMRemoteParamsDownloader.h +++ /dev/null @@ -1,48 +0,0 @@ -#ifndef APMREMOTEPARAMSCONTROLLER_H -#define APMREMOTEPARAMSCONTROLLER_H - -#include -#include -#include -#include - -class QNetworkReply; -class QFile; -class QUrl; - -class APMRemoteParamsDownloader : public QObject -{ - Q_OBJECT - Q_PROPERTY(QString statusText READ statusText) -public: - explicit APMRemoteParamsDownloader(const QString& file); - QString statusText() const; - void refreshParamList(); - void httpParamListFinished(); - void httpFinished(); - void httpReadyRead(); - void updateDataReadProgress(qint64 bytesRead, qint64 totalBytes); - -private: - void setStatusText(const QString& text); - void startFileDownloadRequest(); - void manualListSetup(); - void processDownloadedVersionObject(const QByteArray& listObject); - void startDownloadingRemoteParams(); - -signals: - void finished(); -private: - QString m_fileToDownload; - QString m_statusText; - QNetworkAccessManager m_networkAccessManager; - QNetworkReply* m_networkReply; - QFile* m_downloadedParamFile; - - // the list of needed documents. - QJsonArray m_documentArray; - QJsonArray::const_iterator curr; - QJsonArray::const_iterator end; -}; - -#endif // APMREMOTEPARAMSCONTROLLER_H -- 2.22.0