Unverified Commit 3b4a9ca9 authored by Don Gagne's avatar Don Gagne Committed by GitHub

Merge pull request #8005 from DonLakeFlyer/ParamProgress

Param progress bar and other stuff
parents afcc3fb6 d9bbe9bd
......@@ -94,6 +94,63 @@ ParameterManager::~ParameterManager()
delete _parameterMetaData;
}
void ParameterManager::_updateProgressBar(void)
{
int waitingReadParamIndexCount = 0;
int waitingReadParamNameCount = 0;
int waitingWriteParamCount = 0;
for (int compId: _waitingReadParamIndexMap.keys()) {
waitingReadParamIndexCount += _waitingReadParamIndexMap[compId].count();
}
for(int compId: _waitingReadParamNameMap.keys()) {
waitingReadParamNameCount += _waitingReadParamNameMap[compId].count();
}
for(int compId: _waitingWriteParamNameMap.keys()) {
waitingWriteParamCount += _waitingWriteParamNameMap[compId].count();
}
if (waitingReadParamIndexCount == 0) {
if (_readParamIndexProgressActive) {
_readParamIndexProgressActive = false;
_setLoadProgress(0.0);
return;
}
} else {
_readParamIndexProgressActive = true;
_setLoadProgress((double)(_totalParamCount - waitingReadParamIndexCount) / (double)_totalParamCount);
return;
}
if (waitingWriteParamCount == 0) {
if (_writeParamProgressActive) {
_writeParamProgressActive = false;
_waitingWriteParamBatchCount = 0;
_setLoadProgress(0.0);
emit pendingWritesChanged(false);
return;
}
} else {
_writeParamProgressActive = true;
_setLoadProgress((double)(qMax(_waitingWriteParamBatchCount - waitingWriteParamCount, 1)) / (double)(_waitingWriteParamBatchCount + 1));
emit pendingWritesChanged(true);
return;
}
if (waitingReadParamNameCount == 0) {
if (_readParamNameProgressActive) {
_readParamNameProgressActive = false;
_waitingReadParamNameBatchCount = 0;
_setLoadProgress(0.0);
return;
}
} else {
_readParamNameProgressActive = true;
_setLoadProgress((double)(qMax(_waitingReadParamNameBatchCount - waitingReadParamNameCount, 1)) / (double)(_waitingReadParamNameBatchCount + 1));
return;
}
}
/// Called whenever a parameter is updated or first seen.
void ParameterManager::_parameterUpdate(int vehicleId, int componentId, QString parameterName, int parameterCount, int parameterId, int mavType, QVariant value)
{
......@@ -262,17 +319,8 @@ void ParameterManager::_parameterUpdate(int vehicleId, int componentId, QString
qCDebug(ParameterManagerVerbose1Log) << _logVehiclePrefix(-1) << "Not restarting _waitingParamTimeoutTimer (all requests satisfied)";
}
}
// Update progress bar for waiting reads
if (readWaitingParamCount == 0) {
// We are no longer waiting for any reads to complete
if (_prevWaitingReadParamIndexCount + _prevWaitingReadParamNameCount != 0) {
// Set progress to 0 if not already there
_setLoadProgress(0.0);
}
} else {
_setLoadProgress((double)(_totalParamCount - readWaitingParamCount) / (double)_totalParamCount);
}
\
_updateProgressBar();
// Get parameter set version
if (!_versionParam.isEmpty() && _versionParam == parameterName) {
......@@ -389,8 +437,13 @@ void ParameterManager::_valueUpdated(const QVariant& value)
_dataMutex.lock();
if (_waitingWriteParamNameMap.contains(componentId)) {
_waitingWriteParamNameMap[componentId].remove(name); // Remove any old entry
_waitingWriteParamNameMap[componentId][name] = 0; // Add new entry and set retry count
if (_waitingWriteParamNameMap[componentId].contains(name)) {
_waitingWriteParamNameMap[componentId].remove(name);
} else {
_waitingWriteParamBatchCount++;
}
_waitingWriteParamNameMap[componentId][name] = 0; // Add new entry and set retry count
_updateProgressBar();
_waitingParamTimeoutTimer.start();
_saveRequired = true;
} else {
......@@ -466,8 +519,13 @@ void ParameterManager::refreshParameter(int componentId, const QString& name)
if (_waitingReadParamNameMap.contains(componentId)) {
QString mappedParamName = _remapParamNameToVersion(name);
_waitingReadParamNameMap[componentId].remove(mappedParamName); // Remove old wait entry if there
if (_waitingReadParamNameMap[componentId].contains(mappedParamName)) {
_waitingReadParamNameMap[componentId].remove(mappedParamName);
} else {
_waitingReadParamNameBatchCount++;
}
_waitingReadParamNameMap[componentId][mappedParamName] = 0; // Add new wait entry and update retry count
_updateProgressBar();
qCDebug(ParameterManagerLog) << _logVehiclePrefix(componentId) << "restarting _waitingParamTimeout";
_waitingParamTimeoutTimer.start();
} else {
......@@ -896,7 +954,8 @@ void ParameterManager::_tryCacheHashLoad(int vehicleId, int componentId, QVarian
QString ParameterManager::readParametersFromStream(QTextStream& stream)
{
QString errors;
QString missingErrors;
QString typeErrors;
while (!stream.atEnd()) {
QString line = stream.readLine();
......@@ -915,18 +974,18 @@ QString ParameterManager::readParametersFromStream(QTextStream& stream)
if (!parameterExists(componentId, paramName)) {
QString error;
error = QString("Skipped parameter %1:%2 - does not exist on this vehicle\n").arg(componentId).arg(paramName);
errors += error;
qCDebug(ParameterManagerLog) << error;
error += QStringLiteral("%1:%2 ").arg(componentId).arg(paramName);
missingErrors += error;
qCDebug(ParameterManagerLog) << QStringLiteral("Skipped due to missing: %1").arg(error);
continue;
}
Fact* fact = getParameter(componentId, paramName);
if (fact->type() != _mavTypeToFactType((MAV_PARAM_TYPE)mavType)) {
QString error;
error = QString("Skipped parameter %1:%2 - type mismatch %3:%4\n").arg(componentId).arg(paramName).arg(fact->type()).arg(_mavTypeToFactType((MAV_PARAM_TYPE)mavType));
errors += error;
qCDebug(ParameterManagerLog) << error;
error = QStringLiteral("%1:%2 ").arg(componentId).arg(paramName);
typeErrors += error;
qCDebug(ParameterManagerLog) << QStringLiteral("Skipped due to type mismatch: %1").arg(error);
continue;
}
......@@ -936,6 +995,16 @@ QString ParameterManager::readParametersFromStream(QTextStream& stream)
}
}
QString errors;
if (!missingErrors.isEmpty()) {
errors = tr("Parameters not loaded since they are not currently on the vehicle: %1\n").arg(missingErrors);
}
if (!typeErrors.isEmpty()) {
errors += tr("Parameters not loaded due to type mismatch: %1").arg(typeErrors);
}
return errors;
}
......@@ -1579,11 +1648,24 @@ QString ParameterManager::_logVehiclePrefix(int componentId)
void ParameterManager::_setLoadProgress(double loadProgress)
{
_loadProgress = loadProgress;
emit loadProgressChanged(static_cast<float>(loadProgress));
if (_loadProgress != loadProgress) {
_loadProgress = loadProgress;
emit loadProgressChanged(static_cast<float>(loadProgress));
}
}
QList<int> ParameterManager::componentIds(void)
{
return _paramCountMap.keys();
}
bool ParameterManager::pendingWrites(void)
{
for (int compId: _waitingWriteParamNameMap.keys()) {
if (_waitingWriteParamNameMap[compId].count()) {
return true;
}
}
return false;
}
......@@ -39,6 +39,7 @@ public:
Q_PROPERTY(bool parametersReady READ parametersReady NOTIFY parametersReadyChanged) ///< true: Parameters are ready for use
Q_PROPERTY(bool missingParameters READ missingParameters NOTIFY missingParametersChanged) ///< true: Parameters are missing from firmware response, false: all parameters received from firmware
Q_PROPERTY(double loadProgress READ loadProgress NOTIFY loadProgressChanged)
Q_PROPERTY(bool pendingWrites READ pendingWrites NOTIFY pendingWritesChanged) ///< true: There are still pending write updates against the vehicle
bool parametersReady (void) const { return _parametersReady; }
bool missingParameters (void) const { return _missingParameters; }
......@@ -111,12 +112,15 @@ public:
/// @return true: success, false: failure (errorString set)
bool loadFromJson(const QJsonObject& json, bool required, QString& errorString);
bool pendingWrites(void);
Vehicle* vehicle(void) { return _vehicle; }
signals:
void parametersReadyChanged(bool parametersReady);
void missingParametersChanged(bool missingParameters);
void loadProgressChanged(float value);
void parametersReadyChanged (bool parametersReady);
void missingParametersChanged (bool missingParameters);
void loadProgressChanged (float value);
void pendingWritesChanged (bool pendingWrites);
protected:
Vehicle* _vehicle;
......@@ -146,6 +150,7 @@ private:
QString _logVehiclePrefix(int componentId);
void _setLoadProgress(double loadProgress);
bool _fillIndexBatchQueue(bool waitingParamTimeout);
void _updateProgressBar(void);
MAV_PARAM_TYPE _factTypeToMavType(FactMetaData::ValueType_t factType);
FactMetaData::ValueType_t _mavTypeToFactType(MAV_PARAM_TYPE mavType);
......@@ -178,9 +183,13 @@ private:
QMap<int /* component id */, QMap<QString /* param name */, bool /* seen */>> _debugCacheParamSeen;
// Wait counts from previous parameter update cycle
int _prevWaitingReadParamIndexCount;
int _prevWaitingReadParamNameCount;
int _prevWaitingWriteParamNameCount;
int _prevWaitingReadParamIndexCount;
int _prevWaitingReadParamNameCount;
int _prevWaitingWriteParamNameCount;
bool _readParamIndexProgressActive = false;
bool _readParamNameProgressActive = false;
bool _writeParamProgressActive = false;
static const int _maxInitialRequestListRetry = 4; ///< Maximum retries for request list
int _initialRequestRetryCount; ///< Current retry count for request list
......@@ -197,7 +206,9 @@ private:
QMap<int, QMap<QString, int> > _waitingWriteParamNameMap; ///< Key: Component id, Value: Map { Key: parameter name still waiting for, Value: retry count }
QMap<int, QList<int> > _failedReadParamIndexMap; ///< Key: Component id, Value: failed parameter index
int _totalParamCount; ///< Number of parameters across all components
int _totalParamCount; ///< Number of parameters across all components
int _waitingWriteParamBatchCount = 0; ///< Number of parameters which are batched up waiting on write responses
int _waitingReadParamNameBatchCount = 0; ///< Number of parameters which are batched up waiting on read responses
QTimer _initialRequestTimeoutTimer;
QTimer _waitingParamTimeoutTimer;
......
......@@ -158,12 +158,8 @@ static QObject* shapeFileHelperSingletonFactory(QQmlEngine*, QJSEngine*)
}
QGCApplication::QGCApplication(int &argc, char* argv[], bool unitTesting)
#if defined(__mobile__)
: QGuiApplication (argc, argv)
#else
: QApplication (argc, argv)
#endif
, _runningUnitTests (unitTesting)
: QGuiApplication (argc, argv)
, _runningUnitTests (unitTesting)
{
_app = this;
_msecsElapsedTime.start();
......
......@@ -7,17 +7,7 @@
*
****************************************************************************/
/**
* @file
* @brief Definition of main class
*
* @author Lorenz Meier <mavteam@student.ethz.ch>
*
*/
#ifndef QGCAPPLICATION_H
#define QGCAPPLICATION_H
#pragma once
#include <QApplication>
#include <QTimer>
......@@ -45,21 +35,7 @@ class QGCSingleton;
class QGCToolbox;
class QGCFileDownload;
/**
* @brief The main application and management class.
*
* This class is started by the main method and provides
* the central management unit of the groundstation application.
*
* Needs QApplication base to support QtCharts drawing module and
* avoid application crashing on 5.12. Enforce no widget on mobile
**/
class QGCApplication :
#if defined(__mobile__)
public QGuiApplication
#else
public QApplication
#endif
class QGCApplication : public QGuiApplication
{
Q_OBJECT
......@@ -214,5 +190,3 @@ private:
/// @brief Returns the QGCApplication object singleton.
QGCApplication* qgcApp(void);
#endif
......@@ -32,10 +32,8 @@ Item {
property var _appSettings: QGroundControl.settingsManager.appSettings
ParameterEditorController {
id: controller;
onShowErrorMessage: {
mainWindow.showMessageDialog(qsTr("Parameter Editor"), qsTr("Parameter Load Errors"))
}
id: controller
onShowErrorMessage: mainWindow.showMessageDialog(qsTr("Parameter Load Errors"), errorMsg)
}
ExclusiveGroup { id: sectionGroup }
......
......@@ -196,47 +196,66 @@ ApplicationWindow {
mainWindow.close()
}
// On attempting an application close we check for:
// Unsaved missions - then
// Pending parameter writes - then
// Active connections
onClosing: {
if (!_forceClose) {
unsavedMissionCloseDialog.check()
close.accepted = false
}
}
MessageDialog {
id: activeConnectionsCloseDialog
id: unsavedMissionCloseDialog
title: qsTr("%1 close").arg(QGroundControl.appName)
text: qsTr("There are still active connections to vehicles. Are you sure you want to exit?")
standardButtons: StandardButton.Yes | StandardButton.Cancel
text: qsTr("You have a mission edit in progress which has not been saved/sent. If you close you will lose changes. Are you sure you want to close?")
standardButtons: StandardButton.Yes | StandardButton.No
modality: Qt.ApplicationModal
visible: false
onYes: finishCloseProcess()
onYes: pendingParameterWritesCloseDialog.check()
function check() {
if (QGroundControl.multiVehicleManager.activeVehicle) {
activeConnectionsCloseDialog.open()
if (planMasterControllerPlan && planMasterControllerPlan.dirty) {
unsavedMissionCloseDialog.open()
} else {
finishCloseProcess()
pendingParameterWritesCloseDialog.check()
}
}
}
//-------------------------------------------------------------------------
//-- Check for unsaved missions
onClosing: {
// Check first for unsaved missions and active connections
if (!_forceClose) {
unsavedMissionCloseDialog.check()
close.accepted = false
MessageDialog {
id: pendingParameterWritesCloseDialog
title: qsTr("%1 close").arg(QGroundControl.appName)
text: qsTr("You have pending parameter updates to a vehicle. If you close you will lose changes. Are you sure you want to close?")
standardButtons: StandardButton.Yes | StandardButton.No
modality: Qt.ApplicationModal
visible: false
onYes: activeConnectionsCloseDialog.check()
function check() {
for (var index=0; index<QGroundControl.multiVehicleManager.vehicles.count; index++) {
if (QGroundControl.multiVehicleManager.vehicles.get(index).parameterManager.pendingWrites) {
pendingParameterWritesCloseDialog.open()
return
}
}
activeConnectionsCloseDialog.check()
}
}
MessageDialog {
id: unsavedMissionCloseDialog
id: activeConnectionsCloseDialog
title: qsTr("%1 close").arg(QGroundControl.appName)
text: qsTr("You have a mission edit in progress which has not been saved/sent. If you close you will lose changes. Are you sure you want to close?")
standardButtons: StandardButton.Yes | StandardButton.No
text: qsTr("There are still active connections to vehicles. Are you sure you want to exit?")
standardButtons: StandardButton.Yes | StandardButton.Cancel
modality: Qt.ApplicationModal
visible: false
onYes: activeConnectionsCloseDialog.check()
onYes: finishCloseProcess()
function check() {
if (planMasterControllerPlan && planMasterControllerPlan.dirty) {
unsavedMissionCloseDialog.open()
if (QGroundControl.multiVehicleManager.activeVehicle) {
activeConnectionsCloseDialog.open()
} else {
activeConnectionsCloseDialog.check()
finishCloseProcess()
}
}
}
......
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