FirmwareUpgrade.qml 15.7 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 29

import QGroundControl.Controls 1.0
30
import QGroundControl.FactSystem 1.0
31 32
import QGroundControl.FactControls 1.0
import QGroundControl.Palette 1.0
33
import QGroundControl.Controllers 1.0
34
import QGroundControl.ScreenTools 1.0
35

36
QGCView {
37 38 39 40 41 42 43 44 45 46 47 48 49
    id:         qgcView
    viewPanel:  panel

    // User visible strings
    readonly property string title:             "FIRMWARE UPDATE"
    readonly property string highlightPrefix:   "<font color=\"yellow\">"
    readonly property string highlightSuffix:   "</font>"
    readonly property string welcomeText:       "QGroundControl can upgrade the firmware on Pixhawk devices, 3DR Radios and PX4 Flow Smart Cameras."
    readonly property string plugInText:        highlightPrefix + "Plug in your device" + highlightSuffix + " via USB to " + highlightPrefix + "start" + highlightSuffix + " firmware upgrade"
    readonly property string qgcDisconnectText: "All QGroundControl connections to vehicles must be disconnected prior to firmware upgrade. " +
                                                    "Click " + highlightPrefix + "Disconnect" + highlightSuffix + " in the toolbar above."
    property string usbUnplugText:              "Device must be disconnected from USB to start firmware upgrade. " +
                                                    highlightPrefix + "Disconnect {0}" + highlightSuffix + " from usb."
50 51

    property string firmwareWarningMessage
52 53 54 55 56 57 58 59 60 61
    property bool   controllerCompleted:      false
    property bool   initialBoardSearch:       true
    property string firmwareName

    function cancelFlash() {
        statusTextArea.append(highlightPrefix + "Upgrade cancelled" + highlightSuffix)
        statusTextArea.append("------------------------------------------")
        controller.cancel()
        flashCompleteWaitTimer.running = true
    }
62

63
    QGCPalette { id: qgcPal; colorGroupEnabled: panel.enabled }
64

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

70 71 72 73 74 75 76 77 78 79 80
        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()
            }
        }

        onNoBoardFound: {
            initialBoardSearch = false
            statusTextArea.append(plugInText)
81
        }
82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98
 
        onBoardGone: {
            initialBoardSearch = false
            statusTextArea.append(plugInText)
        }
 
        onBoardFound: {
            if (initialBoardSearch) {
                // Board was found right away, so something is already plugged in before we've started upgrade
                if (controller.qgcConnections) {
                    statusTextArea.append(qgcDisconnectText)
                } else {
                    statusTextArea.append(usbUnplugText.replace('{0}', controller.boardType))
                }
            } else {
                // We end up here when we detect a board plugged in after we've started upgrade
                statusTextArea.append(highlightPrefix + "Found device" + highlightSuffix + ": " + controller.boardType)
99
                if (controller.boardType == "Pixhawk" || controller.boardType == "AeroCore" || controller.boardType == "PX4 Flow") {
100 101 102 103 104 105 106 107 108 109 110
                    showDialog(pixhawkFirmwareSelectDialog, title, 50, StandardButton.Ok | StandardButton.Cancel)
                 }
             }
         }

        onError: {
            hideDialog()
            flashCompleteWaitTimer.running = true
        }

        onFlashComplete: flashCompleteWaitTimer.running = true
111
    }
Don Gagne's avatar
Don Gagne committed
112

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

120 121 122
    // After a flash completes we start this timer to trigger resetting the ui back to it's initial state of being ready to
    // flash another board. We do this only after the timer triggers to leave the results of the previous flash on the screen
    // for a small amount amount of time.
123

124 125 126
    Timer {
        id:         flashCompleteWaitTimer
        interval:   15000
127

128 129 130 131 132
        onTriggered: {
            initialBoardSearch = true
            progressBar.value = 0
            statusTextArea.append(welcomeText)
            controller.startBoardSearch()
133
        }
134 135 136 137
    }

    Component {
        id: pixhawkFirmwareSelectDialog
138

139
        QGCViewDialog {
140
            anchors.fill: parent
141 142
 
            property bool showVersionSelection: apmFlightStack.checked || advancedMode.checked
143
            property bool px4Flow:              controller.boardType == "PX4 Flow"
144

145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162
            function accept() {
                hideDialog()
                controller.flash(firmwareVersionCombo.model.get(firmwareVersionCombo.currentIndex).firmwareType)
            }
 
            function reject() {
                cancelFlash()
                hideDialog()
            }
 
            ExclusiveGroup {
                id: firmwareGroup
            }
 
            ListModel {
                id: px4FirmwareTypeList

                ListElement {
163 164
                    text:           "Standard Version (stable)";
                    firmwareType:   FirmwareUpgradeController.PX4StableFirmware
165 166
                }
                ListElement {
167 168
                    text:           "Beta Testing (beta)";
                    firmwareType:   FirmwareUpgradeController.PX4BetaFirmware
169 170
                }
                ListElement {
171 172
                    text:           "Developer Build (master)";
                    firmwareType:   FirmwareUpgradeController.PX4DeveloperFirmware
173 174
                }
                ListElement {
175 176
                    text:           "Custom firmware file...";
                    firmwareType:   FirmwareUpgradeController.PX4CustomFirmware
177
                 }
178
            }
179 180 181
 
            ListModel {
                id: apmFirmwareTypeList
182

183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218
                ListElement {
                    text: "ArduCopter Quad"
                    firmwareType: FirmwareUpgradeController.ApmArduCopterQuadFirmware
                }
                ListElement {
                    text: "ArduCopter X8"
                    firmwareType: FirmwareUpgradeController.ApmArduCopterX8Firmware
                }
                ListElement {
                    text: "ArduCopter Hexa"
                    firmwareType: FirmwareUpgradeController.ApmArduCopterHexaFirmware
                }
                ListElement {
                    text: "ArduCopter Octo"
                    firmwareType: FirmwareUpgradeController.ApmArduCopterOctoFirmware
                }
                ListElement {
                    text: "ArduCopter Y"
                    firmwareType: FirmwareUpgradeController.ApmArduCopterYFirmware
                }
                ListElement {
                    text: "ArduCopter Y6"
                    firmwareType: FirmwareUpgradeController.ApmArduCopterY6Firmware
                }
                ListElement {
                    text: "ArduCopter Heli"
                    firmwareType: FirmwareUpgradeController.ApmArduCopterHeliFirmware
                }
                ListElement {
                    text: "ArduPlane"
                    firmwareType: FirmwareUpgradeController.ApmArduPlaneFirmware
                }
                ListElement {
                    text: "Rover"
                    firmwareType: FirmwareUpgradeController.ApmRoverFirmware
                }
219 220
            }

221 222 223 224 225 226 227 228 229 230 231 232 233
            ListModel {
                id: px4FlowTypeList

                ListElement {
                    text:           "Standard Version (stable)";
                    firmwareType:   FirmwareUpgradeController.PX4StableFirmware
                }
                ListElement {
                    text:           "Custom firmware file...";
                    firmwareType:   FirmwareUpgradeController.PX4CustomFirmware
                 }
            }
 
234 235 236 237 238 239 240
            Column {
                anchors.fill:   parent
                spacing:        defaultTextHeight

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

244 245 246 247 248 249 250 251 252 253
                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
                }
254

255 256 257 258 259
                QGCRadioButton {
                    id:             px4FlightStack
                    checked:        true
                    exclusiveGroup: firmwareGroup
                    text:           "PX4 Flight Stack (full QGC support)"
260
                    visible:        !px4Flow
261 262 263 264 265 266 267 268

                    onClicked: parent.firmwareVersionChanged(px4FirmwareTypeList)
                }

                QGCRadioButton {
                    id:             apmFlightStack
                    exclusiveGroup: firmwareGroup
                    text:           "APM Flight Stack (partial QGC support)"
269
                    visible:        !px4Flow
270

271 272 273 274 275 276 277
                    onClicked: parent.firmwareVersionChanged(apmFirmwareTypeList)
                }
 
                QGCLabel {
                    width:      parent.width
                    wrapMode:   Text.WordWrap
                    visible:    showVersionSelection
278
                    text:       px4Flow ? "Select which version of the firmware you would like to install:" : "Select which version of the above flight stack you would like to install:"
279
                }
280

281 282 283 284
                QGCComboBox {
                    id:         firmwareVersionCombo
                    width:      200
                    visible:    showVersionSelection
285
                    model:      px4Flow ? px4FlowTypeList : px4FirmwareTypeList
286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303

                    onActivated: {
                        if (model.get(index).firmwareType == FirmwareUpgradeController.PX4BetaFirmware) {
                            firmwareVersionWarningLabel.visible = true
                            firmwareVersionWarningLabel.text = "WARNING: BETA FIRMWARE. " +
                                                                    "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."
                        } else if (model.get(index).firmwareType == FirmwareUpgradeController.PX4DeveloperFirmware) {
                            firmwareVersionWarningLabel.visible = true
                            firmwareVersionWarningLabel.text = "WARNING: CONTINUOUS BUILD FIRMWARE. " +
                                                                    "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."
                         } else {
                            firmwareVersionWarningLabel.visible = false
304
                        }
305 306 307 308 309 310 311 312 313 314 315 316 317 318 319
                     }
                 }

                QGCLabel {
                    id:         firmwareVersionWarningLabel
                    width:      parent.width
                    wrapMode:   Text.WordWrap
                    visible:    false
                }
             }
 
            QGCCheckBox {
                id:             advancedMode
                anchors.bottom: parent.bottom
                text:           "Advanced mode"
320 321
                checked:        px4Flow ? true : false
                visible:        !px4Flow
322 323 324 325

                onClicked: {
                    firmwareVersionCombo.currentIndex = 0
                    firmwareVersionWarningLabel.visible = false
326
                }
327
            }
328

329 330 331 332 333 334
            QGCButton {
                anchors.leftMargin: ScreenTools.defaultFontPixelWidth * 2
                anchors.left:       advancedMode.right
                anchors.bottom:     parent.bottom
                text:               "Help me pick a flight stack"
                onClicked:          Qt.openUrlExternally("http://pixhawk.org/choice")
335
                visible:            !px4Flow
336
            }
337 338 339 340 341 342 343 344 345
        } // QGCViewDialog
    } // Component - pixhawkFirmwareSelectDialog


    Component {
        id: firmwareWarningDialog

        QGCViewMessage {
            message: firmwareWarningMessage
346

347 348 349
            function accept() {
                hideDialog()
                controller.doFirmwareUpgrade();
350
            }
351 352 353 354 355 356
        }
    }

    QGCViewPanel {
        id:             panel
        anchors.fill:   parent
357

358 359 360 361 362
        QGCLabel {
            id:             titleLabel
            text:           title
            font.pixelSize: ScreenTools.largeFontPixelSize
        }
363

364 365 366 367 368 369
        ProgressBar {
            id:                 progressBar
            anchors.topMargin:  ScreenTools.defaultFontPixelHeight
            anchors.top:        titleLabel.bottom
            width:              parent.width
        }
370

371 372 373 374 375 376 377 378 379 380 381 382 383 384 385
        TextArea {
            id:                 statusTextArea
            anchors.topMargin:  ScreenTools.defaultFontPixelHeight
            anchors.top:        progressBar.bottom
            anchors.bottom:     parent.bottom
            width:              parent.width
            readOnly:           true
            frameVisible:       false
            font.pixelSize:     ScreenTools.defaultFontPixelSize
            textFormat:         TextEdit.RichText
            text:               welcomeText

            style: TextAreaStyle {
                textColor:          qgcPal.text
                backgroundColor:    qgcPal.windowShade
386
            }
387 388
        }
    } // QGCViewPabel
389
} // QGCView