Commit 35ec0a14 authored by Don Gagne's avatar Don Gagne

Merge pull request #1565 from DonLakeFlyer/Firmware

Firmware Upgrade usability rework
parents 5d504847 fabacf0f
......@@ -36,6 +36,7 @@
<file alias="QGroundControl/Controls/QGCView.qml">src/QmlControls/QGCView.qml</file>
<file alias="QGroundControl/Controls/QGCViewPanel.qml">src/QmlControls/QGCViewPanel.qml</file>
<file alias="QGroundControl/Controls/QGCViewDialog.qml">src/QmlControls/QGCViewDialog.qml</file>
<file alias="QGroundControl/Controls/QGCViewMessage.qml">src/QmlControls/QGCViewMessage.qml</file>
<file alias="QGroundControl/Controls/ParameterEditor.qml">src/QmlControls/ParameterEditor.qml</file>
......
......@@ -64,8 +64,12 @@ QGCView {
Component {
id: customConfigDialogComponent
QGCViewDialog {
id: customConfigDialog
QGCViewMessage {
id: customConfigDialog
message: "Your vehicle is using a custom airframe configuration. " +
"This configuration can only be modified through the Parameter Editor.\n\n" +
"If you want to Reset your airframe configuration and select a standard configuration, click 'Reset' above."
Fact { id: sys_autostart; name: "SYS_AUTOSTART" }
......@@ -73,14 +77,6 @@ QGCView {
sys_autostart.value = 0
customConfigDialog.hideDialog()
}
QGCLabel {
anchors.fill: parent
wrapMode: Text.WordWrap
text: "Your vehicle is using a custom airframe configuration. " +
"This configuration can only be modified through the Parameter Editor.\n\n" +
"If you want to Reset your airframe configuration and select a standard configuration, click 'Reset' above."
}
}
}
......
......@@ -44,11 +44,9 @@ Item {
/// to go.
signal completed
function __showDialog(component, title, charWidth, buttons) {
function __setupDialogButtons(buttons) {
__acceptButton.visible = false
__rejectButton.visible = false
__dialogCharWidth = charWidth
__dialogTitle = title
// Accept role buttons
if (buttons & StandardButton.Ok) {
......@@ -106,12 +104,31 @@ Item {
__rejectButton.text = "Abort"
__rejectButton.visible = true
}
}
function __showDialog(component, title, charWidth, buttons) {
__dialogCharWidth = charWidth
__dialogTitle = title
__setupDialogButtons(buttons)
__dialogComponent = component
__viewPanel.enabled = false
__dialogOverlay.visible = true
}
function __showMessage(title, message, buttons) {
__dialogCharWidth = 50
__dialogTitle = title
__messageDialogText = message
__setupDialogButtons(buttons)
__dialogComponent = __messageDialog
__viewPanel.enabled = false
__dialogOverlay.visible = true
}
function __hideDialog() {
__dialogComponent = null
__viewPanel.enabled = true
......@@ -130,6 +147,8 @@ Item {
/// The title for the dialog panel
property string __dialogTitle
property string __messageDialogText
property Component __dialogComponent
Component.onCompleted: completed()
......@@ -137,8 +156,9 @@ Item {
Connections {
target: __viewPanel.item
onShowDialog: __showDialog(component, title, charWidth, buttons)
onHideDialog: __hideDialog()
onShowDialog: __showDialog(component, title, charWidth, buttons)
onShowMessage: __showMessage(title, message, buttons)
onHideDialog: __hideDialog()
}
Connections {
......@@ -230,4 +250,12 @@ Item {
}
} // Rectangle - Dialog panel
} // Item - Dialog overlay
Component {
id: __messageDialog
QGCViewMessage {
message: __messageDialogText
}
}
}
\ No newline at end of file
/*=====================================================================
QGroundControl Open Source Ground Control Station
(c) 2009 - 2015 QGROUNDCONTROL PROJECT <http://www.qgroundcontrol.org>
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 <http://www.gnu.org/licenses/>.
======================================================================*/
/// @file
/// @author Don Gagne <don@thegagnes.com>
import QtQuick 2.3
import QtQuick.Controls 1.3
import QGroundControl.Controls 1.0
import QGroundControl.Palette 1.0
QGCViewDialog {
property string message
QGCLabel {
anchors.fill: parent
wrapMode: Text.WordWrap
text: message
}
}
......@@ -31,10 +31,11 @@ import QGroundControl.Palette 1.0
import QGroundControl.Controls 1.0
Rectangle {
QGCPalette { id: qgcPal; colorGroupEnabled: enabled }
property QGCPalette qgcPal: QGCPalette { colorGroupEnabled: enabled }
signal showDialog(Component component, string title, int charWidth, int buttons)
signal hideDialog
signal showMessage(string title, string message, int buttons)
color: qgcPal.window
}
......@@ -20,4 +20,5 @@ ViewWidget 1.0 ViewWidget.qml
QGCView 1.0 QGCView.qml
QGCViewPanel 1.0 QGCViewPanel.qml
QGCViewDialog 1.0 QGCViewDialog.qml
QGCViewMessage 1.0 QGCViewMessage.qml
......@@ -24,108 +24,169 @@
import QtQuick 2.3
import QtQuick.Controls 1.2
import QtQuick.Controls.Styles 1.2
import QtQuick.Dialogs 1.2
import QGroundControl.Controls 1.0
import QGroundControl.FactSystem 1.0
import QGroundControl.FactControls 1.0
import QGroundControl.Palette 1.0
import QGroundControl.Controllers 1.0
import QGroundControl.ScreenTools 1.0
Rectangle {
width: 600
height: 600
property var qgcPal: QGCPalette { colorGroupEnabled: true }
property FirmwareUpgradeController controller: FirmwareUpgradeController {
upgradeButton: upgradeButton
progressBar: progressBar
statusLog: statusTextArea
firmwareType: FirmwareUpgradeController.StableFirmware
}
color: qgcPal.window
Column {
anchors.fill:parent
QGCLabel {
text: "FIRMWARE UPDATE"
font.pointSize: ScreenTools.fontPointFactor * (20);
}
Item {
// Just used as a spacer
height: 20
width: 10
}
Row {
spacing: 10
ListModel {
id: firmwareItems
ListElement {
text: qsTr("Standard Version (stable)");
firmwareType: FirmwareUpgradeController.StableFirmware
QGCView {
viewComponent: viewPanelComponent
property string firmwareWarningMessage
Component {
id: viewPanelComponent
QGCViewPanel {
id: panel
FirmwareUpgradeController {
id: controller
upgradeButton: upgradeButton
progressBar: progressBar
statusLog: statusTextArea
firmwareType: FirmwareUpgradeController.StableFirmware
onShowMessage: {
panel.showMessage(title, message, StandardButton.Ok)
}
}
Component {
id: firmwareWarningComponent
QGCViewMessage {
message: firmwareWarningMessage
function accept() {
panel.hideDialog()
controller.doFirmwareUpgrade();
}
}
}
Column {
anchors.fill: parent
QGCLabel {
text: "FIRMWARE UPDATE"
font.pointSize: ScreenTools.fontPointFactor * (20);
}
ListElement {
text: qsTr("Beta Testing (beta)");
firmwareType: FirmwareUpgradeController.BetaFirmware
Item {
// Just used as a spacer
height: 20
width: 10
}
ListElement {
text: qsTr("Developer Build (master)");
firmwareType: FirmwareUpgradeController.DeveloperFirmware
Row {
spacing: 10
ListModel {
id: firmwareItems
ListElement {
text: qsTr("Standard Version (stable)");
firmwareType: FirmwareUpgradeController.StableFirmware
}
ListElement {
text: qsTr("Beta Testing (beta)");
firmwareType: FirmwareUpgradeController.BetaFirmware
}
ListElement {
text: qsTr("Developer Build (master)");
firmwareType: FirmwareUpgradeController.DeveloperFirmware
}
ListElement {
text: qsTr("Custom firmware file...");
firmwareType: FirmwareUpgradeController.CustomFirmware
}
}
QGCComboBox {
id: firmwareCombo
width: 200
height: upgradeButton.height
model: firmwareItems
}
QGCButton {
id: upgradeButton
text: "UPGRADE"
primary: true
onClicked: {
if (controller.activeQGCConnections()) {
panel.showMessage("Firmware Upgrade",
"There are still vehicles connected to QGroundControl. " +
"You must disconnect all vehicles from QGroundControl prior to Firmware Upgrade.",
StandardButton.Ok)
return
}
if (controller.pluggedInBoard()) {
panel.showMessage("Firmware Upgrade",
"You vehicle is currently connected via USB. " +
"You must unplug your vehicle from USB prior to Firmware Upgrade.",
StandardButton.Ok)
return
}
controller.firmwareType = firmwareItems.get(firmwareCombo.currentIndex).firmwareType
if (controller.firmwareType == 1) {
firmwareWarningMessage = "WARNING: BETA FIRMWARE\n" +
"This firmware version is ONLY intended for beta testers. " +
"Although it has received FLIGHT TESTING, it represents actively changed code. " +
"Do NOT use for normal operation.\n\n" +
"Click Cancel to abort upgrade, Click Ok to Upgrade anwyay"
panel.showDialog(firmwareWarningComponent, "Firmware Upgrade", 50, StandardButton.Cancel | StandardButton.Ok)
} else if (controller.firmwareType == 2) {
firmwareWarningMessage = "WARNING: CONTINUOUS BUILD FIRMWARE\n" +
"This firmware has NOT BEEN FLIGHT TESTED. " +
"It is only intended for DEVELOPERS. " +
"Run bench tests without props first. " +
"Do NOT fly this without addional safety precautions. " +
"Follow the mailing list actively when using it.\n\n" +
"Click Cancel to abort upgrade, Click Ok to Upgrade anwyay"
panel.showDialog(firmwareWarningComponent, "Firmware Upgrade", 50, StandardButton.Cancel | StandardButton.Ok)
} else {
controller.doFirmwareUpgrade();
}
}
}
}
ListElement {
text: qsTr("Custom firmware file...");
firmwareType: FirmwareUpgradeController.CustomFirmware
Item {
// Just used as a spacer
height: 20
width: 10
}
}
QGCComboBox {
id: firmwareCombo
width: 200
height: upgradeButton.height
model: firmwareItems
}
ProgressBar {
id: progressBar
width: parent.width
}
QGCButton {
id: upgradeButton
text: "UPGRADE"
primary: true
onClicked: {
controller.firmwareType = firmwareItems.get(firmwareCombo.currentIndex).firmwareType
controller.doFirmwareUpgrade();
TextArea {
id: statusTextArea
width: parent.width
height: 300
readOnly: true
frameVisible: false
font.pointSize: ScreenTools.defaultFontPointSize
text: qsTr("Please disconnect all vehicles from QGroundControl before selecting Upgrade.")
style: TextAreaStyle {
textColor: qgcPal.text
backgroundColor: qgcPal.windowShade
}
}
}
}
Item {
// Just used as a spacer
height: 20
width: 10
}
ProgressBar {
id: progressBar
width: parent.width
}
TextArea {
id: statusTextArea
width: parent.width
height: 300
readOnly: true
frameVisible: false
font.pointSize: ScreenTools.defaultFontPointSize
text: qsTr("Please disconnect all vehicles from QGroundControl before selecting Upgrade.")
style: TextAreaStyle {
textColor: qgcPal.text
backgroundColor: qgcPal.windowShade
}
}
}
}
} // Column
} // QGCViewPanel
} // Component - View Panel
} // QGCView
\ No newline at end of file
......@@ -74,7 +74,11 @@ void FirmwareUpgradeController::_cancel(void)
/// @brief Begins the process or searching for the board
void FirmwareUpgradeController::_findBoard(void)
{
_appendStatusLog(tr("Plug your board into USB now..."));
QString msg("Plug your board into USB now. Press Ok when board is plugged in.");
_appendStatusLog(msg);
emit showMessage("Firmware Upgrade", msg);
_searchingForBoard = true;
_threadController->findBoard(_findBoardTimeoutMsec);
}
......@@ -84,9 +88,10 @@ void FirmwareUpgradeController::_foundBoard(bool firstTry, const QString portNam
{
if (firstTry) {
// Board is still plugged
_appendStatusLog(tr("Please unplug your board before beginning the Firmware Upgrade process."));
_appendStatusLog(tr("Click Upgrade again once the board is unplugged."));
_cancel();
emit showMessage("Board plugged in",
"Please unplug your board before beginning the Firmware Upgrade process. "
"Click Upgrade again once the board is unplugged.");
} else {
_portName = portName;
_portDescription = portDescription;
......@@ -142,8 +147,8 @@ void FirmwareUpgradeController::_findTimeout(void)
} else {
msg = tr("Unable to communicate with Bootloader. If the board is currently connected via USB. Disconnect it and try Upgrade again.");
}
_appendStatusLog(msg);
_cancel();
emit showMessage("Error", msg);
}
/// @brief Prompts the user to select a firmware file if needed and moves the state machine to the next state.
......@@ -602,27 +607,6 @@ void FirmwareUpgradeController::_eraseProgressTick(void)
void FirmwareUpgradeController::doFirmwareUpgrade(void)
{
QString warningMsg;
if (_firmwareType == BetaFirmware) {
warningMsg = tr("WARNING: BETA FIRMWARE\n"
"This firmware version is ONLY intended for beta testers. "
"Although it has received FLIGHT TESTING, it represents actively changed code. Do NOT use for normal operation.\n\n"
"Are you sure you want to continue?");
} else if (_firmwareType == DeveloperFirmware) {
warningMsg = tr("WARNING: CONTINUOUS BUILD FIRMWARE\n"
"This firmware has NOT BEEN FLIGHT TESTED. "
"It is only intended for DEVELOPERS. Run bench tests without props first. "
"Do NOT fly this without addional safety precautions. Follow the mailing "
"list actively when using it.\n\n"
"Are you sure you want to continue?");
}
if (!warningMsg.isEmpty()) {
if (QGCMessageBox::warning(tr("Firmware Upgrade"), warningMsg, QGCMessageBox::Yes | QGCMessageBox::No, QGCMessageBox::No) == QGCMessageBox::No) {
return;
}
}
Q_ASSERT(_upgradeButton);
_upgradeButton->setEnabled(false);
......@@ -641,3 +625,13 @@ void FirmwareUpgradeController::_appendStatusLog(const QString& text)
Q_RETURN_ARG(QVariant, returnedValue),
Q_ARG(QVariant, varText));
}
bool FirmwareUpgradeController::activeQGCConnections(void)
{
return LinkManager::instance()->anyConnectedLinks();
}
bool FirmwareUpgradeController::pluggedInBoard(void)
{
return _threadController->pluggedInBoard();
}
\ No newline at end of file
......@@ -49,7 +49,7 @@ class FirmwareUpgradeController : public QObject
public:
FirmwareUpgradeController(void);
/// Supported firmware types
/// Supported firmware types. If you modify these you will need to update the qml file as well.
typedef enum {
StableFirmware,
BetaFirmware,
......@@ -71,6 +71,9 @@ public:
/// Progress bar for you know what
Q_PROPERTY(QQuickItem* progressBar READ progressBar WRITE setProgressBar)
Q_INVOKABLE bool activeQGCConnections(void);
Q_INVOKABLE bool pluggedInBoard(void);
/// Begins the firware upgrade process
Q_INVOKABLE void doFirmwareUpgrade(void);
......@@ -86,6 +89,9 @@ public:
QQuickItem* statusLog(void) { return _statusLog; }
void setStatusLog(QQuickItem* statusLog) { _statusLog = statusLog; }
signals:
void showMessage(const QString& title, const QString& message);
private slots:
void _downloadProgress(qint64 curr, qint64 total);
void _downloadFinished(void);
......
......@@ -118,6 +118,22 @@ void PX4FirmwareUpgradeThreadWorker::_findBoardOnce(void)
_timerRetry->start();
}
bool PX4FirmwareUpgradeThreadController::pluggedInBoard(void)
{
qDebug() << "pluggedInBoard";
QString portName;
QString portDescription;
foreach (QSerialPortInfo info, QSerialPortInfo::availablePorts()) {
if (!info.portName().isEmpty() && (info.description().contains("PX4") || info.vendorIdentifier() == 9900 /* 3DR */)) {
return true;
}
}
return false;
}
void PX4FirmwareUpgradeThreadWorker::findBootloader(const QString portName, int msecTimeout)
{
Q_UNUSED(msecTimeout);
......
......@@ -105,6 +105,9 @@ public:
PX4FirmwareUpgradeThreadController(QObject* parent = NULL);
~PX4FirmwareUpgradeThreadController(void);
/// Returns true is a board is currently connected via USB
bool pluggedInBoard(void);
/// @brief Begins the process of searching for a PX4 board connected to any serial port.
/// @param msecTimeout Numbers of msecs to continue looking for a board to become available.
void findBoard(int msecTimeout);
......
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