FirmwareUpgrade.qml 17.9 KB
Newer Older
1 2 3 4 5 6 7 8
/****************************************************************************
 *
 *   (c) 2009-2016 QGROUNDCONTROL PROJECT <http://www.qgroundcontrol.org>
 *
 * QGroundControl is licensed according to the terms in the file
 * COPYING.md in the root of the source code directory.
 *
 ****************************************************************************/
9 10


11 12
import QtQuick 2.3
import QtQuick.Controls 1.2
13
import QtQuick.Controls.Styles 1.4
14
import QtQuick.Dialogs 1.2
15

Don Gagne's avatar
Don Gagne committed
16 17 18 19 20 21 22
import QGroundControl               1.0
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
23

24
QGCView {
25 26 27
    id:         qgcView
    viewPanel:  panel

Tomaz Canabrava's avatar
Tomaz Canabrava committed
28 29 30 31
    // Those user visible strings are hard to translate because we can't send the
    // HTML strings to translation as this can create a security risk. we need to find
    // a better way to hightlight them, or use less hightlights.

32
    // User visible strings
Don Gagne's avatar
Don Gagne committed
33
    readonly property string title:             "FIRMWARE"
dogmaphobic's avatar
dogmaphobic committed
34
    readonly property string highlightPrefix:   "<font color=\"" + qgcPal.warningText + "\">"
35
    readonly property string highlightSuffix:   "</font>"
36
    readonly property string welcomeText:       qsTr("%1 can upgrade the firmware on Pixhawk devices, SiK Radios and PX4 Flow Smart Cameras.").arg(QGroundControl.appName)
37
    readonly property string plugInText:        "<big>" + highlightPrefix + "Plug in your device" + highlightSuffix + " via USB to " + highlightPrefix + "start" + highlightSuffix + " firmware upgrade.</big>"
38 39
    readonly property string flashFailText:     "If upgrade failed, make sure to connect " + highlightPrefix + "directly" + highlightSuffix + " to a powered USB port on your computer, not through a USB hub. " +
                                                "Also make sure you are only powered via USB " + highlightPrefix + "not battery" + highlightSuffix + "."
40
    readonly property string qgcUnplugText1:    qsTr("All %1 connections to vehicles must be ").arg(QGroundControl.appName) + highlightPrefix + " disconnected " + highlightSuffix + "prior to firmware upgrade."
Don Gagne's avatar
Don Gagne committed
41
    readonly property string qgcUnplugText2:    highlightPrefix + "<big>Please unplug your Pixhawk and/or Radio from USB.</big>" + highlightSuffix
42

43 44 45 46 47 48
    readonly property int _defaultFimwareTypePX4:   12
    readonly property int _defaultFimwareTypeAPM:   3

    property var    _defaultFirmwareFact:   QGroundControl.settingsManager.appSettings.defaultFirmwareType
    property bool   _defaultFirmwareIsPX4:  _defaultFirmwareFact.rawValue == _defaultFimwareTypePX4

49
    property string firmwareWarningMessage
50 51 52 53
    property bool   controllerCompleted:      false
    property bool   initialBoardSearch:       true
    property string firmwareName

54 55
    property bool _singleFirmwareMode: QGroundControl.corePlugin.options.firmwareUpgradeSingleURL.length != 0   ///< true: running in special single firmware download mode

56
    function cancelFlash() {
Tomaz Canabrava's avatar
Tomaz Canabrava committed
57
        statusTextArea.append(highlightPrefix + qsTr("Upgrade cancelled") + highlightSuffix)
58 59 60
        statusTextArea.append("------------------------------------------")
        controller.cancel()
    }
61

Don Gagne's avatar
Don Gagne committed
62
    QGCPalette { id: qgcPal; colorGroupEnabled: true }
63

64 65 66 67
    FirmwareUpgradeController {
        id:             controller
        progressBar:    progressBar
        statusLog:      statusTextArea
68

69 70
        property var activeVehicle: QGroundControl.multiVehicleManager.activeVehicle

71 72 73 74 75 76 77 78
        Component.onCompleted: {
            controllerCompleted = true
            if (qgcView.completedSignalled) {
                // We can only start the board search when the Qml and Controller are completely done loading
                controller.startBoardSearch()
            }
        }

79 80 81 82 83 84
        onActiveVehicleChanged: {
            if (!activeVehicle) {
                statusTextArea.append(plugInText)
            }
        }

85 86
        onNoBoardFound: {
            initialBoardSearch = false
87 88 89
            if (!QGroundControl.multiVehicleManager.activeVehicleAvailable) {
                statusTextArea.append(plugInText)
            }
90
        }
dogmaphobic's avatar
dogmaphobic committed
91

92 93
        onBoardGone: {
            initialBoardSearch = false
94 95 96
            if (!QGroundControl.multiVehicleManager.activeVehicleAvailable) {
                statusTextArea.append(plugInText)
            }
97
        }
dogmaphobic's avatar
dogmaphobic committed
98

99 100 101
        onBoardFound: {
            if (initialBoardSearch) {
                // Board was found right away, so something is already plugged in before we've started upgrade
Don Gagne's avatar
Don Gagne committed
102 103
                statusTextArea.append(qgcUnplugText1)
                statusTextArea.append(qgcUnplugText2)
104
                QGroundControl.multiVehicleManager.activeVehicle.autoDisconnect = true
105 106
            } else {
                // We end up here when we detect a board plugged in after we've started upgrade
Tomaz Canabrava's avatar
Tomaz Canabrava committed
107
                statusTextArea.append(highlightPrefix + qsTr("Found device") + highlightSuffix + ": " + controller.boardType)
108
                if (controller.pixhawkBoard || controller.px4FlowBoard) {
109
                    showDialog(pixhawkFirmwareSelectDialogComponent, title, qgcView.showDialogDefaultWidth, StandardButton.Ok | StandardButton.Cancel)
110 111 112
                }
            }
        }
113 114 115

        onError: {
            hideDialog()
116
            statusTextArea.append(flashFailText)
117
        }
118
    }
Don Gagne's avatar
Don Gagne committed
119

120 121 122 123 124 125
    onCompleted: {
        if (controllerCompleted) {
            // We can only start the board search when the Qml and Controller are completely done loading
            controller.startBoardSearch()
        }
    }
126

127
    Component {
128
        id: pixhawkFirmwareSelectDialogComponent
129

130
        QGCViewDialog {
131 132 133 134
            id:             pixhawkFirmwareSelectDialog
            anchors.fill:   parent

            property bool showFirmwareTypeSelection:    _advanced.checked
135
            property bool px4Flow:                      controller.px4FlowBoard
136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152

            function updatePX4VersionDisplay() {
                var versionString = ""
                if (_advanced.checked) {
                    switch (controller.selectedFirmwareType) {
                    case FirmwareUpgradeController.StableFirmware:
                        versionString = controller.px4StableVersion
                        break
                    case FirmwareUpgradeController.BetaFirmware:
                        versionString = controller.px4BetaVersion
                        break
                    }
                } else {
                    versionString = controller.px4StableVersion
                }
                px4FlightStack.text = qsTr("PX4 Flight Stack ") + versionString
            }
dogmaphobic's avatar
dogmaphobic committed
153

154
            Component.onCompleted: updatePX4VersionDisplay()
155

156 157
            function accept() {
                hideDialog()
158 159 160 161 162 163 164
                if (_singleFirmwareMode) {
                    controller.flashSingleFirmwareMode()
                } else {
                    var stack = apmFlightStack.checked ? FirmwareUpgradeController.AutoPilotStackAPM : FirmwareUpgradeController.AutoPilotStackPX4
                    if (px4Flow) {
                        stack = FirmwareUpgradeController.PX4Flow
                    }
165

166 167 168 169 170 171
                    var firmwareType = firmwareVersionCombo.model.get(firmwareVersionCombo.currentIndex).firmwareType
                    var vehicleType = FirmwareUpgradeController.DefaultVehicleFirmware
                    if (apmFlightStack.checked) {
                        vehicleType = controller.vehicleTypeFromVersionIndex(vehicleTypeSelectionCombo.currentIndex)
                    }
                    controller.flash(stack, firmwareType, vehicleType)
172
                }
173
            }
dogmaphobic's avatar
dogmaphobic committed
174

175 176
            function reject() {
                hideDialog()
177
                cancelFlash()
178
            }
dogmaphobic's avatar
dogmaphobic committed
179

180 181 182
            ExclusiveGroup {
                id: firmwareGroup
            }
dogmaphobic's avatar
dogmaphobic committed
183

184
            ListModel {
185
                id: firmwareTypeList
186 187

                ListElement {
Tomaz Canabrava's avatar
Tomaz Canabrava committed
188
                    text:           qsTr("Standard Version (stable)")
189
                    firmwareType:   FirmwareUpgradeController.StableFirmware
190 191
                }
                ListElement {
Tomaz Canabrava's avatar
Tomaz Canabrava committed
192
                    text:           qsTr("Beta Testing (beta)")
193
                    firmwareType:   FirmwareUpgradeController.BetaFirmware
194 195
                }
                ListElement {
Tomaz Canabrava's avatar
Tomaz Canabrava committed
196
                    text:           qsTr("Developer Build (master)")
197
                    firmwareType:   FirmwareUpgradeController.DeveloperFirmware
198 199
                }
                ListElement {
Tomaz Canabrava's avatar
Tomaz Canabrava committed
200
                    text:           qsTr("Custom firmware file...")
201
                    firmwareType:   FirmwareUpgradeController.CustomFirmware
202
                }
203
            }
dogmaphobic's avatar
dogmaphobic committed
204

205 206 207 208
            ListModel {
                id: px4FlowTypeList

                ListElement {
Tomaz Canabrava's avatar
Tomaz Canabrava committed
209
                    text:           qsTr("Standard Version (stable)")
210
                    firmwareType:   FirmwareUpgradeController.StableFirmware
211 212
                }
                ListElement {
Tomaz Canabrava's avatar
Tomaz Canabrava committed
213
                    text:           qsTr("Custom firmware file...")
214
                    firmwareType:   FirmwareUpgradeController.CustomFirmware
215
                }
216
            }
dogmaphobic's avatar
dogmaphobic committed
217

218 219 220 221 222 223 224 225 226 227 228 229 230
            ListModel {
                id: singleFirmwareModeTypeList

                ListElement {
                    text:           qsTr("Standard Version")
                    firmwareType:   FirmwareUpgradeController.StableFirmware
                }
                ListElement {
                    text:           qsTr("Custom firmware file...")
                    firmwareType:   FirmwareUpgradeController.CustomFirmware
                }
            }

231 232 233 234 235 236 237
            Column {
                anchors.fill:   parent
                spacing:        defaultTextHeight

                QGCLabel {
                    width:      parent.width
                    wrapMode:   Text.WordWrap
238 239 240 241 242
                    text:       _singleFirmwareMode ? _singleFirmwareLabel : (px4Flow ? _px4FlowLabel : _pixhawkLabel)

                    readonly property string _px4FlowLabel:          qsTr("Detected PX4 Flow board. You can select from the following firmware:")
                    readonly property string _pixhawkLabel:          qsTr("Detected Pixhawk board. You can select from the following flight stacks:")
                    readonly property string _singleFirmwareLabel:   qsTr("Press Ok to upgrade your vehicle.")
243
                }
244

245 246 247 248 249 250 251 252 253 254
                function firmwareVersionChanged(model) {
                    firmwareVersionWarningLabel.visible = false
                    // All of this bizarre, setting model to null and index to 1 and then to 0 is to work around
                    // strangeness in the combo box implementation. This sequence of steps correctly changes the combo model
                    // without generating any warnings and correctly updates the combo text with the new selection.
                    firmwareVersionCombo.model = null
                    firmwareVersionCombo.model = model
                    firmwareVersionCombo.currentIndex = 1
                    firmwareVersionCombo.currentIndex = 0
                }
255

256 257 258 259 260 261 262 263
                Component.onCompleted: {
                    if (_defaultFirmwareIsPX4) {
                        px4FlightStack.checked = true
                    } else {
                        apmFlightStack.checked = true
                    }
                }

264 265 266
                QGCRadioButton {
                    id:             px4FlightStack
                    exclusiveGroup: firmwareGroup
267
                    text:           qsTr("PX4 Flight Stack ")
268
                    visible:        !_singleFirmwareMode && !px4Flow
269

270 271 272 273
                    onClicked: {
                        _defaultFirmwareFact.rawValue = _defaultFimwareTypePX4
                        parent.firmwareVersionChanged(firmwareTypeList)
                    }
274 275 276 277 278
                }

                QGCRadioButton {
                    id:             apmFlightStack
                    exclusiveGroup: firmwareGroup
Tomaz Canabrava's avatar
Tomaz Canabrava committed
279
                    text:           qsTr("ArduPilot Flight Stack")
280
                    visible:        !_singleFirmwareMode && !px4Flow
281

282 283 284 285
                    onClicked: {
                        _defaultFirmwareFact.rawValue = _defaultFimwareTypeAPM
                        parent.firmwareVersionChanged(firmwareTypeList)
                    }
286
                }
287

288
                QGCComboBox {
Don Gagne's avatar
Don Gagne committed
289 290 291 292 293
                    id:             vehicleTypeSelectionCombo
                    anchors.left:   parent.left
                    anchors.right:  parent.right
                    visible:        apmFlightStack.checked
                    model:          controller.apmAvailableVersions
294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309
                }

                Row {
                    width:      parent.width
                    spacing:    ScreenTools.defaultFontPixelWidth / 2
                    visible:    !px4Flow

                    Rectangle {
                        height: 1
                        width:      ScreenTools.defaultFontPixelWidth * 5
                        color:      qgcPal.text
                        anchors.verticalCenter: _advanced.verticalCenter
                    }

                    QGCCheckBox {
                        id:         _advanced
Tomaz Canabrava's avatar
Tomaz Canabrava committed
310
                        text:       qsTr("Advanced settings")
311 312 313 314 315
                        checked:    px4Flow ? true : false

                        onClicked: {
                            firmwareVersionCombo.currentIndex = 0
                            firmwareVersionWarningLabel.visible = false
316
                            updatePX4VersionDisplay()
317 318 319 320 321 322 323 324 325 326 327
                        }
                    }

                    Rectangle {
                        height:     1
                        width:      ScreenTools.defaultFontPixelWidth * 5
                        color:      qgcPal.text
                        anchors.verticalCenter: _advanced.verticalCenter
                    }
                }

328 329 330
                QGCLabel {
                    width:      parent.width
                    wrapMode:   Text.WordWrap
331
                    visible:    showFirmwareTypeSelection
Tomaz Canabrava's avatar
Tomaz Canabrava committed
332
                    text:       px4Flow ? qsTr("Select which version of the firmware you would like to install:") : qsTr("Select which version of the above flight stack you would like to install:")
333
                }
334

335 336
                QGCComboBox {
                    id:             firmwareVersionCombo
Don Gagne's avatar
Don Gagne committed
337 338
                    anchors.left:   parent.left
                    anchors.right:  parent.right
339
                    visible:        showFirmwareTypeSelection
340
                    model:          _singleFirmwareMode ? singleFirmwareModeTypeList: (px4Flow ? px4FlowTypeList : firmwareTypeList)
341 342 343 344 345 346
                    currentIndex:   controller.selectedFirmwareType

                    onActivated: {
                        controller.selectedFirmwareType = index
                        if (model.get(index).firmwareType == FirmwareUpgradeController.BetaFirmware) {
                            firmwareVersionWarningLabel.visible = true
Tomaz Canabrava's avatar
Tomaz Canabrava committed
347 348 349 350
                            firmwareVersionWarningLabel.text = qsTr("WARNING: BETA FIRMWARE. ") +
                                    qsTr("This firmware version is ONLY intended for beta testers. ") +
                                    qsTr("Although it has received FLIGHT TESTING, it represents actively changed code. ") +
                                    qsTr("Do NOT use for normal operation.")
351 352
                        } else if (model.get(index).firmwareType == FirmwareUpgradeController.DeveloperFirmware) {
                            firmwareVersionWarningLabel.visible = true
Tomaz Canabrava's avatar
Tomaz Canabrava committed
353 354 355 356
                            firmwareVersionWarningLabel.text = qsTr("WARNING: CONTINUOUS BUILD FIRMWARE. ") +
                                    qsTr("This firmware has NOT BEEN FLIGHT TESTED. ") +
                                    qsTr("It is only intended for DEVELOPERS. ") +
                                    qsTr("Run bench tests without props first. ") +
Ricardo de Almeida Gonzaga's avatar
Ricardo de Almeida Gonzaga committed
357
                                    qsTr("Do NOT fly this without additional safety precautions. ") +
Tomaz Canabrava's avatar
Tomaz Canabrava committed
358
                                    qsTr("Follow the mailing list actively when using it.")
359 360
                        } else {
                            firmwareVersionWarningLabel.visible = false
361
                        }
362
                        updatePX4VersionDisplay()
363 364
                    }
                }
365 366 367 368 369 370 371

                QGCLabel {
                    id:         firmwareVersionWarningLabel
                    width:      parent.width
                    wrapMode:   Text.WordWrap
                    visible:    false
                }
372
            } // Column
373
        } // QGCViewDialog
374
    } // Component - pixhawkFirmwareSelectDialogComponent
375 376 377 378 379 380

    Component {
        id: firmwareWarningDialog

        QGCViewMessage {
            message: firmwareWarningMessage
381

382 383 384
            function accept() {
                hideDialog()
                controller.doFirmwareUpgrade();
385
            }
386 387 388 389 390 391
        }
    }

    QGCViewPanel {
        id:             panel
        anchors.fill:   parent
392

393 394 395
        QGCLabel {
            id:             titleLabel
            text:           title
396
            font.pointSize: ScreenTools.mediumFontPointSize
397
        }
398

399 400 401 402 403 404
        ProgressBar {
            id:                 progressBar
            anchors.topMargin:  ScreenTools.defaultFontPixelHeight
            anchors.top:        titleLabel.bottom
            width:              parent.width
        }
405

406 407 408 409 410 411 412 413
        TextArea {
            id:                 statusTextArea
            anchors.topMargin:  ScreenTools.defaultFontPixelHeight
            anchors.top:        progressBar.bottom
            anchors.bottom:     parent.bottom
            width:              parent.width
            readOnly:           true
            frameVisible:       false
414
            font.pointSize:     ScreenTools.defaultFontPointSize
415 416 417 418 419 420
            textFormat:         TextEdit.RichText
            text:               welcomeText

            style: TextAreaStyle {
                textColor:          qgcPal.text
                backgroundColor:    qgcPal.windowShade
421
            }
422 423
        }
    } // QGCViewPabel
424
} // QGCView