ValuePageWidget.qml 20.7 KB
Newer Older
1 2
/****************************************************************************
 *
Gus Grubba's avatar
Gus Grubba committed
3
 * (c) 2009-2020 QGROUNDCONTROL PROJECT <http://www.qgroundcontrol.org>
4 5 6 7 8
 *
 * QGroundControl is licensed according to the terms in the file
 * COPYING.md in the root of the source code directory.
 *
 ****************************************************************************/
9

DonLakeFlyer's avatar
DonLakeFlyer committed
10
import QtQuick          2.12
11
import QtQuick.Dialogs  1.2
12
import QtQuick.Layouts  1.2
13 14
import QtQuick.Controls 2.5
import QtQml            2.12
15 16 17 18

import QGroundControl.Controls      1.0
import QGroundControl.ScreenTools   1.0
import QGroundControl.FactSystem    1.0
19
import QGroundControl.FactControls  1.0
20 21 22 23
import QGroundControl.Controllers   1.0
import QGroundControl.Palette       1.0
import QGroundControl               1.0

24 25
/// Value page for InstrumentPanel PageView
Column {
26
    id:         _root
27
    width:      pageWidth
28
    spacing:    ScreenTools.defaultFontPixelHeight / 2
29

30
    property bool showSettingsIcon: true
31 32 33 34 35 36
    property bool showLockIcon:     true

    property var    _activeVehicle:                 QGroundControl.multiVehicleManager.activeVehicle ? QGroundControl.multiVehicleManager.activeVehicle : QGroundControl.multiVehicleManager.offlineEditingVehicle
    property real   _margins:                       ScreenTools.defaultFontPixelWidth / 2
    property int    _colMax:                        4
    property bool   _settingsUnlocked:              false
37
    property var    _valueDialogInstrumentValue:    null
38
    property var    _rgFontSizes:                   [ ScreenTools.defaultFontPointSize, ScreenTools.smallFontPointSize, ScreenTools.mediumFontPointSize, ScreenTools.largeFontPointSize ]
39 40 41 42
    property var    _rgFontSizeRatios:              [ 1, ScreenTools.smallFontPointRatio, ScreenTools.mediumFontPointRatio, ScreenTools.largeFontPointRatio ]
    property real   _doubleDescent:                 ScreenTools.defaultFontDescent * 2
    property real   _tightDefaultFontHeight:        ScreenTools.defaultFontPixelHeight - _doubleDescent
    property var    _rgFontSizeTightHeights:        [ _tightDefaultFontHeight * _rgFontSizeRatios[0] + 2, _tightDefaultFontHeight * _rgFontSizeRatios[1] + 2, _tightDefaultFontHeight * _rgFontSizeRatios[2] + 2, _tightDefaultFontHeight * _rgFontSizeRatios[3] + 2 ]
43 44 45 46 47
    property real   _blankEntryHeight:              ScreenTools.defaultFontPixelHeight * 2
    property real   _columnButtonWidth:             ScreenTools.minTouchPixels / 2
    property real   _columnButtonHeight:            ScreenTools.minTouchPixels
    property real   _columnButtonSpacing:           2
    property real   _columnButtonsTotalHeight:      (_columnButtonHeight * 2) + _columnButtonSpacing
48 49

    QGCPalette { id:qgcPal; colorGroupEnabled: true }
50
    QGCPalette { id:qgcPalDisabled; colorGroupEnabled: false }
51

52
    ValuesWidgetController { id: controller }
53

54 55
    function showSettings(settingsUnlocked) {
        _settingsUnlocked = settingsUnlocked
56 57
    }

58 59 60 61 62 63 64 65 66
    function listContains(list, value) {
        for (var i=0; i<list.length; i++) {
            if (list[i] === value) {
                return true
            }
        }
        return false
    }

67
    ButtonGroup { id: factRadioGroup }
68

69
    Component {
70
        id: valueItemMouseAreaComponent
71

72 73 74 75 76 77 78 79 80 81
        MouseArea {
            anchors.centerIn:   parent
            width:              parent.width
            height:             _columnButtonsTotalHeight
            visible:            _settingsUnlocked

            property var instrumentValue
            property int rowIndex

            onClicked: {
82 83
                _valueDialogInstrumentValue = instrumentValue
                mainWindow.showPopupDialog(valueDialog, qsTr("Value Display"), StandardButton.Close)
84 85 86 87
            }
        }
    }

88 89 90
    Repeater {
        id:     rowRepeater
        model:  controller.valuesModel
91 92

        Column {
93 94 95 96 97 98 99 100 101 102 103 104 105 106 107
            id:             rowRepeaterLayout
            spacing:        1

            property int rowIndex: index

            Row {
                id:         columnRow
                spacing:    1

                Repeater {
                    id:     columnRepeater
                    model:  object

                    property real _interColumnSpacing:  (columnRepeater.count - (_settingsUnlocked ? 0 : 1)) * columnRow.spacing
                    property real columnWidth:          (pageWidth - (_settingsUnlocked ? _columnButtonWidth : 0) - _interColumnSpacing) / columnRepeater.count
108
                    property bool componentCompleted:   false
109

110
                    Component.onCompleted: componentCompleted = true
111 112 113
                    onItemAdded: valueItemMouseAreaComponent.createObject(item, { "instrumentValue": object.get(index), "rowIndex": index })

                    Item {
114 115
                        id:                     columnItem
                        anchors.verticalCenter: parent.verticalCenter
116 117
                        width:                  columnRepeater.columnWidth
                        height:                 value.y + value.height
118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143

                        property real columnWidth:                  columnRepeater.columnWidth
                        property bool repeaterComponentCompleted:   columnRepeater.componentCompleted

                        // After fighting with using layout and/or anchors I gave up and just do a manual recalc to position items which ends up being much simpler
                        function recalcPositions() {
                            if (!repeaterComponentCompleted) {
                                return
                            }
                            var smallSpacing = 2
                            if (object.icon) {
                                if (object.iconPosition === InstrumentValue.IconAbove) {
                                    valueIcon.x = (width - valueIcon.width) / 2
                                    valueIcon.y = 0
                                    value.x = (width - value.width) / 2
                                    value.y = valueIcon.height + smallSpacing
                                } else {
                                    var iconPlusValueWidth = valueIcon.width + value.width + ScreenTools.defaultFontPixelWidth
                                    valueIcon.x = (width - iconPlusValueWidth) / 2
                                    valueIcon.y = (value.height - valueIcon.height) / 2
                                    value.x = valueIcon.x + valueIcon.width + (ScreenTools.defaultFontPixelWidth / 2)
                                    value.y = 0
                                }
                                label.x = label.y = 0
                            } else {
                                // label above value
144
                                if (object.label) {
145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178
                                    label.x = (width - label.width) / 2
                                    label.y = 0
                                    value.y = label.height + smallSpacing
                                } else {
                                    value.y = 0
                                }
                                value.x = (width - value.width) / 2
                                valueIcon.x = valueIcon.y = 0
                            }
                        }

                        onRepeaterComponentCompletedChanged:    recalcPositions()
                        onColumnWidthChanged:                   recalcPositions()

                        Connections {
                            target:                 object
                            onIconChanged:          recalcPositions()
                            onIconPositionChanged:  recalcPositions()
                        }

                        QGCColoredImage {
                            id:                         valueIcon
                            height:                     _rgFontSizeTightHeights[object.fontSize]
                            width:                      height
                            source:                     object.icon ? "/InstrumentValueIcons/" + object.icon : ""
                            sourceSize.height:          height
                            fillMode:                   Image.PreserveAspectFit
                            mipmap:                     true
                            smooth:                     true
                            color:                      qgcPal.text
                            visible:                    object.icon
                            onWidthChanged:             columnItem.recalcPositions()
                            onHeightChanged:            columnItem.recalcPositions()
                        }
179 180

                        QGCLabel {
181
                            id:                         blank
182 183 184 185 186 187 188
                            anchors.horizontalCenter:   parent.horizontalCenter
                            height:                     _columnButtonsTotalHeight
                            font.pointSize:             ScreenTools.smallFontPointSize
                            text:                       _settingsUnlocked ? qsTr("BLANK") : ""
                            horizontalAlignment:        Text.AlignHCenter
                            verticalAlignment:          Text.AlignVCenter
                            visible:                    !object.fact
189 190
                            onWidthChanged:             columnItem.recalcPositions()
                            onHeightChanged:            columnItem.recalcPositions()
191 192 193
                        }

                        QGCLabel {
194
                            id:                         label
195
                            height:                     _rgFontSizeTightHeights[InstrumentValue.SmallFontSize]
196 197
                            font.pointSize:             ScreenTools.smallFontPointSize
                            text:                       object.label.toUpperCase()
198 199 200 201
                            verticalAlignment:          Text.AlignVCenter
                            visible:                    object.fact && object.label && !object.icon
                            onWidthChanged:             columnItem.recalcPositions()
                            onHeightChanged:            columnItem.recalcPositions()
202 203 204
                        }

                        QGCLabel {
205 206 207
                            id:                         value
                            font.pointSize:             _rgFontSizes[object.fontSize]
                            text:                       visible ? (object.fact.enumOrValueString + (object.showUnits ? object.fact.units : "")) : ""
208
                            verticalAlignment:          Text.AlignVCenter
209
                            visible:                    object.fact
210 211
                            onWidthChanged:             columnItem.recalcPositions()
                            onHeightChanged:            columnItem.recalcPositions()
212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250
                        }
                    }
                } // Repeater - columns

                ColumnLayout {
                    id:                 columnsButtonsLayout
                    width:              _columnButtonWidth
                    spacing:            _columnButtonSpacing
                    visible:            _settingsUnlocked

                    QGCButton {
                        Layout.fillHeight:      true
                        Layout.minimumHeight:   ScreenTools.minTouchPixels
                        Layout.preferredWidth:  parent.width
                        text:                   qsTr("+")
                        onClicked:              controller.appendColumn(rowRepeaterLayout.rowIndex)
                    }

                    QGCButton {
                        Layout.fillHeight:      true
                        Layout.minimumHeight:   ScreenTools.minTouchPixels
                        Layout.preferredWidth:  parent.width
                        text:                   qsTr("-")
                        enabled:                index !== 0 || columnRepeater.count !== 1
                        onClicked:              controller.deleteLastColumn(rowRepeaterLayout.rowIndex)
                    }
                }
            } // RowLayout

            RowLayout {
                width:      parent.width
                height:             ScreenTools.defaultFontPixelWidth * 2
                spacing:            1
                visible:            _settingsUnlocked

                QGCButton {
                    Layout.fillWidth:   true
                    Layout.preferredHeight: ScreenTools.defaultFontPixelWidth * 2
                    text:               qsTr("+")
251
                    onClicked:          controller.insertRow(index + 1)
252 253 254 255 256 257 258 259 260
                }

                QGCButton {
                    Layout.fillWidth:   true
                    Layout.preferredHeight: ScreenTools.defaultFontPixelWidth * 2
                    text:               qsTr("-")
                    enabled:            index !== 0
                    onClicked:          controller.deleteRow(index)
                }
261 262
            }
        }
263 264 265 266 267 268 269 270
    } // Repeater - rows

    QGCButton {
        anchors.left:   parent.left
        anchors.right:  parent.right
        text:           qsTr("Reset To Defaults")
        visible:        _settingsUnlocked
        onClicked:      controller.resetToDefaults()
271 272
    }

273
    Component {
274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290
        id: valueDialog

        QGCPopupDialog {
            GridLayout {
                rowSpacing:     _margins
                columnSpacing:  _margins
                columns:        3

                QGCCheckBox {
                    id:         valueCheckBox
                    text:       qsTr("Value")
                    checked:    _valueDialogInstrumentValue.fact
                    onClicked: {
                        if (checked) {
                            _valueDialogInstrumentValue.setFact(_valueDialogInstrumentValue.factGroupNames[0], _valueDialogInstrumentValue.factValueNames[0])
                        } else {
                            _valueDialogInstrumentValue.clearFact()
291 292
                        }
                    }
293
                }
294

295 296 297 298 299 300 301 302 303 304
                QGCComboBox {
                    model:                  _valueDialogInstrumentValue.factGroupNames
                    sizeToContents:         true
                    enabled:                valueCheckBox.enabled
                    onModelChanged:         currentIndex = find(_valueDialogInstrumentValue.factGroupName)
                    Component.onCompleted:  currentIndex = find(_valueDialogInstrumentValue.factGroupName)
                    onActivated: {
                        _valueDialogInstrumentValue.setFact(currentText, "")
                        _valueDialogInstrumentValue.icon = ""
                        _valueDialogInstrumentValue.label = _valueDialogInstrumentValue.fact.shortDescription
305
                    }
306
                }
307

308 309 310 311 312 313 314 315 316 317
                QGCComboBox {
                    model:                  _valueDialogInstrumentValue.factValueNames
                    sizeToContents:         true
                    enabled:                valueCheckBox.enabled
                    onModelChanged:         currentIndex = _valueDialogInstrumentValue.fact ? find(_valueDialogInstrumentValue.factName) : -1
                    Component.onCompleted:  currentIndex = _valueDialogInstrumentValue.fact ? find(_valueDialogInstrumentValue.factName) : -1
                    onActivated: {
                        _valueDialogInstrumentValue.setFact(_valueDialogInstrumentValue.factGroupName, currentText)
                        _valueDialogInstrumentValue.icon = ""
                        _valueDialogInstrumentValue.label = _valueDialogInstrumentValue.fact.shortDescription
318
                    }
319
                }
320

321 322 323 324 325 326 327 328
                QGCRadioButton {
                    id:                     iconCheckBox
                    text:                   qsTr("Icon")
                    Component.onCompleted:  checked = _valueDialogInstrumentValue.icon != ""
                    onClicked: {
                        _valueDialogInstrumentValue.label = ""
                        _valueDialogInstrumentValue.icon = _valueDialogInstrumentValue.iconNames[0]
                        mainWindow.showPopupDialog(iconDialog, qsTr("Select Icon"), StandardButton.Close)
329
                    }
330
                }
331

332 333 334 335 336 337 338 339 340 341 342 343 344 345 346
                QGCColoredImage {
                    Layout.alignment:   Qt.AlignHCenter
                    height:             iconPositionCombo.height
                    width:              height
                    source:             "/InstrumentValueIcons/" + (_valueDialogInstrumentValue.icon ? _valueDialogInstrumentValue.icon : _valueDialogInstrumentValue.iconNames[0])
                    sourceSize.height:  height
                    fillMode:           Image.PreserveAspectFit
                    mipmap:             true
                    smooth:             true
                    color:              enabled ? qgcPal.text : qgcPalDisabled.text
                    enabled:            iconCheckBox.checked

                    MouseArea {
                        anchors.fill:   parent
                        onClicked:      mainWindow.showPopupDialog(iconDialog, qsTr("Select Icon"), StandardButton.Close)
DonLakeFlyer's avatar
DonLakeFlyer committed
347
                    }
348
                }
DonLakeFlyer's avatar
DonLakeFlyer committed
349

350 351 352 353 354 355 356 357
                QGCComboBox {
                    id:             iconPositionCombo
                    model:          _valueDialogInstrumentValue.iconPositionNames
                    currentIndex:   _valueDialogInstrumentValue.iconPosition
                    sizeToContents: true
                    onActivated:    _valueDialogInstrumentValue.iconPosition = index
                    enabled:        iconCheckBox.checked
                }
DonLakeFlyer's avatar
DonLakeFlyer committed
358

359 360 361 362 363 364 365
                QGCRadioButton {
                    id:                     labelCheckBox
                    text:                   qsTr("Label")
                    Component.onCompleted:  checked = _valueDialogInstrumentValue.label != ""
                    onClicked: {
                        _valueDialogInstrumentValue.icon = ""
                        _valueDialogInstrumentValue.label = _valueDialogInstrumentValue.fact ? _valueDialogInstrumentValue.fact.shortDescription : qsTr("Label")
366
                    }
367
                }
368

369 370 371 372 373 374
                QGCTextField {
                    id:                 labelTextField
                    Layout.fillWidth:   true
                    Layout.columnSpan:  2
                    text:               _valueDialogInstrumentValue.label
                    enabled:            labelCheckBox.checked
DonLakeFlyer's avatar
DonLakeFlyer committed
375 376
                }

377 378 379 380 381 382 383 384 385
                QGCLabel { text: qsTr("Size") }

                QGCComboBox {
                    id:                 fontSizeCombo
                    Layout.columnSpan:  2
                    model:              _valueDialogInstrumentValue.fontSizeNames
                    currentIndex:       _valueDialogInstrumentValue.fontSize
                    sizeToContents:     true
                    onActivated:        _valueDialogInstrumentValue.fontSize = index
DonLakeFlyer's avatar
DonLakeFlyer committed
386 387
                }

388 389 390 391 392
                QGCCheckBox {
                    Layout.columnSpan:  3
                    text:               qsTr("Show Units")
                    checked:            _valueDialogInstrumentValue.showUnits
                    onClicked:          _valueDialogInstrumentValue.showUnits = checked
DonLakeFlyer's avatar
DonLakeFlyer committed
393 394 395 396 397
                }
            }
        }
    }

398
    Component {
399
        id: iconDialog
400

401 402 403 404 405
        QGCPopupDialog {
            GridLayout {
                columns:        10
                columnSpacing:  0
                rowSpacing:     0
DonLakeFlyer's avatar
DonLakeFlyer committed
406 407

                Repeater {
408
                    model: _valueDialogInstrumentValue.iconNames
409

410 411 412 413
                    Rectangle {
                        height: ScreenTools.minTouchPixels
                        width:  height
                        color:  currentSelection ? qgcPal.text  : qgcPal.window
414

415
                        property bool currentSelection: _valueDialogInstrumentValue.icon == modelData
416

417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433
                        QGCColoredImage {
                            anchors.centerIn:   parent
                            height:             parent.height * 0.75
                            width:              height
                            source:             "/InstrumentValueIcons/" + modelData
                            sourceSize.height:  height
                            fillMode:           Image.PreserveAspectFit
                            mipmap:             true
                            smooth:             true
                            color:              currentSelection ? qgcPal.window : qgcPal.text

                            MouseArea {
                                anchors.fill:   parent
                                onClicked:  {
                                    _valueDialogInstrumentValue.icon = modelData
                                    hideDialog()
                                }
434
                            }
DonLakeFlyer's avatar
DonLakeFlyer committed
435
                        }
436 437 438 439 440 441
                    }
                }
            }
        }
    }
}