From 33c9059d721b08984a289a8f563fe7edc55f5294 Mon Sep 17 00:00:00 2001 From: Don Gagne Date: Sat, 5 Dec 2015 21:09:33 -0800 Subject: [PATCH 1/5] Live flight mode config --- .../APM/APMFlightModesComponent.qml | 59 +++------------ .../APM/APMFlightModesComponentController.cc | 87 ++++++---------------- .../APM/APMFlightModesComponentController.h | 29 ++++---- 3 files changed, 48 insertions(+), 127 deletions(-) diff --git a/src/AutoPilotPlugins/APM/APMFlightModesComponent.qml b/src/AutoPilotPlugins/APM/APMFlightModesComponent.qml index 9caf04f..9c2a57e 100644 --- a/src/AutoPilotPlugins/APM/APMFlightModesComponent.qml +++ b/src/AutoPilotPlugins/APM/APMFlightModesComponent.qml @@ -77,11 +77,14 @@ QGCView { Row { spacing: ScreenTools.defaultFontPixelWidth - property int index: modelData + 1 + property int index: modelData + 1 + property var pwmStrings: [ "PWM 0 - 1230", "PWM 1231 - 1360", "PWM 1361 - 1490", "PWM 1491 - 1620", "PWM 1621 - 1749", "PWM 1750 +"] + QGCLabel { anchors.baseline: modeCombo.baseline text: "Flight Mode " + index + ":" + color: controller.activeFlightMode == index ? qgcPal.buttonHighlight : qgcPal.text } FactComboBox { @@ -91,56 +94,9 @@ QGCView { indexModel: false } - QGCCheckBox { - id: simple - anchors.baseline: modeCombo.baseline - text: "Simple Mode" - visible: !controller.fixedWing - checked: isChecked() - - onClicked: { - var simpleFact = controller.getParameterFact(-1, "SIMPLE") - if (checked) { - simpleFact.value |= 1 << modelData - } else { - simpleFact.value &= ~modelData - } - } - - function isChecked() { - if (simple.visible) { - var simpleFact = controller.getParameterFact(-1, "SIMPLE") - return simpleFact.value & (1 << modelData) - } else { - return false; - } - } - } - - QGCCheckBox { - id: superSimple + QGCLabel { anchors.baseline: modeCombo.baseline - text: "Super Simple Mode" - visible: !controller.fixedWing - checked: isChecked() - - onClicked: { - var simpleFact = controller.getParameterFact(-1, "SUPER_SIMPLE") - if (checked) { - simpleFact.value |= 1 << modelData - } else { - simpleFact.value &= ~modelData - } - } - - function isChecked() { - if (superSimple.visible) { - var simpleFact = controller.getParameterFact(-1, "SUPER_SIMPLE") - return simpleFact.value & (1 << modelData) - } else { - return false; - } - } + text: pwmStrings[modelData] } } } // Repeater - Flight Modes @@ -176,6 +132,9 @@ QGCView { QGCLabel { anchors.baseline: optCombo.baseline text: "Channel option " + index + ":" + color: controller.channelOptionEnabled[modelData] ? qgcPal.buttonHighlight : qgcPal.text + + Component.onCompleted: console.log(index, controller.channelOptionEnabled[modelData]) } FactComboBox { diff --git a/src/AutoPilotPlugins/APM/APMFlightModesComponentController.cc b/src/AutoPilotPlugins/APM/APMFlightModesComponentController.cc index b1a3dbe..e6a5f07 100644 --- a/src/AutoPilotPlugins/APM/APMFlightModesComponentController.cc +++ b/src/AutoPilotPlugins/APM/APMFlightModesComponentController.cc @@ -29,7 +29,9 @@ #include APMFlightModesComponentController::APMFlightModesComponentController(void) - : _channelCount(Vehicle::cMaxRcChannels) + : _activeFlightMode(0) + , _channelCount(Vehicle::cMaxRcChannels) + , _fixedWing(_vehicle->vehicleType() == MAV_TYPE_FIXED_WING) { QStringList usedParams; usedParams << "FLTMODE1" << "FLTMODE2" << "FLTMODE3" << "FLTMODE4" << "FLTMODE5" << "FLTMODE6"; @@ -37,78 +39,37 @@ APMFlightModesComponentController::APMFlightModesComponentController(void) return; } - _init(); - _validateConfiguration(); + _rgChannelOptionEnabled << QVariant(false) << QVariant(false) << QVariant(false) << QVariant(false) << QVariant(false) << QVariant(false); connect(_vehicle, &Vehicle::rcChannelsChanged, this, &APMFlightModesComponentController::_rcChannelsChanged); } -void APMFlightModesComponentController::_init(void) +/// Connected to Vehicle::rcChannelsChanged signal +void APMFlightModesComponentController::_rcChannelsChanged(int channelCount, int pwmValues[Vehicle::cMaxRcChannels]) { - _fixedWing = _vehicle->vehicleType() == MAV_TYPE_FIXED_WING; -} + Q_UNUSED(channelCount); -/// This will look for parameter settings which would cause the config to not run correctly. -/// It will set _validConfiguration and _configurationErrors as needed. -void APMFlightModesComponentController::_validateConfiguration(void) -{ - _validConfiguration = true; -#if 0 - - // Make sure switches are valid and within channel range - - QStringList switchParams; - QList switchMappings; - - switchParams << "RC_MAP_MODE_SW" << "RC_MAP_ACRO_SW" << "RC_MAP_POSCTL_SW" << "RC_MAP_LOITER_SW" << "RC_MAP_RETURN_SW" << "RC_MAP_OFFB_SW"; - - for(int i=0; irawValue().toInt(); - switchMappings << map; - - if (map < 0 || map > _channelCount) { - _validConfiguration = false; - _configurationErrors += QString("%1 is set to %2. Mapping must between 0 and %3 (inclusive).\n").arg(switchParams[i]).arg(map).arg(_channelCount); - } - } - - // Make sure mode switches are not double-mapped - - QStringList attitudeParams; - - attitudeParams << "RC_MAP_THROTTLE" << "RC_MAP_YAW" << "RC_MAP_PITCH" << "RC_MAP_ROLL" << "RC_MAP_FLAPS" << "RC_MAP_AUX1" << "RC_MAP_AUX2"; + _activeFlightMode = 0; - for (int i=0; irawValue().toInt(); - - for (int j=0; jrawValue().toFloat(); - if (threshold < 0.0f || threshold > 1.0f) { - _validConfiguration = false; - _configurationErrors += QString("%1 is set to %2. Threshold must between 0.0 and 1.0 (inclusive).\n").arg(thresholdParam).arg(threshold); - } - } -#endif -} + emit activeFlightModeChanged(_activeFlightMode); -/// Connected to Vehicle::rcChannelsChanged signal -void APMFlightModesComponentController::_rcChannelsChanged(int channelCount, int pwmValues[Vehicle::cMaxRcChannels]) -{ - for (int channel=0; channel 1800) { + _rgChannelOptionEnabled[i] = QVariant(true); + } } + emit channelOptionEnabledChanged(); } diff --git a/src/AutoPilotPlugins/APM/APMFlightModesComponentController.h b/src/AutoPilotPlugins/APM/APMFlightModesComponentController.h index 886a7db..127d669 100644 --- a/src/AutoPilotPlugins/APM/APMFlightModesComponentController.h +++ b/src/AutoPilotPlugins/APM/APMFlightModesComponentController.h @@ -42,25 +42,26 @@ class APMFlightModesComponentController : public FactPanelController public: APMFlightModesComponentController(void); - Q_PROPERTY(int channelCount MEMBER _channelCount CONSTANT) - Q_PROPERTY(bool fixedWing MEMBER _fixedWing CONSTANT) - Q_PROPERTY(QString reservedChannels MEMBER _reservedChannels CONSTANT) + Q_PROPERTY(int activeFlightMode READ activeFlightMode NOTIFY activeFlightModeChanged) + Q_PROPERTY(int channelCount MEMBER _channelCount CONSTANT) + Q_PROPERTY(QVariantList channelOptionEnabled READ channelOptionEnabled NOTIFY channelOptionEnabledChanged) + Q_PROPERTY(bool fixedWing MEMBER _fixedWing CONSTANT) + + int activeFlightMode(void) { return _activeFlightMode; } + QVariantList channelOptionEnabled(void) { return _rgChannelOptionEnabled; } + +signals: + void activeFlightModeChanged(int activeFlightMode); + void channelOptionEnabledChanged(void); private slots: void _rcChannelsChanged(int channelCount, int pwmValues[Vehicle::cMaxRcChannels]); private: - void _init(void); - void _validateConfiguration(void); - - bool _fixedWing; - - int _rcValues[Vehicle::cMaxRcChannels]; - - bool _validConfiguration; - QString _configurationErrors; - int _channelCount; - QString _reservedChannels; + int _activeFlightMode; + int _channelCount; + QVariantList _rgChannelOptionEnabled; + bool _fixedWing; }; #endif From f36d8d0362a2133bcb04052512220d0507318066 Mon Sep 17 00:00:00 2001 From: Don Gagne Date: Sat, 5 Dec 2015 21:31:01 -0800 Subject: [PATCH 2/5] Clear unsent channels --- src/Vehicle/Vehicle.cc | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/Vehicle/Vehicle.cc b/src/Vehicle/Vehicle.cc index 8df158c..f9e3288 100644 --- a/src/Vehicle/Vehicle.cc +++ b/src/Vehicle/Vehicle.cc @@ -353,6 +353,10 @@ void Vehicle::_handleRCChannelsRaw(mavlink_message_t& message) int pwmValues[cMaxRcChannels]; int channelCount = 0; + for (int i=0; i Date: Sat, 5 Dec 2015 21:31:08 -0800 Subject: [PATCH 3/5] Fix live values --- src/AutoPilotPlugins/APM/APMFlightModesComponentController.cc | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/AutoPilotPlugins/APM/APMFlightModesComponentController.cc b/src/AutoPilotPlugins/APM/APMFlightModesComponentController.cc index e6a5f07..f2a273d 100644 --- a/src/AutoPilotPlugins/APM/APMFlightModesComponentController.cc +++ b/src/AutoPilotPlugins/APM/APMFlightModesComponentController.cc @@ -50,23 +50,26 @@ void APMFlightModesComponentController::_rcChannelsChanged(int channelCount, int Q_UNUSED(channelCount); _activeFlightMode = 0; - int channelValue = pwmValues[4]; if (channelValue != -1) { + bool found = false; int rgThreshold[] = { 1230, 1360, 1490, 1620, 1749 }; for (int i=0; i<5; i++) { if (channelValue <= rgThreshold[i]) { _activeFlightMode = i + 1; + found = true; break; } } - _activeFlightMode = 5; + if (!found) { + _activeFlightMode = 6; + } } emit activeFlightModeChanged(_activeFlightMode); for (int i=0; i<6; i++) { _rgChannelOptionEnabled[i] = QVariant(false); - channelValue = pwmValues[i+7]; + channelValue = pwmValues[i+6]; if (channelValue != -1 && channelValue > 1800) { _rgChannelOptionEnabled[i] = QVariant(true); } From e3134f6a1a51666464b0211a4f9aba9938d45af6 Mon Sep 17 00:00:00 2001 From: Don Gagne Date: Sat, 5 Dec 2015 23:20:06 -0800 Subject: [PATCH 4/5] Change window close sequence to prompt user from Qml side --- src/ui/MainWindow.cc | 24 ++++++++++-------------- src/ui/MainWindow.h | 5 +++++ src/ui/MainWindow.qml | 16 +++++++++++++++- 3 files changed, 30 insertions(+), 15 deletions(-) diff --git a/src/ui/MainWindow.cc b/src/ui/MainWindow.cc index 9507200..8267484 100644 --- a/src/ui/MainWindow.cc +++ b/src/ui/MainWindow.cc @@ -425,24 +425,20 @@ void MainWindow::showStatusBarCallback(bool checked) checked ? statusBar()->show() : statusBar()->hide(); } +void MainWindow::acceptWindowClose(void) +{ + qgcApp()->toolbox()->linkManager()->shutdown(); + // The above shutdown causes a flurry of activity as the vehicle components are removed. This in turn + // causes the Windows Version of Qt to crash if you allow the close event to be accepted. In order to prevent + // the crash, we ignore the close event and setup a delayed timer to close the window after things settle down. + QTimer::singleShot(1500, this, &MainWindow::_closeWindow); +} + void MainWindow::closeEvent(QCloseEvent *event) { // Disallow window close if there are active connections if (qgcApp()->toolbox()->multiVehicleManager()->vehicles()->count()) { - QGCMessageBox::StandardButton button = - QGCMessageBox::warning( - tr("QGroundControl close"), - tr("There are still active connections to vehicles. Do you want to disconnect these before closing?"), - QMessageBox::Yes | QMessageBox::Cancel, - QMessageBox::Cancel); - if (button == QMessageBox::Yes) { - qgcApp()->toolbox()->linkManager()->shutdown(); - // The above disconnect causes a flurry of activity as the vehicle components are removed. This in turn - // causes the Windows Version of Qt to crash if you allow the close event to be accepted. In order to prevent - // the crash, we ignore the close event and setup a delayed timer to close the window after things settle down. - QTimer::singleShot(1500, this, &MainWindow::_closeWindow); - } - + emit showWindowCloseMessage(); event->ignore(); return; } diff --git a/src/ui/MainWindow.h b/src/ui/MainWindow.h index f0ec66d..6f76e9c 100644 --- a/src/ui/MainWindow.h +++ b/src/ui/MainWindow.h @@ -91,6 +91,9 @@ public: /// @brief Saves the last used connection void saveLastUsedConnection(const QString connection); + // Called from MainWindow.qml when the user accepts the window close dialog + Q_INVOKABLE void acceptWindowClose(void); + public slots: /** @brief Show the application settings */ void showSettings(); @@ -132,6 +135,7 @@ protected slots: * this incoherent. */ void handleActiveViewActionState(bool triggered); + signals: // Signals the Qml to show the specified view void showFlyView(void); @@ -139,6 +143,7 @@ signals: void showSetupView(void); void showToolbarMessage(const QString& message); + void showWindowCloseMessage(void); // These are used for unit testing void showSetupFirmware(void); diff --git a/src/ui/MainWindow.qml b/src/ui/MainWindow.qml index acdc07b..23fceac 100644 --- a/src/ui/MainWindow.qml +++ b/src/ui/MainWindow.qml @@ -23,6 +23,7 @@ along with QGROUNDCONTROL. If not, see . import QtQuick 2.5 import QtQuick.Controls 1.2 +import QtQuick.Dialogs 1.2 import QtPositioning 5.2 import QGroundControl 1.0 @@ -95,6 +96,8 @@ Item { onShowToolbarMessage: toolBar.showToolbarMessage(message) + onShowWindowCloseMessage: windowCloseDialog.open() + // The following are use for unit testing only onShowSetupFirmware: setupViewLoader.item.showFirmwarePanel() @@ -173,13 +176,24 @@ Item { function showPopUp(dropItem, centerX) { if(currentPopUp) { currentPopUp.close() - } + } indicatorDropdown.centerX = centerX indicatorDropdown.sourceComponent = dropItem indicatorDropdown.visible = true currentPopUp = indicatorDropdown } + MessageDialog { + id: windowCloseDialog + title: "QGroundControl close" + text: "There are still active connections to vehicles. Do you want to disconnect these before closing?" + standardButtons: StandardButton.Yes | StandardButton.Cancel + modality: Qt.ApplicationModal + visible: false + + onYes: controller.acceptWindowClose() + } + //-- Left Settings Menu Loader { id: leftPanel From 549000eb29f7a3509d36f93935971fb8b804f521 Mon Sep 17 00:00:00 2001 From: Don Gagne Date: Sat, 5 Dec 2015 23:20:22 -0800 Subject: [PATCH 5/5] Remove QGCMessageBox usage --- src/AutoPilotPlugins/Common/RadioComponentController.cc | 2 +- src/FactSystem/ParameterLoader.cc | 13 ++----------- src/QGCApplication.cc | 11 +++-------- src/QGCQuickWidget.cc | 2 +- 4 files changed, 7 insertions(+), 21 deletions(-) diff --git a/src/AutoPilotPlugins/Common/RadioComponentController.cc b/src/AutoPilotPlugins/Common/RadioComponentController.cc index 2f88a48..b4e8cb3 100644 --- a/src/AutoPilotPlugins/Common/RadioComponentController.cc +++ b/src/AutoPilotPlugins/Common/RadioComponentController.cc @@ -26,8 +26,8 @@ /// @author Don Gagne diff --git a/src/FactSystem/ParameterLoader.cc b/src/FactSystem/ParameterLoader.cc index 0fbd59e..bbaa748 100644 --- a/src/FactSystem/ParameterLoader.cc +++ b/src/FactSystem/ParameterLoader.cc @@ -657,7 +657,6 @@ void ParameterLoader::_saveToEEPROM(void) QString ParameterLoader::readParametersFromStream(QTextStream& stream) { QString errors; - bool userWarned = false; while (!stream.atEnd()) { QString line = stream.readLine(); @@ -665,16 +664,8 @@ QString ParameterLoader::readParametersFromStream(QTextStream& stream) QStringList wpParams = line.split("\t"); int lineMavId = wpParams.at(0).toInt(); if (wpParams.size() == 5) { - if (!userWarned && (_vehicle->id() != lineMavId)) { - userWarned = true; - QString msg("The parameters in the stream have been saved from System Id %1, but the current vehicle has the System Id %2."); - QGCMessageBox::StandardButton button = QGCMessageBox::warning("Parameter Load", - msg.arg(lineMavId).arg(_vehicle->id()), - QGCMessageBox::Ok | QGCMessageBox::Cancel, - QGCMessageBox::Cancel); - if (button == QGCMessageBox::Cancel) { - return QString(); - } + if (_vehicle->id() != lineMavId) { + return QString("The parameters in the stream have been saved from System Id %1, but the current vehicle has the System Id %2.").arg(lineMavId).arg(_vehicle->id()); } int componentId = wpParams.at(1).toInt(); diff --git a/src/QGCApplication.cc b/src/QGCApplication.cc index beddbde..921a9f1 100644 --- a/src/QGCApplication.cc +++ b/src/QGCApplication.cc @@ -455,9 +455,7 @@ bool QGCApplication::_initForNormalAppBoot(void) /// settings. QString savedFilesLocation = settings.value(_savedFilesLocationKey).toString(); if (savedFilesLocation.isEmpty()) { - QGCMessageBox::warning( - tr("Bad save location"), - tr("The location to save files to is invalid, or cannot be written to. Please provide a new one.")); + showMessage("The location to save files to is invalid, or cannot be written to. Please provide a new one."); mainWindow->showSettings(); } @@ -705,10 +703,7 @@ void QGCApplication::_missingParamsDisplay(void) } _missingParams.clear(); - QGCMessageBox::critical( - "Missing Parameters", - QString("Parameters missing from firmware: %1.\n\n" - "You should quit QGroundControl immediately and update your firmware.").arg(params)); + showMessage(QString("Parameters missing from firmware: %1.\n\nYou should quit QGroundControl immediately and update your firmware.").arg(params)); } void QGCApplication::showMessage(const QString& message) @@ -717,6 +712,6 @@ void QGCApplication::showMessage(const QString& message) if (mainWindow) { mainWindow->showToolbarMessage(message); } else { - QGCMessageBox::information("", message); + qWarning() << "showMessage with no mainWindow" << message; } } diff --git a/src/QGCQuickWidget.cc b/src/QGCQuickWidget.cc index da30232..5a5b24c 100644 --- a/src/QGCQuickWidget.cc +++ b/src/QGCQuickWidget.cc @@ -60,7 +60,7 @@ bool QGCQuickWidget::setSource(const QUrl& qmlUrl) errorList += error.toString(); errorList += "\n"; } - QGCMessageBox::warning(tr("Qml Error"), tr("Source not ready: Status(%1)\nErrors:\n%2").arg(status()).arg(errorList)); + qgcApp()->showMessage(QString("Source not ready: Status(%1)\nErrors:\n%2").arg(status()).arg(errorList)); return false; }