ParameterEditor.qml 15.5 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.
 *
 ****************************************************************************/
Don Gagne's avatar
Don Gagne committed
9 10


11 12 13
/// @file
///     @author Don Gagne <don@thegagnes.com>

Don Gagne's avatar
Don Gagne committed
14 15 16
import QtQuick                  2.5
import QtQuick.Controls         1.3
import QtQuick.Dialogs          1.2
Don Gagne's avatar
Don Gagne committed
17

Don Gagne's avatar
Don Gagne committed
18 19 20 21 22 23 24
import QGroundControl               1.0
import QGroundControl.Controls      1.0
import QGroundControl.Palette       1.0
import QGroundControl.ScreenTools   1.0
import QGroundControl.Controllers   1.0
import QGroundControl.FactSystem    1.0
import QGroundControl.FactControls  1.0
Don Gagne's avatar
Don Gagne committed
25

Don Gagne's avatar
Don Gagne committed
26
QGCView {
27 28
    id:         qgcView
    viewPanel:  panel
Don Gagne's avatar
Don Gagne committed
29

Don Gagne's avatar
Don Gagne committed
30
    QGCPalette { id: __qgcPal; colorGroupEnabled: true }
Don Gagne's avatar
Don Gagne committed
31

32
    property Fact   _editorDialogFact: Fact { }
33
    property int    _rowHeight:         ScreenTools.defaultFontPixelHeight * 2
dogmaphobic's avatar
dogmaphobic committed
34 35 36 37
    property int    _rowWidth:          10      // Dynamic adjusted at runtime
    property bool   _searchFilter:      false   ///< true: showing results of search
    property var    _searchResults              ///< List of parameter names from search results
    property string _currentGroup:      ""
38
    property bool   _showRCToParam:     !ScreenTools.isMobile && QGroundControl.multiVehicleManager.activeVehicle.px4Firmware
Don Gagne's avatar
Don Gagne committed
39

40
    ParameterEditorController {
Don Gagne's avatar
Don Gagne committed
41 42
        id:         controller;
        factPanel:  panel
43
        onShowErrorMessage: {
44
            showMessage(qsTr("Parameter Load Errors"), errorMsg, StandardButton.Ok)
45 46
        }
    }
Don Gagne's avatar
Don Gagne committed
47

dogmaphobic's avatar
dogmaphobic committed
48 49 50
    QGCViewPanel {
        id:             panel
        anchors.fill:   parent
Don Gagne's avatar
Don Gagne committed
51 52 53 54 55 56 57 58 59 60

        //---------------------------------------------
        //-- Header
        Row {
            id:             header
            anchors.left:   parent.left
            anchors.right:  parent.right
            height:         searchText.height + ScreenTools.defaultFontPixelHeight / 3
            spacing:        ScreenTools.defaultFontPixelWidth

61 62 63 64
            QGCTextField {
                id: searchText
            }

Don Gagne's avatar
Don Gagne committed
65 66 67
            QGCButton {
                anchors.top:    searchText.top
                anchors.bottom: searchText.bottom
68
                text:           qsTr("Search")
Don Gagne's avatar
Don Gagne committed
69 70 71
                onClicked: {
                    _searchResults = controller.searchParametersForComponent(-1, searchText.text)
                    _searchFilter = true
dogmaphobic's avatar
dogmaphobic committed
72
                }
Don Gagne's avatar
Don Gagne committed
73 74 75 76 77 78 79 80 81 82 83 84
            }

            QGCButton {
                anchors.top:    searchText.top
                anchors.bottom: searchText.bottom
                text:           qsTr("Clear")
                visible:        _searchFilter

                onClicked: {
                    searchText.text = ""
                    _searchFilter = false
                    hideDialog()
dogmaphobic's avatar
dogmaphobic committed
85
                }
Don Gagne's avatar
Don Gagne committed
86 87 88 89 90 91 92 93 94 95 96 97 98 99
            }
        } // Row - Header

        QGCButton {
            anchors.top:    header.top
            anchors.bottom: header.bottom
            anchors.right:  parent.right
            text:           qsTr("Tools")
            visible:        !_searchFilter

            menu: Menu {
                MenuItem {
                    text:           qsTr("Refresh")
                    onTriggered:	controller.refresh()
dogmaphobic's avatar
dogmaphobic committed
100
                }
Don Gagne's avatar
Don Gagne committed
101 102 103
                MenuItem {
                    text:           qsTr("Reset all to defaults")
                    onTriggered:    showDialog(resetToDefaultConfirmComponent, qsTr("Reset All"), qgcView.showDialogDefaultWidth, StandardButton.Cancel | StandardButton.Reset)
dogmaphobic's avatar
dogmaphobic committed
104
                }
Don Gagne's avatar
Don Gagne committed
105 106 107 108 109 110 111 112
                MenuSeparator { }
                MenuItem {
                    text:           qsTr("Load from file...")
                    onTriggered: {
                        if (ScreenTools.isMobile) {
                            qgcView.showDialog(mobileFilePicker, qsTr("Select Parameter File"), qgcView.showDialogDefaultWidth, StandardButton.Yes | StandardButton.Cancel)
                        } else {
                            controller.loadFromFilePicker()
dogmaphobic's avatar
dogmaphobic committed
113
                        }
Don Gagne's avatar
Don Gagne committed
114 115 116 117 118 119 120 121 122
                    }
                }
                MenuItem {
                    text:           qsTr("Save to file...")
                    onTriggered: {
                        if (ScreenTools.isMobile) {
                            qgcView.showDialog(mobileFileSaver, qsTr("Save Parameter File"), qgcView.showDialogDefaultWidth, StandardButton.Save | StandardButton.Cancel)
                        } else {
                            controller.saveToFilePicker()
dogmaphobic's avatar
dogmaphobic committed
123 124 125
                        }
                    }
                }
Don Gagne's avatar
Don Gagne committed
126 127 128 129 130 131
                MenuSeparator { visible: _showRCToParam }
                MenuItem {
                    text:           qsTr("Clear RC to Param")
                    onTriggered:	controller.clearRCToParam()
                    visible:        _showRCToParam
                }
dogmaphobic's avatar
dogmaphobic committed
132
            }
Don Gagne's avatar
Don Gagne committed
133 134 135 136 137 138 139 140 141 142
        }

        //---------------------------------------------
        //-- Contents
        Loader {
            anchors.left:       parent.left
            anchors.right:      parent.right
            anchors.top:        header.bottom
            anchors.bottom:     parent.bottom
            sourceComponent:    _searchFilter ? searchResultsViewComponent: groupedViewComponent
dogmaphobic's avatar
dogmaphobic committed
143 144 145 146
        }
    }

    //-- Parameter Groups
Don Gagne's avatar
Don Gagne committed
147
    Component {
dogmaphobic's avatar
dogmaphobic committed
148 149 150 151
        id: groupedViewComponent
        Row {
            spacing: ScreenTools.defaultFontPixelWidth * 0.5
            //-- Parameter Groups
Don Gagne's avatar
Don Gagne committed
152
            QGCFlickable {
dogmaphobic's avatar
dogmaphobic committed
153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170
                id :                groupScroll
                width:              ScreenTools.defaultFontPixelWidth * 25
                height:             parent.height
                clip:               true
                pixelAligned:       true
                contentHeight:      groupedViewComponentColumn.height
                contentWidth:       groupedViewComponentColumn.width
                flickableDirection: Flickable.VerticalFlick
                Column {
                    id: groupedViewComponentColumn
                    spacing: Math.ceil(ScreenTools.defaultFontPixelHeight * 0.25)
                    Repeater {
                        model: controller.componentIds
                        Column {
                            id: componentColumn
                            readonly property int componentId: parseInt(modelData)
                            spacing: Math.ceil(ScreenTools.defaultFontPixelHeight * 0.25)
                            QGCLabel {
171
                                text: qsTr("Component #: %1").arg(componentId.toString())
172
                                font.family: ScreenTools.demiboldFontFamily
dogmaphobic's avatar
dogmaphobic committed
173 174 175 176 177 178 179 180 181 182 183 184
                                anchors.horizontalCenter: parent.horizontalCenter
                            }
                            ExclusiveGroup { id: groupGroup }
                            Repeater {
                                model: controller.getGroupsForComponent(componentId)
                                QGCButton {
                                    width:  ScreenTools.defaultFontPixelWidth * 25
                                    text:	modelData
                                    height: _rowHeight
                                    exclusiveGroup: setupButtonGroup
                                    onClicked: {
                                        checked = true
185 186 187
                                        // Clear the rows from the component first. This allows us to change the componentId without
                                        // breaking any bindings.
                                        factRowsLoader.parameterNames   = [ ]
dogmaphobic's avatar
dogmaphobic committed
188 189 190 191
                                        _rowWidth                       = 10
                                        factRowsLoader.componentId      = componentId
                                        factRowsLoader.parameterNames   = controller.getParametersForGroup(componentId, modelData)
                                        _currentGroup                   = modelData
192 193
                                        factScrollView.contentX         = 0
                                        factScrollView.contentY         = 0
dogmaphobic's avatar
dogmaphobic committed
194 195 196 197 198 199 200 201 202 203 204 205 206 207
                                    }
                                }
                            }
                        }
                    }
                }
            }
            Rectangle {
                color:      __qgcPal.text
                width:      1
                height:     parent.height
                opacity:    0.1
            }
            //-- Parameters
Don Gagne's avatar
Don Gagne committed
208
            QGCFlickable {
dogmaphobic's avatar
dogmaphobic committed
209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228
                id:             factScrollView
                width:          parent.width - groupScroll.width
                height:         parent.height
                contentHeight:  factRowsLoader.height
                contentWidth:   _rowWidth
                boundsBehavior: Flickable.OvershootBounds
                pixelAligned:   true
                clip:           true
                Loader {
                    id:                 factRowsLoader
                    sourceComponent:    factRowsComponent
                    property int    componentId:    controller.componentIds[0]
                    property var    parameterNames: controller.getParametersForGroup(componentId, controller.getGroupsForComponent(componentId)[0])
                    onLoaded: {
                        _currentGroup = controller.getGroupsForComponent(controller.componentIds[0])[0]
                    }
                }
            }
        }
    }
Don Gagne's avatar
Don Gagne committed
229

dogmaphobic's avatar
dogmaphobic committed
230 231 232 233 234
    //---------------------------------------------
    // Search result view
    Component {
        id: searchResultsViewComponent
        Item {
Don Gagne's avatar
Don Gagne committed
235
            QGCFlickable {
dogmaphobic's avatar
dogmaphobic committed
236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274
                id:             factScrollView
                width:          parent.width
                height:         parent.height
                contentHeight:  factRowsLoader.height
                contentWidth:   _rowWidth
                boundsBehavior: Flickable.OvershootBounds
                pixelAligned:   true
                clip:           true
                Loader {
                    id:                 factRowsLoader
                    sourceComponent:    factRowsComponent
                    property int    componentId:       -1
                    property var    parameterNames:    _searchResults
                }
            }
        }
    }

    //---------------------------------------------
    // Paremeters view
    Component {
        id: factRowsComponent
        Column {
            spacing: Math.ceil(ScreenTools.defaultFontPixelHeight * 0.25)
            Repeater {
                model: parameterNames
                Rectangle {
                    height: _rowHeight
                    width:  _rowWidth
                    color:  Qt.rgba(0,0,0,0)
                    Row {
                        id:     factRow
                        property Fact modelFact: controller.getParameterFact(componentId, modelData)
                        spacing: Math.ceil(ScreenTools.defaultFontPixelWidth * 0.5)
                        anchors.verticalCenter: parent.verticalCenter
                        QGCLabel {
                            id:     nameLabel
                            width:  ScreenTools.defaultFontPixelWidth  * 20
                            text:   factRow.modelFact.name
Don Gagne's avatar
Don Gagne committed
275
                            clip:   true
dogmaphobic's avatar
dogmaphobic committed
276 277 278 279
                        }
                        QGCLabel {
                            id:     valueLabel
                            width:  ScreenTools.defaultFontPixelWidth  * 20
280
                            color:  factRow.modelFact.defaultValueAvailable ? (factRow.modelFact.valueEqualsDefault ? __qgcPal.text : __qgcPal.warningText) : __qgcPal.text
281
                            text:   factRow.modelFact.enumStrings.length == 0 ? factRow.modelFact.valueString + " " + factRow.modelFact.units : factRow.modelFact.enumStringValue
Don Gagne's avatar
Don Gagne committed
282
                            clip:   true
dogmaphobic's avatar
dogmaphobic committed
283 284 285 286 287 288
                        }
                        QGCLabel {
                            text:   factRow.modelFact.shortDescription
                        }
                        Component.onCompleted: {
                            if(_rowWidth < factRow.width + ScreenTools.defaultFontPixelWidth) {
Don Gagne's avatar
Don Gagne committed
289
                                _rowWidth = factRow.width + ScreenTools.defaultFontPixelWidth
dogmaphobic's avatar
dogmaphobic committed
290 291 292 293 294 295 296 297 298 299 300 301 302 303 304
                            }
                        }
                    }
                    Rectangle {
                        width:  _rowWidth
                        height: 1
                        color:  __qgcPal.text
                        opacity: 0.15
                        anchors.bottom: parent.bottom
                        anchors.left:   parent.left
                    }
                    MouseArea {
                        anchors.fill:       parent
                        acceptedButtons:    Qt.LeftButton
                        onClicked: {
305
                            _editorDialogFact = factRow.modelFact
306
                            showDialog(editorDialogComponent, qsTr("Parameter Editor"), qgcView.showDialogDefaultWidth, StandardButton.Cancel | StandardButton.Save)
dogmaphobic's avatar
dogmaphobic committed
307 308 309 310 311 312 313 314 315
                        }
                    }
                }
            }
        }
    }

    Component {
        id: editorDialogComponent
316 317 318 319 320

        ParameterEditorDialog {
            fact:           _editorDialogFact
            showRCToParam:  _showRCToParam
        }
dogmaphobic's avatar
dogmaphobic committed
321
    }
Don Gagne's avatar
Don Gagne committed
322

Don Gagne's avatar
Don Gagne committed
323 324 325 326 327 328
    Component {
        id: searchDialogComponent

        QGCViewDialog {

            function accept() {
329
                _searchResults = controller.searchParametersForComponent(-1, searchFor.text, true /*searchInName.checked*/, true /*searchInDescriptions.checked*/)
Don Gagne's avatar
Don Gagne committed
330 331 332 333 334 335 336 337 338 339 340
                _searchFilter = true
                hideDialog()
            }

            function reject() {
                _searchFilter = false
                hideDialog()
            }

            QGCLabel {
                id:     searchForLabel
341
                text:   qsTr("Search for:")
Don Gagne's avatar
Don Gagne committed
342 343 344 345 346 347
            }

            QGCTextField {
                id:                 searchFor
                anchors.topMargin:  defaultTextHeight / 3
                anchors.top:        searchForLabel.bottom
dogmaphobic's avatar
dogmaphobic committed
348
                width:              ScreenTools.defaultFontPixelWidth * 20
Don Gagne's avatar
Don Gagne committed
349 350 351 352
            }

            QGCLabel {
                anchors.topMargin:  defaultTextHeight
353
                anchors.top:        searchFor.bottom
Don Gagne's avatar
Don Gagne committed
354 355
                width:              parent.width
                wrapMode:           Text.WordWrap
356
                text:               qsTr("Hint: Leave 'Search For' blank and click Apply to list all parameters sorted by name.")
Don Gagne's avatar
Don Gagne committed
357 358 359 360
            }
        }
    }

Don Gagne's avatar
Don Gagne committed
361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378
    Component {
        id: mobileFilePicker

        QGCMobileFileDialog {
            fileExtension:      QGroundControl.parameterFileExtension
            onFilenameReturned: controller.loadFromFile(filename)
        }
    }

    Component {
        id: mobileFileSaver

        QGCMobileFileDialog {
            openDialog:         false
            fileExtension:      QGroundControl.parameterFileExtension
            onFilenameReturned: controller.saveToFile(filename)
        }
    }
Don Gagne's avatar
Don Gagne committed
379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395

    Component {
        id: resetToDefaultConfirmComponent

        QGCViewDialog {
            function accept() {
                controller.resetAllToDefaults()
                hideDialog()
            }

            QGCLabel {
                width:              parent.width
                wrapMode:           Text.WordWrap
                text:               qsTr("Select Reset to reset all parameters to their defaults.")
            }
        }
    }
396
} // QGCView