FirmwareUpgrade.qml 16.4 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
/*=====================================================================

 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/>.

 ======================================================================*/

Don Gagne's avatar
Don Gagne committed
24
import QtQuick 2.3
25 26
import QtQuick.Controls 1.2
import QtQuick.Controls.Styles 1.2
27
import QtQuick.Dialogs 1.2
28

Don Gagne's avatar
Don Gagne committed
29 30 31 32 33 34 35
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
36

37
QGCView {
38 39 40
    id:         qgcView
    viewPanel:  panel

Tomaz Canabrava's avatar
Tomaz Canabrava committed
41 42 43 44
    // 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.

45
    // User visible strings
Don Gagne's avatar
Don Gagne committed
46
    readonly property string title:             "FIRMWARE"
dogmaphobic's avatar
dogmaphobic committed
47
    readonly property string highlightPrefix:   "<font color=\"" + qgcPal.warningText + "\">"
48
    readonly property string highlightSuffix:   "</font>"
49
    readonly property string welcomeText:       "QGroundControl can upgrade the firmware on Pixhawk devices, SiK Radios and PX4 Flow Smart Cameras."
50
    readonly property string plugInText:        "<big>" + highlightPrefix + "Plug in your device" + highlightSuffix + " via USB to " + highlightPrefix + "start" + highlightSuffix + " firmware upgrade.</big>"
51 52
    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
53 54
    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
55 56

    property string firmwareWarningMessage
57 58 59 60 61
    property bool   controllerCompleted:      false
    property bool   initialBoardSearch:       true
    property string firmwareName

    function cancelFlash() {
Tomaz Canabrava's avatar
Tomaz Canabrava committed
62
        statusTextArea.append(highlightPrefix + qsTr("Upgrade cancelled") + highlightSuffix)
63 64 65
        statusTextArea.append("------------------------------------------")
        controller.cancel()
    }
66

Don Gagne's avatar
Don Gagne committed
67
    QGCPalette { id: qgcPal; colorGroupEnabled: true }
68

69 70 71 72
    FirmwareUpgradeController {
        id:             controller
        progressBar:    progressBar
        statusLog:      statusTextArea
73

74 75
        property var activeVehicle: QGroundControl.multiVehicleManager.activeVehicle

76 77 78 79 80 81 82 83
        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()
            }
        }

84 85 86 87 88 89
        onActiveVehicleChanged: {
            if (!activeVehicle) {
                statusTextArea.append(plugInText)
            }
        }

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

97 98
        onBoardGone: {
            initialBoardSearch = false
99 100 101
            if (!QGroundControl.multiVehicleManager.activeVehicleAvailable) {
                statusTextArea.append(plugInText)
            }
102
        }
dogmaphobic's avatar
dogmaphobic committed
103

104 105 106
        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
107 108
                statusTextArea.append(qgcUnplugText1)
                statusTextArea.append(qgcUnplugText2)
109
                QGroundControl.multiVehicleManager.activeVehicle.autoDisconnect = true
110 111
            } else {
                // We end up here when we detect a board plugged in after we've started upgrade
Tomaz Canabrava's avatar
Tomaz Canabrava committed
112
                statusTextArea.append(highlightPrefix + qsTr("Found device") + highlightSuffix + ": " + controller.boardType)
Henry Zhang's avatar
Henry Zhang committed
113
                if (controller.boardType == "Pixhawk" || controller.boardType == "AeroCore" || controller.boardType == "PX4 Flow" || controller.boardType == "PX4 FMU V1" || controller.boardType == "MindPX") {
114
                    showDialog(pixhawkFirmwareSelectDialogComponent, title, qgcView.showDialogDefaultWidth, StandardButton.Ok | StandardButton.Cancel)
115 116 117
                }
            }
        }
118 119 120

        onError: {
            hideDialog()
121
            statusTextArea.append(flashFailText)
122
        }
123
    }
Don Gagne's avatar
Don Gagne committed
124

125 126 127 128 129 130
    onCompleted: {
        if (controllerCompleted) {
            // We can only start the board search when the Qml and Controller are completely done loading
            controller.startBoardSearch()
        }
    }
131

132
    Component {
133
        id: pixhawkFirmwareSelectDialogComponent
134

135
        QGCViewDialog {
136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157
            id:             pixhawkFirmwareSelectDialog
            anchors.fill:   parent

            property bool showFirmwareTypeSelection:    _advanced.checked
            property bool px4Flow:                      controller.boardType == "PX4 Flow"

            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
158

159
            Component.onCompleted: updatePX4VersionDisplay()
160

161 162
            function accept() {
                hideDialog()
163
                var stack = apmFlightStack.checked ? FirmwareUpgradeController.AutoPilotStackAPM : FirmwareUpgradeController.AutoPilotStackPX4
164 165 166 167
                if (px4Flow) {
                    stack = FirmwareUpgradeController.PX4Flow
                }

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

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

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

185
            ListModel {
186
                id: firmwareTypeList
187 188

                ListElement {
Tomaz Canabrava's avatar
Tomaz Canabrava committed
189
                    text:           qsTr("Standard Version (stable)")
190
                    firmwareType:   FirmwareUpgradeController.StableFirmware
191 192
                }
                ListElement {
Tomaz Canabrava's avatar
Tomaz Canabrava committed
193
                    text:           qsTr("Beta Testing (beta)")
194
                    firmwareType:   FirmwareUpgradeController.BetaFirmware
195 196
                }
                ListElement {
Tomaz Canabrava's avatar
Tomaz Canabrava committed
197
                    text:           qsTr("Developer Build (master)")
198
                    firmwareType:   FirmwareUpgradeController.DeveloperFirmware
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
            ListModel {
                id: px4FlowTypeList

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

219 220 221 222 223 224 225
            Column {
                anchors.fill:   parent
                spacing:        defaultTextHeight

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

229 230 231 232 233 234 235 236 237 238
                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
                }
239

240 241 242 243
                QGCRadioButton {
                    id:             px4FlightStack
                    checked:        true
                    exclusiveGroup: firmwareGroup
244
                    text:           qsTr("PX4 Flight Stack ")
245
                    visible:        !px4Flow
246

247
                    onClicked: parent.firmwareVersionChanged(firmwareTypeList)
248 249 250 251 252
                }

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

256
                    onClicked: parent.firmwareVersionChanged(firmwareTypeList)
257
                }
258

259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279
                QGCComboBox {
                    id:         vehicleTypeSelectionCombo
                    width:      200
                    visible:    apmFlightStack.checked
                    model:      controller.apmAvailableVersions
                }

                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
280
                        text:       qsTr("Advanced settings")
281 282 283 284 285
                        checked:    px4Flow ? true : false

                        onClicked: {
                            firmwareVersionCombo.currentIndex = 0
                            firmwareVersionWarningLabel.visible = false
286
                            updatePX4VersionDisplay()
287 288 289 290 291 292 293 294 295 296 297
                        }
                    }

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

298 299 300
                QGCLabel {
                    width:      parent.width
                    wrapMode:   Text.WordWrap
301
                    visible:    showFirmwareTypeSelection
Tomaz Canabrava's avatar
Tomaz Canabrava committed
302
                    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:")
303
                }
304

305 306 307 308 309 310 311 312 313 314 315
                QGCComboBox {
                    id:             firmwareVersionCombo
                    width:          200
                    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
316 317 318 319
                            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.")
320 321
                        } else if (model.get(index).firmwareType == FirmwareUpgradeController.DeveloperFirmware) {
                            firmwareVersionWarningLabel.visible = true
Tomaz Canabrava's avatar
Tomaz Canabrava committed
322 323 324 325 326 327
                            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. ") +
                                    qsTr("Do NOT fly this without additonal safety precautions. ") +
                                    qsTr("Follow the mailing list actively when using it.")
328 329
                        } else {
                            firmwareVersionWarningLabel.visible = false
330
                        }
331
                        updatePX4VersionDisplay()
332 333
                    }
                }
334 335 336 337 338 339 340

                QGCLabel {
                    id:         firmwareVersionWarningLabel
                    width:      parent.width
                    wrapMode:   Text.WordWrap
                    visible:    false
                }
341
            } // Column
342
        } // QGCViewDialog
343
    } // Component - pixhawkFirmwareSelectDialogComponent
344 345 346 347 348 349

    Component {
        id: firmwareWarningDialog

        QGCViewMessage {
            message: firmwareWarningMessage
350

351 352 353
            function accept() {
                hideDialog()
                controller.doFirmwareUpgrade();
354
            }
355 356 357 358 359 360
        }
    }

    QGCViewPanel {
        id:             panel
        anchors.fill:   parent
361

362 363 364
        QGCLabel {
            id:             titleLabel
            text:           title
365
            font.pointSize: ScreenTools.mediumFontPointSize
366
        }
367

368 369 370 371 372 373
        ProgressBar {
            id:                 progressBar
            anchors.topMargin:  ScreenTools.defaultFontPixelHeight
            anchors.top:        titleLabel.bottom
            width:              parent.width
        }
374

375 376 377 378 379 380 381 382
        TextArea {
            id:                 statusTextArea
            anchors.topMargin:  ScreenTools.defaultFontPixelHeight
            anchors.top:        progressBar.bottom
            anchors.bottom:     parent.bottom
            width:              parent.width
            readOnly:           true
            frameVisible:       false
383
            font.pointSize:     ScreenTools.defaultFontPointSize
384 385 386 387 388 389
            textFormat:         TextEdit.RichText
            text:               welcomeText

            style: TextAreaStyle {
                textColor:          qgcPal.text
                backgroundColor:    qgcPal.windowShade
390
            }
391 392
        }
    } // QGCViewPabel
393
} // QGCView