FirmwareUpgrade.qml 15.8 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:       "QGroundControl can upgrade the firmware on Pixhawk devices, SiK Radios and PX4 Flow Smart Cameras."
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 + "."
Don Gagne's avatar
Don Gagne committed
40 41
    readonly property string qgcUnplugText1:    "All QGroundControl connections to vehicles must be " + highlightPrefix + " disconnected " + highlightSuffix + "prior to firmware upgrade."
    readonly property string qgcUnplugText2:    highlightPrefix + "<big>Please unplug your Pixhawk and/or Radio from USB.</big>" + highlightSuffix
42 43

    property string firmwareWarningMessage
44 45 46 47 48
    property bool   controllerCompleted:      false
    property bool   initialBoardSearch:       true
    property string firmwareName

    function cancelFlash() {
Tomaz Canabrava's avatar
Tomaz Canabrava committed
49
        statusTextArea.append(highlightPrefix + qsTr("Upgrade cancelled") + highlightSuffix)
50 51 52
        statusTextArea.append("------------------------------------------")
        controller.cancel()
    }
53

Don Gagne's avatar
Don Gagne committed
54
    QGCPalette { id: qgcPal; colorGroupEnabled: true }
55

56 57 58 59
    FirmwareUpgradeController {
        id:             controller
        progressBar:    progressBar
        statusLog:      statusTextArea
60

61 62
        property var activeVehicle: QGroundControl.multiVehicleManager.activeVehicle

63 64 65 66 67 68 69 70
        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()
            }
        }

71 72 73 74 75 76
        onActiveVehicleChanged: {
            if (!activeVehicle) {
                statusTextArea.append(plugInText)
            }
        }

77 78
        onNoBoardFound: {
            initialBoardSearch = false
79 80 81
            if (!QGroundControl.multiVehicleManager.activeVehicleAvailable) {
                statusTextArea.append(plugInText)
            }
82
        }
dogmaphobic's avatar
dogmaphobic committed
83

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

91 92 93
        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
94 95
                statusTextArea.append(qgcUnplugText1)
                statusTextArea.append(qgcUnplugText2)
96
                QGroundControl.multiVehicleManager.activeVehicle.autoDisconnect = true
97 98
            } else {
                // We end up here when we detect a board plugged in after we've started upgrade
Tomaz Canabrava's avatar
Tomaz Canabrava committed
99
                statusTextArea.append(highlightPrefix + qsTr("Found device") + highlightSuffix + ": " + controller.boardType)
100
                if (controller.pixhawkBoard || controller.px4FlowBoard) {
101
                    showDialog(pixhawkFirmwareSelectDialogComponent, title, qgcView.showDialogDefaultWidth, StandardButton.Ok | StandardButton.Cancel)
102 103 104
                }
            }
        }
105 106 107

        onError: {
            hideDialog()
108
            statusTextArea.append(flashFailText)
109
        }
110
    }
Don Gagne's avatar
Don Gagne committed
111

112 113 114 115 116 117
    onCompleted: {
        if (controllerCompleted) {
            // We can only start the board search when the Qml and Controller are completely done loading
            controller.startBoardSearch()
        }
    }
118

119
    Component {
120
        id: pixhawkFirmwareSelectDialogComponent
121

122
        QGCViewDialog {
123 124 125 126
            id:             pixhawkFirmwareSelectDialog
            anchors.fill:   parent

            property bool showFirmwareTypeSelection:    _advanced.checked
127
            property bool px4Flow:                      controller.px4FlowBoard
128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144

            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
145

146
            Component.onCompleted: updatePX4VersionDisplay()
147

148 149
            function accept() {
                hideDialog()
150
                var stack = apmFlightStack.checked ? FirmwareUpgradeController.AutoPilotStackAPM : FirmwareUpgradeController.AutoPilotStackPX4
151 152 153 154
                if (px4Flow) {
                    stack = FirmwareUpgradeController.PX4Flow
                }

155 156 157
                var firmwareType = firmwareVersionCombo.model.get(firmwareVersionCombo.currentIndex).firmwareType
                var vehicleType = FirmwareUpgradeController.DefaultVehicleFirmware
                if (apmFlightStack.checked) {
158
                    vehicleType = controller.vehicleTypeFromVersionIndex(vehicleTypeSelectionCombo.currentIndex)
159 160
                }
                controller.flash(stack, firmwareType, vehicleType)
161
            }
dogmaphobic's avatar
dogmaphobic committed
162

163 164
            function reject() {
                hideDialog()
165
                cancelFlash()
166
            }
dogmaphobic's avatar
dogmaphobic committed
167

168 169 170
            ExclusiveGroup {
                id: firmwareGroup
            }
dogmaphobic's avatar
dogmaphobic committed
171

172
            ListModel {
173
                id: firmwareTypeList
174 175

                ListElement {
Tomaz Canabrava's avatar
Tomaz Canabrava committed
176
                    text:           qsTr("Standard Version (stable)")
177
                    firmwareType:   FirmwareUpgradeController.StableFirmware
178 179
                }
                ListElement {
Tomaz Canabrava's avatar
Tomaz Canabrava committed
180
                    text:           qsTr("Beta Testing (beta)")
181
                    firmwareType:   FirmwareUpgradeController.BetaFirmware
182 183
                }
                ListElement {
Tomaz Canabrava's avatar
Tomaz Canabrava committed
184
                    text:           qsTr("Developer Build (master)")
185
                    firmwareType:   FirmwareUpgradeController.DeveloperFirmware
186 187
                }
                ListElement {
Tomaz Canabrava's avatar
Tomaz Canabrava committed
188
                    text:           qsTr("Custom firmware file...")
189
                    firmwareType:   FirmwareUpgradeController.CustomFirmware
190
                }
191
            }
dogmaphobic's avatar
dogmaphobic committed
192

193 194 195 196
            ListModel {
                id: px4FlowTypeList

                ListElement {
Tomaz Canabrava's avatar
Tomaz Canabrava committed
197
                    text:           qsTr("Standard Version (stable)")
198
                    firmwareType:   FirmwareUpgradeController.StableFirmware
199 200
                }
                ListElement {
Tomaz Canabrava's avatar
Tomaz Canabrava committed
201
                    text:           qsTr("Custom firmware file...")
202
                    firmwareType:   FirmwareUpgradeController.CustomFirmware
203
                }
204
            }
dogmaphobic's avatar
dogmaphobic committed
205

206 207 208 209 210 211 212
            Column {
                anchors.fill:   parent
                spacing:        defaultTextHeight

                QGCLabel {
                    width:      parent.width
                    wrapMode:   Text.WordWrap
213
                    text:       px4Flow ? "Detected PX4 Flow board. You can select from the following firmware:" : "Detected Pixhawk board. You can select from the following flight stacks:"
214
                }
215

216 217 218 219 220 221 222 223 224 225
                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
                }
226

227 228 229 230
                QGCRadioButton {
                    id:             px4FlightStack
                    checked:        true
                    exclusiveGroup: firmwareGroup
231
                    text:           qsTr("PX4 Flight Stack ")
232
                    visible:        !px4Flow
233

234
                    onClicked: parent.firmwareVersionChanged(firmwareTypeList)
235 236 237 238 239
                }

                QGCRadioButton {
                    id:             apmFlightStack
                    exclusiveGroup: firmwareGroup
Tomaz Canabrava's avatar
Tomaz Canabrava committed
240
                    text:           qsTr("ArduPilot Flight Stack")
241
                    visible:        !px4Flow
242

243
                    onClicked: parent.firmwareVersionChanged(firmwareTypeList)
244
                }
245

246
                QGCComboBox {
Don Gagne's avatar
Don Gagne committed
247 248 249 250 251
                    id:             vehicleTypeSelectionCombo
                    anchors.left:   parent.left
                    anchors.right:  parent.right
                    visible:        apmFlightStack.checked
                    model:          controller.apmAvailableVersions
252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267
                }

                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
268
                        text:       qsTr("Advanced settings")
269 270 271 272 273
                        checked:    px4Flow ? true : false

                        onClicked: {
                            firmwareVersionCombo.currentIndex = 0
                            firmwareVersionWarningLabel.visible = false
274
                            updatePX4VersionDisplay()
275 276 277 278 279 280 281 282 283 284 285
                        }
                    }

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

286 287 288
                QGCLabel {
                    width:      parent.width
                    wrapMode:   Text.WordWrap
289
                    visible:    showFirmwareTypeSelection
Tomaz Canabrava's avatar
Tomaz Canabrava committed
290
                    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:")
291
                }
292

293 294
                QGCComboBox {
                    id:             firmwareVersionCombo
Don Gagne's avatar
Don Gagne committed
295 296
                    anchors.left:   parent.left
                    anchors.right:  parent.right
297 298 299 300 301 302 303 304
                    visible:        showFirmwareTypeSelection
                    model:          px4Flow ? px4FlowTypeList : firmwareTypeList
                    currentIndex:   controller.selectedFirmwareType

                    onActivated: {
                        controller.selectedFirmwareType = index
                        if (model.get(index).firmwareType == FirmwareUpgradeController.BetaFirmware) {
                            firmwareVersionWarningLabel.visible = true
Tomaz Canabrava's avatar
Tomaz Canabrava committed
305 306 307 308
                            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.")
309 310
                        } else if (model.get(index).firmwareType == FirmwareUpgradeController.DeveloperFirmware) {
                            firmwareVersionWarningLabel.visible = true
Tomaz Canabrava's avatar
Tomaz Canabrava committed
311 312 313 314
                            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
315
                                    qsTr("Do NOT fly this without additional safety precautions. ") +
Tomaz Canabrava's avatar
Tomaz Canabrava committed
316
                                    qsTr("Follow the mailing list actively when using it.")
317 318
                        } else {
                            firmwareVersionWarningLabel.visible = false
319
                        }
320
                        updatePX4VersionDisplay()
321 322
                    }
                }
323 324 325 326 327 328 329

                QGCLabel {
                    id:         firmwareVersionWarningLabel
                    width:      parent.width
                    wrapMode:   Text.WordWrap
                    visible:    false
                }
330
            } // Column
331
        } // QGCViewDialog
332
    } // Component - pixhawkFirmwareSelectDialogComponent
333 334 335 336 337 338

    Component {
        id: firmwareWarningDialog

        QGCViewMessage {
            message: firmwareWarningMessage
339

340 341 342
            function accept() {
                hideDialog()
                controller.doFirmwareUpgrade();
343
            }
344 345 346 347 348 349
        }
    }

    QGCViewPanel {
        id:             panel
        anchors.fill:   parent
350

351 352 353
        QGCLabel {
            id:             titleLabel
            text:           title
354
            font.pointSize: ScreenTools.mediumFontPointSize
355
        }
356

357 358 359 360 361 362
        ProgressBar {
            id:                 progressBar
            anchors.topMargin:  ScreenTools.defaultFontPixelHeight
            anchors.top:        titleLabel.bottom
            width:              parent.width
        }
363

364 365 366 367 368 369 370 371
        TextArea {
            id:                 statusTextArea
            anchors.topMargin:  ScreenTools.defaultFontPixelHeight
            anchors.top:        progressBar.bottom
            anchors.bottom:     parent.bottom
            width:              parent.width
            readOnly:           true
            frameVisible:       false
372
            font.pointSize:     ScreenTools.defaultFontPointSize
373 374 375 376 377 378
            textFormat:         TextEdit.RichText
            text:               welcomeText

            style: TextAreaStyle {
                textColor:          qgcPal.text
                backgroundColor:    qgcPal.windowShade
379
            }
380 381
        }
    } // QGCViewPabel
382
} // QGCView