Commit 381acec9 authored by Don Gagne's avatar Don Gagne

Convert Firmware Upgrade to QML

- Much simpler UI
- MVC style qml programming model
parent e411b95c
......@@ -340,7 +340,6 @@ FORMS += \
src/ui/px4_configuration/QGCPX4MulticopterConfig.ui \
src/ui/px4_configuration/QGCPX4SensorCalibration.ui \
src/ui/px4_configuration/PX4RCCalibration.ui \
src/ui/px4_configuration/PX4FirmwareUpgrade.ui \
src/ui/QGCUASFileView.ui \
src/QGCQmlWidgetHolder.ui \
src/ui/QGCMapRCToParamDialog.ui \
......@@ -477,9 +476,6 @@ HEADERS += \
src/ui/px4_configuration/QGCPX4SensorCalibration.h \
src/ui/px4_configuration/PX4RCCalibration.h \
src/ui/px4_configuration/RCValueWidget.h \
src/ui/px4_configuration/PX4Bootloader.h \
src/ui/px4_configuration/PX4FirmwareUpgradeThread.h \
src/ui/px4_configuration/PX4FirmwareUpgrade.h \
src/uas/UASManagerInterface.h \
src/uas/QGCUASParamManagerInterface.h \
src/uas/QGCUASFileManager.h \
......@@ -622,9 +618,6 @@ SOURCES += \
src/ui/px4_configuration/QGCPX4SensorCalibration.cc \
src/ui/px4_configuration/PX4RCCalibration.cc \
src/ui/px4_configuration/RCValueWidget.cc \
src/ui/px4_configuration/PX4Bootloader.cc \
src/ui/px4_configuration/PX4FirmwareUpgradeThread.cc \
src/ui/px4_configuration/PX4FirmwareUpgrade.cc \
src/uas/QGCUASFileManager.cc \
src/ui/QGCUASFileView.cc \
src/CmdLineOptParser.cc \
......@@ -714,6 +707,10 @@ SOURCES += \
#
# AutoPilot Plugin Support
#
INCLUDEPATH += \
src/VehicleSetup
FORMS += \
src/VehicleSetup/ParameterEditor.ui \
src/ui/QGCPX4VehicleConfig.ui \
......@@ -724,6 +721,9 @@ HEADERS+= \
src/VehicleSetup/SetupView.h \
src/VehicleSetup/ParameterEditor.h \
src/VehicleSetup/VehicleComponent.h \
src/VehicleSetup/FirmwareUpgradeController.h \
src/VehicleSetup/PX4Bootloader.h \
src/VehicleSetup/PX4FirmwareUpgradeThread.h \
src/AutoPilotPlugins/AutoPilotPluginManager.h \
src/AutoPilotPlugins/AutoPilotPlugin.h \
src/AutoPilotPlugins/Generic/GenericAutoPilotPlugin.h \
......@@ -742,6 +742,9 @@ SOURCES += \
src/VehicleSetup/SetupView.cc \
src/VehicleSetup/ParameterEditor.cc \
src/VehicleSetup/VehicleComponent.cc \
src/VehicleSetup/FirmwareUpgradeController.cc \
src/VehicleSetup/PX4Bootloader.cc \
src/VehicleSetup/PX4FirmwareUpgradeThread.cc \
src/AutoPilotPlugins/AutoPilotPluginManager.cc \
src/AutoPilotPlugins/Generic/GenericAutoPilotPlugin.cc \
src/AutoPilotPlugins/Generic/GenericParameterFacts.cc \
......
......@@ -5,33 +5,100 @@ import QtQuick.Controls.Styles 1.2
import QGroundControl.Controls 1.0
import QGroundControl.FactControls 1.0
import QGroundControl.Palette 1.0
import QGroundControl.FirmwareUpgradeController 1.0
Rectangle {
width: 600
height: 400
height: 600
property var qgcPal: QGCPalette { colorGroup: QGCPalette.Active }
property FirmwareUpgradeController controller: FirmwareUpgradeController {
upgradeButton: upgradeButton
statusLog: statusTextArea
firmwareType: FirmwareUpgradeController.StableFirmware
}
color: qgcPal.window
Text {
text: "FIRMWARE UPDATE"
color: qgcPal.windowText
font.pointSize: 20
}
Column {
anchors.fill:parent
Text {
text: "FIRMWARE UPDATE"
color: qgcPal.windowText
font.pointSize: 20
}
Item {
// Just used as a spacer
height: 20
width: 10
}
ExclusiveGroup { id: firmwareGroup }
QGCRadioButton {
id: stableFirwareRadio
exclusiveGroup: firmwareGroup
text: qsTr("Standard Version (stable)")
checked: true
enabled: upgradeButton.enabled
onClicked: {
if (checked)
controller.firmwareType = FirmwareUpgradeController.StableFirmware
}
}
QGCRadioButton {
id: betaFirwareRadio
exclusiveGroup: firmwareGroup
text: qsTr("Beta Testing (beta)")
enabled: upgradeButton.enabled
onClicked: { if (checked) controller.firmwareType = FirmwareUpgradeController.BetaFirmware }
}
QGCRadioButton {
id: devloperFirwareRadio
exclusiveGroup: firmwareGroup
text: qsTr("Developer Build (master)")
enabled: upgradeButton.enabled
onClicked: { if (checked) controller.firmwareType = FirmwareUpgradeController.DeveloperFirmware }
}
QGCRadioButton {
id: customFirwareRadio
exclusiveGroup: firmwareGroup
text: qsTr("Custom firmware file...")
enabled: upgradeButton.enabled
onClicked: { if (checked) controller.firmwareType = FirmwareUpgradeController.CustomFirmware }
}
Item {
// Just used as a spacer
height: 20
width: 10
}
QGCButton {
id: upgradeButton
text: "UPGRADE"
onClicked: {
controller.doFirmwareUpgrade();
}
}
Item {
// Just used as a spacer
height: 20
width: 10
}
TextArea {
id: statusTextArea
width: parent.width
height: 300
readOnly: true
style: TextAreaStyle {
textColor: qgcPal.windowText
backgroundColor: qgcPal.window
}
}
}
}
......@@ -2,7 +2,7 @@
QGroundControl Open Source Ground Control Station
(c) 2009, 2014 QGROUNDCONTROL PROJECT <http://www.qgroundcontrol.org>
(c) 2009, 2015 QGROUNDCONTROL PROJECT <http://www.qgroundcontrol.org>
This file is part of the QGROUNDCONTROL project
......@@ -22,43 +22,65 @@
======================================================================*/
/// @file
/// @brief PX4 Firmware Upgrade UI
/// @author Don Gagne <don@thegagnes.com>
#ifndef PX4FirmwareUpgrade_H
#define PX4FirmwareUpgrade_H
#ifndef FirmwareUpgradeController_H
#define FirmwareUpgradeController_H
#include <QWidget>
#include "PX4FirmwareUpgradeThread.h"
#include <QObject>
#include <QUrl>
#include <QTimer>
#include <QNetworkAccessManager>
#include <QNetworkReply>
#include <QPixmap>
#include <QQuickItem>
#include "qextserialport.h"
#include <stdint.h>
#include "PX4FirmwareUpgradeThread.h"
#include "ui_PX4FirmwareUpgrade.h"
namespace Ui {
class PX4RCCalibration;
}
class PX4FirmwareUpgrade : public QWidget
// Firmware Upgrade MVC Controller for FirmwareUpgrade.qml.
class FirmwareUpgradeController : public QObject
{
Q_OBJECT
public:
explicit PX4FirmwareUpgrade(QWidget *parent = 0);
~PX4FirmwareUpgrade();
FirmwareUpgradeController(void);
/// Supported firmware types
typedef enum {
StableFirmware,
BetaFirmware,
DeveloperFirmware,
CustomFirmware
} FirmwareType_t;
Q_ENUMS(FirmwareType_t)
/// Firmare type to load
Q_PROPERTY(FirmwareType_t firmwareType READ firmwareType WRITE setFirmwareType)
/// Upgrade push button in UI
Q_PROPERTY(QQuickItem* upgradeButton READ upgradeButton WRITE setUpgradeButton)
/// TextArea for log output
Q_PROPERTY(QQuickItem* statusLog READ statusLog WRITE setStatusLog)
/// Begins the firware upgrade process
Q_INVOKABLE void doFirmwareUpgrade(void);
FirmwareType_t firmwareType(void) { return _firmwareType; }
void setFirmwareType(FirmwareType_t firmwareType) { _firmwareType = firmwareType; }
QQuickItem* upgradeButton(void) { return _upgradeButton; }
void setUpgradeButton(QQuickItem* upgradeButton) { _upgradeButton = upgradeButton; }
QQuickItem* statusLog(void) { return _statusLog; }
void setStatusLog(QQuickItem* statusLog) { _statusLog = statusLog; }
private slots:
void _tryAgainButton(void);
void _cancelButton(void);
void _nextButton(void);
void _firmwareSelected(int index);
void _downloadProgress(qint64 curr, qint64 total);
void _downloadFinished(void);
void _downloadError(QNetworkReply::NetworkError code);
......@@ -73,56 +95,18 @@ private slots:
void _eraseProgressTick(void);
private:
/// @brief The various states that the upgrade process progresses through.
enum upgradeStates {
upgradeStateBegin,
upgradeStateBoardSearch,
upgradeStateBoardNotFound,
upgradeStateBootloaderSearch,
upgradeStateBootloaderNotFound,
upgradeStateBootloaderError,
upgradeStateFirmwareSelect,
upgradeStateFirmwareDownloading,
upgradeStateDownloadFailed,
upgradeStateErasing,
upgradeStateEraseError,
upgradeStateFlashing,
upgradeStateFlashError,
upgradeStateVerifying,
upgradeStateVerifyError,
upgradeStateBoardUpgraded,
upgradeStateMax
};
void _setupState(enum upgradeStates state);
void _updateIndicatorUI(void);
void _findBoard(void);
void _findBootloader(void);
void _cancel(void);
void _cancelFind(void);
void _getFirmwareFile(void);
void _setBoardIcon(int boardID);
void _setFirmwareCombo(int boardID);
void _downloadFirmware(void);
void _cancelDownload(void);
void _erase(void);
typedef void (PX4FirmwareUpgrade::*stateFunc)(void);
struct stateMachineEntry {
enum upgradeStates state; ///< State machine state, used to verify correctness of entry
stateFunc next; ///< Method to call when Next is clicked, NULL for Next not available
stateFunc cancel; ///< Method to call when Cancel is clicked, NULL for Cancel not available
stateFunc tryAgain; ///< Method to call when Try Again is clicked, NULL for Try Again not available
const char* msg; ///< Text message to display to user for this state
};
const struct stateMachineEntry* _getStateMachineEntry(enum upgradeStates state);
enum upgradeStates _upgradeState; ///< Current state of the upgrade state machines
void _appendStatusLog(const QString& text);
QString _portName;
QString _portDescription;
......@@ -154,7 +138,11 @@ private:
static const int _findBoardTimeoutMsec = 30000; ///< Amount of time for user to plug in USB
static const int _findBootloaderTimeoutMsec = 5000; ///< Amount time to look for bootloader
Ui::PX4FirmwareUpgrade* _ui;
FirmwareType_t _firmwareType; ///< Firmware type to load
QQuickItem* _upgradeButton; ///< Upgrade button in ui
QQuickItem* _statusLog; ///< Status log TextArea Qml control
bool _searchingForBoard; ///< true: searching for board, false: search for bootloader
};
#endif // PX4FirmwareUpgrade_H
#endif
......@@ -174,9 +174,13 @@ void PX4FirmwareUpgradeThreadWorker::timeout(void)
void PX4FirmwareUpgradeThreadWorker::sendBootloaderReboot(void)
{
_bootloader->sendBootloaderReboot(_bootloaderPort);
_bootloaderPort->deleteLater();
_bootloaderPort = NULL;
if (_bootloaderPort) {
if (_bootloaderPort->isOpen()) {
_bootloader->sendBootloaderReboot(_bootloaderPort);
}
_bootloaderPort->deleteLater();
_bootloaderPort = NULL;
}
}
void PX4FirmwareUpgradeThreadWorker::program(const QString firmwareFilename)
......
......@@ -30,11 +30,11 @@
#include "UASManager.h"
#include "AutoPilotPluginManager.h"
#include "VehicleComponent.h"
#include "PX4FirmwareUpgrade.h"
#include "ParameterEditor.h"
#include "QGCQmlWidgetHolder.h"
#include "MainWindow.h"
#include "QGCMessageBox.h"
#include "FirmwareUpgradeController.h"
#include <QQmlError>
#include <QQmlContext>
......@@ -54,13 +54,13 @@ SetupView::SetupView(QWidget* parent) :
Q_UNUSED(fSucceeded);
Q_ASSERT(fSucceeded);
//setResizeMode(SizeRootObjectToView);
_ui->buttonHolder->setAutoPilot(NULL);
_ui->buttonHolder->setSource(QUrl::fromUserInput("qrc:/qml/SetupViewButtons.qml"));
_ui->buttonHolder->rootContext()->setContextProperty("controller", this);
qmlRegisterType<FirmwareUpgradeController>("QGroundControl.FirmwareUpgradeController", 1, 0, "FirmwareUpgradeController");
_setActiveUAS(UASManager::instance()->getActiveUAS());
}
......@@ -120,16 +120,11 @@ void SetupView::firmwareButtonClicked(void)
return;
}
#if 1
PX4FirmwareUpgrade* setup = new PX4FirmwareUpgrade(this);
#else
// NYI
QGCQmlWidgetHolder* setup = new QGCQmlWidgetHolder;
Q_CHECK_PTR(setup);
//setup->setAutoPilot(_autoPilotPlugin);
setup->setSource(QUrl::fromUserInput("qrc:/qml/FirmwareUpgrade.qml"));
#endif
_changeSetupWidget(setup);
}
......
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>PX4FirmwareUpgrade</class>
<widget class="QWidget" name="PX4FirmwareUpgrade">
<property name="windowModality">
<enum>Qt::ApplicationModal</enum>
</property>
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>727</width>
<height>527</height>
</rect>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="MinimumExpanding" vsizetype="MinimumExpanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>727</width>
<height>527</height>
</size>
</property>
<property name="windowTitle">
<string>Form</string>
</property>
<property name="windowOpacity">
<double>1.000000000000000</double>
</property>
<widget class="QWidget" name="layoutWidget">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>726</width>
<height>525</height>
</rect>
</property>
<layout class="QGridLayout" name="gridLayout" rowstretch="0" columnstretch="0,0">
<item row="0" column="1">
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QCheckBox" name="boardFoundCheck">
<property name="text">
<string>Board found</string>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="port">
<property name="text">
<string>Port</string>
</property>
<property name="alignment">
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="description">
<property name="text">
<string>Description</string>
</property>
<property name="alignment">
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item>
<widget class="QCheckBox" name="bootloaderFoundCheck">
<property name="text">
<string>Bootloader found</string>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="bootloaderVersion">
<property name="text">
<string>Bootloader Version</string>
</property>
<property name="alignment">
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="boardID">
<property name="text">
<string>Board ID</string>
</property>
<property name="alignment">
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="icon">
<property name="minimumSize">
<size>
<width>200</width>
<height>100</height>
</size>
</property>
<property name="text">
<string>Icon</string>
</property>
</widget>
</item>
<item>
<widget class="QCheckBox" name="selectFirmwareCheck">
<property name="text">
<string>Select Firmware</string>
</property>
</widget>
</item>
<item>
<widget class="QComboBox" name="firmwareCombo"/>
</item>
<item>
<widget class="QCheckBox" name="firmwareDownloadedCheck">
<property name="text">
<string>Firmware downloaded</string>
</property>
</widget>
</item>
<item>
<widget class="QCheckBox" name="boardUpgradedCheck">
<property name="text">
<string>Board upgraded</string>
</property>
</widget>
</item>
<item>
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
</layout>
</item>
<item row="0" column="0">
<layout class="QVBoxLayout" name="verticalLayout_9">
<item>
<widget class="QLabel" name="statusLog">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>400</width>
<height>180</height>
</size>
</property>
<property name="text">
<string>Status log</string>
</property>
<property name="alignment">
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="statusLabel">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>400</width>
<height>16</height>
</size>
</property>
<property name="text">
<string>TextLabel</string>
</property>
<property name="alignment">
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="QPushButton" name="tryAgain">
<property name="text">
<string>Try Again</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="skip">
<property name="text">
<string>Skip</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="cancel">
<property name="text">
<string>Cancel</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="next">
<property name="text">
<string>Next</string>
</property>
</widget>
</item>
</layout>
</item>
<item>
<widget class="QProgressBar" name="progressBar">
<property name="value">
<number>24</number>
</property>
</widget>
</item>
<item>
<spacer name="verticalSpacer_3">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>60</height>
</size>
</property>
</spacer>
</item>
</layout>
</item>
</layout>
</widget>
</widget>
<resources/>
<connections/>
</ui>
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