Commit f970a839 authored by dogmaphobic's avatar dogmaphobic

UI Tweaks

parent fb371f36
<RCC>
<qresource prefix="/qmlimages">
<file alias="SafetyComponentTree.svg">src/AutoPilotPlugins/PX4/Images/SafetyComponentTree.svg</file>
<file alias="SafetyComponentHome.png">src/AutoPilotPlugins/PX4/Images/SafetyComponentHome.png</file>
<file alias="SafetyComponentArrowDown.png">src/AutoPilotPlugins/PX4/Images/SafetyComponentArrowDown.png</file>
<file alias="SafetyComponentPlane.png">src/AutoPilotPlugins/PX4/Images/SafetyComponentPlane.png</file>
<file alias="VehicleDown.png">src/AutoPilotPlugins/PX4/Images/VehicleDown.png</file>
<file alias="VehicleUpsideDown.png">src/AutoPilotPlugins/PX4/Images/VehicleUpsideDown.png</file>
<file alias="VehicleLeft.png">src/AutoPilotPlugins/PX4/Images/VehicleLeft.png</file>
<file alias="VehicleRight.png">src/AutoPilotPlugins/PX4/Images/VehicleRight.png</file>
<file alias="VehicleNoseDown.png">src/AutoPilotPlugins/PX4/Images/VehicleNoseDown.png</file>
<file alias="VehicleTailDown.png">src/AutoPilotPlugins/PX4/Images/VehicleTailDown.png</file>
<file alias="VehicleDownRotate.png">src/AutoPilotPlugins/PX4/Images/VehicleDownRotate.png</file>
<file alias="VehicleLeftRotate.png">src/AutoPilotPlugins/PX4/Images/VehicleLeftRotate.png</file>
<file alias="VehicleNoseDownRotate.png">src/AutoPilotPlugins/PX4/Images/VehicleNoseDownRotate.png</file>
<file alias="AirframeStandardPlane.png">src/AutoPilotPlugins/PX4/Images/AirframeStandardPlane.png</file>
<file alias="AirframeComponentIcon.png">src/AutoPilotPlugins/PX4/Images/AirframeComponentIcon.png</file>
<file alias="AirframeFlyingWing.png">src/AutoPilotPlugins/PX4/Images/AirframeFlyingWing.png</file>
<file alias="AirframeQuadRotorX.png">src/AutoPilotPlugins/PX4/Images/AirframeQuadRotorX.png</file>
<file alias="AirframeQuadRotorPlus.png">src/AutoPilotPlugins/PX4/Images/AirframeQuadRotorPlus.png</file>
<file alias="AirframeOctoRotorX.png">src/AutoPilotPlugins/PX4/Images/AirframeOctoRotorX.png</file>
<file alias="AirframeOctoRotorPlus.png">src/AutoPilotPlugins/PX4/Images/AirframeOctoRotorPlus.png</file>
<file alias="AirframeHexaRotorX.png">src/AutoPilotPlugins/PX4/Images/AirframeHexaRotorX.png</file>
<file alias="AirframeHexaRotorPlus.png">src/AutoPilotPlugins/PX4/Images/AirframeHexaRotorPlus.png</file>
<file alias="AirframeHexaRotorX.png">src/AutoPilotPlugins/PX4/Images/AirframeHexaRotorX.png</file>
<file alias="AirframeOctoRotorPlus.png">src/AutoPilotPlugins/PX4/Images/AirframeOctoRotorPlus.png</file>
<file alias="AirframeOctoRotorX.png">src/AutoPilotPlugins/PX4/Images/AirframeOctoRotorX.png</file>
<file alias="AirframeQuadRotorH.png">src/AutoPilotPlugins/PX4/Images/AirframeQuadRotorH.png</file>
<file alias="AirframeQuadRotorPlus.png">src/AutoPilotPlugins/PX4/Images/AirframeQuadRotorPlus.png</file>
<file alias="AirframeQuadRotorX.png">src/AutoPilotPlugins/PX4/Images/AirframeQuadRotorX.png</file>
<file alias="AirframeSimulation.png">src/AutoPilotPlugins/PX4/Images/AirframeSimulation.png</file>
<file alias="AirframeStandardPlane.png">src/AutoPilotPlugins/PX4/Images/AirframeStandardPlane.png</file>
<file alias="arrow-down.png">src/QmlControls/arrow-down.png</file>
<file alias="subMenuButtonImage.png">resources/CogWheels.png</file>
<file alias="SensorsComponentIcon.png">src/AutoPilotPlugins/PX4/Images/SensorsComponentIcon.png</file>
<file alias="RadioComponentIcon.png">src/AutoPilotPlugins/PX4/Images/RadioComponentIcon.png</file>
<file alias="FlightModesComponentIcon.png">src/AutoPilotPlugins/PX4/Images/FlightModesComponentIcon.png</file>
<file alias="AirframeComponentIcon.png">src/AutoPilotPlugins/PX4/Images/AirframeComponentIcon.png</file>
<file alias="SafetyComponentIcon.png">src/AutoPilotPlugins/PX4/Images/SafetyComponentIcon.png</file>
<file alias="PowerComponentIcon.png">src/AutoPilotPlugins/PX4/Images/PowerComponentIcon.png</file>
<file alias="FirmwareUpgradeIcon.png">src/VehicleSetup/FirmwareUpgradeIcon.png</file>
<file alias="VehicleSummaryIcon.png">src/VehicleSetup/VehicleSummaryIcon.png</file>
<file alias="FlightModesComponentIcon.png">src/AutoPilotPlugins/PX4/Images/FlightModesComponentIcon.png</file>
<file alias="PowerComponentBattery_01cell.svg">src/AutoPilotPlugins/PX4/Images/PowerComponentBattery_01cell.svg</file>
<file alias="PowerComponentBattery_02cell.svg">src/AutoPilotPlugins/PX4/Images/PowerComponentBattery_02cell.svg</file>
<file alias="PowerComponentBattery_03cell.svg">src/AutoPilotPlugins/PX4/Images/PowerComponentBattery_03cell.svg</file>
<file alias="PowerComponentBattery_04cell.svg">src/AutoPilotPlugins/PX4/Images/PowerComponentBattery_04cell.svg</file>
<file alias="PowerComponentBattery_05cell.svg">src/AutoPilotPlugins/PX4/Images/PowerComponentBattery_05cell.svg</file>
<file alias="PowerComponentBattery_06cell.svg">src/AutoPilotPlugins/PX4/Images/PowerComponentBattery_06cell.svg</file>
<file alias="PowerComponentIcon.png">src/AutoPilotPlugins/PX4/Images/PowerComponentIcon.png</file>
<file alias="RadioComponentIcon.png">src/AutoPilotPlugins/PX4/Images/RadioComponentIcon.png</file>
<file alias="ReturnToHomeAltitude.svg">src/AutoPilotPlugins/PX4/Images/ReturnToHomeAltitude.svg</file>
<file alias="SafetyComponentIcon.png">src/AutoPilotPlugins/PX4/Images/SafetyComponentIcon.png</file>
<file alias="SensorsComponentIcon.png">src/AutoPilotPlugins/PX4/Images/SensorsComponentIcon.png</file>
<file alias="subMenuButtonImage.png">resources/CogWheels.png</file>
<file alias="VehicleDown.png">src/AutoPilotPlugins/PX4/Images/VehicleDown.png</file>
<file alias="VehicleDownRotate.png">src/AutoPilotPlugins/PX4/Images/VehicleDownRotate.png</file>
<file alias="VehicleLeft.png">src/AutoPilotPlugins/PX4/Images/VehicleLeft.png</file>
<file alias="VehicleLeftRotate.png">src/AutoPilotPlugins/PX4/Images/VehicleLeftRotate.png</file>
<file alias="VehicleNoseDown.png">src/AutoPilotPlugins/PX4/Images/VehicleNoseDown.png</file>
<file alias="VehicleNoseDownRotate.png">src/AutoPilotPlugins/PX4/Images/VehicleNoseDownRotate.png</file>
<file alias="VehicleRight.png">src/AutoPilotPlugins/PX4/Images/VehicleRight.png</file>
<file alias="VehicleSummaryIcon.png">src/VehicleSetup/VehicleSummaryIcon.png</file>
<file alias="VehicleTailDown.png">src/AutoPilotPlugins/PX4/Images/VehicleTailDown.png</file>
<file alias="VehicleUpsideDown.png">src/AutoPilotPlugins/PX4/Images/VehicleUpsideDown.png</file>
<file alias="attitudeDial.svg">src/FlightMap/Images/attitudeDial.svg</file>
<file alias="attitudeInstrument.svg">src/FlightMap/Images/attitudeInstrument.svg</file>
......
......@@ -39,6 +39,28 @@ QGCView {
QGCPalette { id: qgcPal; colorGroupEnabled: panel.enabled }
property real _minW: ScreenTools.defaultFontPixelWidth * 30
property real _boxWidth: _minW
property real _boxSpace: ScreenTools.defaultFontPixelWidth
function computeDimensions() {
var sw = 0
var rw = 0
var idx = Math.floor(scroll.width / (_minW + ScreenTools.defaultFontPixelWidth))
if(idx < 1) {
_boxWidth = scroll.width
_boxSpace = 0
} else {
_boxSpace = 0
if(idx > 1) {
_boxSpace = ScreenTools.defaultFontPixelWidth
sw = _boxSpace * (idx - 1)
}
rw = scroll.width - sw
_boxWidth = rw / idx
}
}
AirframeComponentController {
id: controller
factPanel: panel
......@@ -127,16 +149,25 @@ QGCView {
width: 10
}
ScrollView {
id: scroll
anchors.top: lastSpacer.bottom
anchors.bottom: parent.bottom
width: parent.width
horizontalScrollBarPolicy: Qt.ScrollBarAlwaysOff
Flickable {
id: scroll
anchors.top: lastSpacer.bottom
anchors.bottom: parent.bottom
width: parent.width
clip: true
contentHeight: flowView.height
contentWidth: parent.width
boundsBehavior: Flickable.StopAtBounds
flickableDirection: Flickable.VerticalFlick
onWidthChanged: {
computeDimensions()
}
Flow {
id: flowView
width: scroll.width
spacing: ScreenTools.defaultFontPixelWidth
spacing: _boxSpace
ExclusiveGroup {
id: airframeTypeExclusive
......@@ -148,8 +179,8 @@ QGCView {
// Outer summary item rectangle
Rectangle {
id: airframeBackground
width: ScreenTools.defaultFontPixelWidth * 30
height: width * .75
width: _boxWidth
height: ScreenTools.defaultFontPixelWidth * 22.5
color: (modelData.name != controller.currentAirframeType) ? qgcPal.windowShade : qgcPal.buttonHighlight
readonly property real titleHeight: ScreenTools.defaultFontPixelHeight * 1.75
......
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 19.1.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 144 72" style="enable-background:new 0 0 144 72;" xml:space="preserve">
<style type="text/css">
.st0{opacity:0.5;}
.st1{fill:#FFFFFF;}
.st2{fill:none;stroke:#FFFFFF;stroke-miterlimit:10;}
.st3{fill:none;stroke:#FFFFFF;stroke-miterlimit:10;stroke-dasharray:3.0478,3.0478;}
.st4{fill:none;stroke:#FFFFFF;stroke-miterlimit:10;stroke-dasharray:3.6243,3.6243;}
.st5{fill:none;stroke:#FFFFFF;stroke-miterlimit:10;stroke-dasharray:3.0018,3.0018;}
.st6{fill:none;stroke:#FFFFFF;stroke-miterlimit:10;stroke-dasharray:2.9665,2.9665;}
</style>
<g class="st0">
<title>Layer 1</title>
<g id="layer1_1_">
<g id="g4623_1_">
<path id="rect2192_1_" class="st1" d="M77.2,59.3h3.4v7.1c-1,0.5-2.2,0.6-3.4,0V59.3z"/>
<path id="path1307_1_" class="st1" d="M90.9,60.2c-7.6-1.6-15.9,1.7-24,0c5.5-5.1,7.1-15.3,12-20.8
C82.8,44.7,85.2,55.1,90.9,60.2z"/>
<path id="path2183_1_" class="st1" d="M88.5,46.8c-6.1-1.2-12.7,1.4-19.2,0c4.4-4.1,5.7-12.3,9.6-16.6C82,34.5,84,42.8,88.5,46.8
z"/>
<path id="path2185_1_" class="st1" d="M86.3,36.2c-4.7-1-9.8,1-14.8,0c3.4-3.1,4.4-9.5,7.4-12.8C81.3,26.7,82.8,33.1,86.3,36.2z"
/>
</g>
</g>
</g>
<path class="st1" d="M143,37.1c0.1,0.4,0,0.8-0.3,1.1l-6.4,6.1l-1.1,7.7c-0.1,0.4-0.3,0.7-0.7,0.8s-0.7,0.1-1-0.1l-3.3-2.5l-7.9,7.6
c-0.1,0.1-0.2,0.2-0.3,0.2c-0.2,0.1-0.3,0.1-0.5,0.1c-0.3-0.1-0.6-0.2-0.8-0.5l-16.6-27.2c-0.2-0.4-0.2-0.8,0-1.1
c0.1-0.2,0.3-0.3,0.5-0.4c0.2-0.1,0.4-0.1,0.6,0l37,7.7C142.6,36.4,142.9,36.7,143,37.1L143,37.1z M111.3,32L134.8,43l0.1-0.1
c0-0.1,0.1-0.1,0.1-0.2l4.9-4.7L111.3,32z M108,31.6l25.5,18.1l0.8-5.8L108,31.6z M108.6,33.5l13.3,21.7l6.9-6.7
c0.1-0.1,0.3-0.2,0.6-0.4L108.6,33.5z"/>
<g>
<polygon class="st1" points="32,56.6 16.7,38.7 1.4,56.6 5.3,56.6 5.3,69.3 12.9,69.3 12.9,59.1 20.6,59.1 20.6,69.3 28.2,69.3
28.2,56.6 "/>
</g>
<g>
<title>Layer 1</title>
<g id="layer1">
<g id="g4623">
<path id="rect2192" class="st1" d="M69,61.6h3.9v8.3c-1.1,0.5-2.5,0.7-3.9,0V61.6z"/>
<path id="path1307" class="st1" d="M84.9,62.6c-8.9-1.8-18.4,2-27.8,0c6.4-5.9,8.3-17.8,13.9-24.1C75.5,44.7,78.4,56.7,84.9,62.6
z"/>
<path id="path2183" class="st1" d="M82.1,47.1c-7.1-1.4-14.7,1.6-22.2,0C65,42.4,66.5,32.9,71,27.9
C74.6,32.8,76.9,42.4,82.1,47.1z"/>
<path id="path2185" class="st1" d="M79.5,34.9c-5.5-1.1-11.3,1.2-17.1,0c4-3.6,5.1-11,8.6-14.8C73.8,23.8,75.5,31.2,79.5,34.9z"
/>
</g>
</g>
</g>
<g>
<g>
<line class="st2" x1="77.3" y1="5.4" x2="78.8" y2="5.4"/>
<line class="st3" x1="81.8" y1="5.4" x2="123" y2="5.4"/>
<polyline class="st2" points="124.5,5.4 126,5.4 126,6.9 "/>
<line class="st4" x1="126" y1="10.5" x2="126" y2="15.9"/>
<line class="st2" x1="126" y1="17.8" x2="126" y2="19.3"/>
<g>
<polygon class="st1" points="72,5.4 79.5,8.4 77.7,5.4 79.5,2.3 "/>
</g>
<g>
<g>
<polygon class="st1" points="123.3,21.1 123.5,21 125.6,18.8 125.6,25.3 123.3,27.6 "/>
<path class="st1" d="M128.6,27.6l-2.2-2.3v-6.5c0.6,0.8,1.4,1.6,2.2,2.3V27.6z"/>
</g>
</g>
</g>
</g>
<g>
<g>
<line class="st2" x1="16.7" y1="29.4" x2="16.7" y2="27.9"/>
<line class="st5" x1="16.7" y1="24.9" x2="16.7" y2="8.4"/>
<polyline class="st2" points="16.7,6.9 16.7,5.4 18.2,5.4 "/>
<line class="st6" x1="21.2" y1="5.4" x2="67.2" y2="5.4"/>
<line class="st2" x1="68.7" y1="5.4" x2="70.2" y2="5.4"/>
<g>
<polygon class="st1" points="16.7,34.7 19.8,27.2 16.7,29 13.7,27.2 "/>
</g>
</g>
</g>
</svg>
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 18.1.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="356 -168 306 480" enable-background="new 356 -168 306 480" xml:space="preserve">
<g>
<title>Layer 1</title>
<g id="layer1">
<g id="g4623">
<path id="rect2192" fill="#FFFFFF" d="M484.7,225.1h36.7v77.8c-10.8,5.1-23.7,6.6-36.7,0V225.1z"/>
<path id="path1307" fill="#FFFFFF" d="M633.7,234.3c-83.3-16.9-172.7,18.5-261.3,0C432.8,178.9,450.2,67.3,503,8
C545.8,65.7,572.4,178.9,633.7,234.3z"/>
<path id="path2183" fill="#FFFFFF" d="M607.5,89.1c-66.6-13.5-138.1,14.8-208.9,0C446.9,44.8,460.8-44.4,503-91.8
C537.2-45.7,558.5,44.8,607.5,89.1z"/>
<path id="path2185" fill="#FFFFFF" d="M583.6-26.4c-51.3-10.4-106.5,11.4-161.1,0c37.3-34.2,48-103,80.6-139.5
C529.4-130.3,545.8-60.5,583.6-26.4z"/>
</g>
</g>
</g>
</svg>
......@@ -106,13 +106,15 @@ QGCView {
Flickable {
anchors.fill: parent
flickableDirection: Flickable.VerticalFlick
clip: true
contentHeight: innerColumn.height
contentWidth: panel.width
boundsBehavior: Flickable.StopAtBounds
flickableDirection: Flickable.VerticalFlick
Column {
id: innerColumn
anchors.left: parent.left
anchors.right: parent.right
width: panel.width
spacing: ScreenTools.defaultFontPixelHeight
QGCLabel {
......@@ -246,6 +248,7 @@ QGCView {
QGCButton {
text: "Calibrate"
width: ScreenTools.defaultFontPixelWidth * 20
onClicked: controller.calibrateEsc()
}
}
......@@ -279,11 +282,13 @@ QGCView {
QGCButton {
text: "Start Configuration"
width: ScreenTools.defaultFontPixelWidth * 20
onClicked: controller.busConfigureActuators()
}
QGCButton {
text: "End Configuration"
width: ScreenTools.defaultFontPixelWidth * 20
onClicked: controller.StopBusConfigureActuators()
}
}
......
......@@ -21,9 +21,11 @@
======================================================================*/
import QtQuick 2.2
import QtQuick 2.5
import QtQuick.Controls 1.2
import QtQuick.Controls.Styles 1.2
import QtQuick.Layouts 1.2
import QtGraphicalEffects 1.0
import QGroundControl.FactSystem 1.0
import QGroundControl.FactControls 1.0
......@@ -31,281 +33,225 @@ import QGroundControl.Palette 1.0
import QGroundControl.Controls 1.0
import QGroundControl.ScreenTools 1.0
QGCView {
id: rootQGCView
viewPanel: view
QGCPalette { id: palette; colorGroupEnabled: enabled }
FactPanelController { id: controller; factPanel: rootQGCView }
property int flightLineWidth: 2 // width of lines for flight graphic
property int loiterAltitudeColumnWidth: 180 // width of loiter altitude column
property int shadedMargin: 20 // margin inset for shaded areas
property int controlVerticalSpacing: 10 // vertical spacing between controls
property int homeWidth: 50 // width of home graphic
property int planeWidth: 40 // width of plane graphic
property int arrowToHomeSpacing: 20 // space between down arrow and home graphic
property int arrowWidth: 18 // width for arrow graphic
property int firstColumnWidth: 220 // Width of first column in return home triggers area
QGCView {
id: view
anchors.fill: parent
Column {
anchors.fill: parent
//-----------------------------------------------------------------
//-- Return Home Triggers
QGCLabel { text: "Triggers For Return Home"; font.pixelSize: ScreenTools.mediumFontPixelSize; }
Item { height: 10; width: 10 } // spacer
Rectangle {
width: parent.width
height: triggerColumn.height
color: palette.windowShade
Column {
id: triggerColumn
spacing: controlVerticalSpacing
anchors.margins: shadedMargin
anchors.left: parent.left
// Top margin
Item { height: 1; width: 10 }
Row {
spacing: 10
QGCLabel { text: "RC Transmitter Signal Loss"; width: firstColumnWidth; anchors.baseline: rcLossField.baseline }
QGCLabel { text: "Return Home after"; anchors.baseline: rcLossField.baseline }
FactTextField {
id: rcLossField
fact: controller.getParameterFact(-1, "COM_RC_LOSS_T")
showUnits: true
}
}
Row {
spacing: 10
FactCheckBox {
id: telemetryTimeoutCheckbox
anchors.baseline: telemetryLossField.baseline
width: firstColumnWidth
fact: controller.getParameterFact(-1, "COM_DL_LOSS_EN")
checkedValue: 1
uncheckedValue: 0
text: "Telemetry Signal Timeout"
}
QGCLabel { text: "Return Home after"; anchors.baseline: telemetryLossField.baseline }
FactTextField {
id: telemetryLossField
fact: controller.getParameterFact(-1, "COM_DL_LOSS_T")
showUnits: true
enabled: telemetryTimeoutCheckbox.checked
}
}
// Bottom margin
Item { height: 1; width: 10 }
}
}
Item { height: 20; width: 10 } // spacer
//-----------------------------------------------------------------
//-- Return Home Settings
QGCLabel { text: "Return Home Settings"; font.pixelSize: ScreenTools.mediumFontPixelSize; }
Item { height: 10; width: 10 } // spacer
Rectangle {
width: parent.width
height: settingsColumn.height
color: palette.windowShade
Column {
id: settingsColumn
width: parent.width
anchors.margins: shadedMargin
anchors.left: parent.left
Item { height: shadedMargin; width: 10 } // top margin
QGCView {
id: _safetyView
viewPanel: panel
anchors.fill: parent
// This item is the holder for the climb alt and loiter seconds fields
Item {
width: parent.width
height: climbAltitudeColumn.height
FactPanelController { id: controller; factPanel: panel }
Column {
id: climbAltitudeColumn
spacing: controlVerticalSpacing
QGCPalette { id: palette; colorGroupEnabled: enabled }
QGCLabel { text: "Climb to altitude of" }
property real firstColumnWidth: ScreenTools.defaultFontPixelWidth * 28
property real secondColumnWidth: ScreenTools.defaultFontPixelWidth * 25
QGCViewPanel {
id: panel
anchors.fill: parent
Flickable {
clip: true
anchors.fill: parent
contentHeight: safetyColumn.height
contentWidth: parent.width
boundsBehavior: Flickable.StopAtBounds
flickableDirection: Flickable.VerticalFlick
Column {
id: safetyColumn
width: _safetyView.width
//-----------------------------------------------------------------
//-- Return Home Triggers
QGCLabel { text: "Triggers For Return Home"; font.pixelSize: ScreenTools.mediumFontPixelSize; }
Item { height: ScreenTools.defaultFontPixelHeight * 0.5; width: 1 } // spacer
Rectangle {
width: parent.width
height: triggerColumn.height + ScreenTools.defaultFontPixelHeight
color: palette.windowShade
Column {
id: triggerColumn
width: parent.width
spacing: ScreenTools.defaultFontPixelHeight * 0.5
anchors.margins: ScreenTools.defaultFontPixelWidth
anchors.left: parent.left
Item { height: ScreenTools.defaultFontPixelHeight * 0.5; width: 1 } // spacer
Row {
spacing: ScreenTools.defaultFontPixelWidth
QGCLabel {
text: "RC Transmitter Signal Loss"
width: firstColumnWidth
anchors.verticalCenter: parent.verticalCenter
}
QGCLabel {
text: "Return Home after"
width: secondColumnWidth
anchors.verticalCenter: parent.verticalCenter
}
FactTextField {
id: climbField
fact: controller.getParameterFact(-1, "RTL_RETURN_ALT")
showUnits: true
id: rcLossField
fact: controller.getParameterFact(-1, "COM_RC_LOSS_T")
showUnits: true
anchors.verticalCenter: parent.verticalCenter
}
}
Column {
x: flightGraphic.width - 200
spacing: controlVerticalSpacing
QGCCheckBox {
id: homeLoiterCheckbox
checked: fact.value > 0
text: "Loiter at Home altitude for"
property Fact fact: controller.getParameterFact(-1, "RTL_LAND_DELAY")
onClicked: {
fact.value = checked ? 60 : -1
}
Row {
spacing: ScreenTools.defaultFontPixelWidth
FactCheckBox {
id: telemetryTimeoutCheckbox
width: firstColumnWidth
fact: controller.getParameterFact(-1, "COM_DL_LOSS_EN")
checkedValue: 1
uncheckedValue: 0
text: "Telemetry Signal Timeout"
anchors.verticalCenter: parent.verticalCenter
}
QGCLabel {
text: "Return Home after"
width: secondColumnWidth
anchors.verticalCenter: parent.verticalCenter
}
FactTextField {
fact: controller.getParameterFact(-1, "RTL_LAND_DELAY")
showUnits: true
enabled: homeLoiterCheckbox.checked == true
id: telemetryLossField
fact: controller.getParameterFact(-1, "COM_DL_LOSS_T")
showUnits: true
enabled: telemetryTimeoutCheckbox.checked
anchors.verticalCenter: parent.verticalCenter
}
}
Item { height: ScreenTools.defaultFontPixelHeight * 0.5; width: 1 } // spacer
}
}
Item { height: 20; width: 10 } // spacer
Item { height: ScreenTools.defaultFontPixelHeight; width: 1 } // spacer
// This row holds the flight graphic and the home loiter alt column
Row {
width: parent.width
spacing: 20
//-----------------------------------------------------------------
//-- Return Home Settings
// Flight graphic
Item {
id: flightGraphic
width: parent.width - loiterAltitudeColumnWidth
height: 200 // controls the height of the flight graphic
Rectangle {
x: planeWidth / 2
height: planeImage.y - 5
width: flightLineWidth
color: palette.button
}
Rectangle {
x: planeWidth / 2
height: flightLineWidth
width: parent.width - x
color: palette.button
}
Rectangle {
x: parent.width - flightLineWidth
height: parent.height - homeWidth - arrowToHomeSpacing
width: flightLineWidth
color: palette.button
}
QGCColoredImage {
id: planeImage
y: parent.height - planeWidth - 40
source: "/qmlimages/SafetyComponentPlane.png"
fillMode: Image.PreserveAspectFit
width: planeWidth
height: planeWidth
smooth: true
color: palette.button
}
QGCLabel { text: "Return Home Settings"; font.pixelSize: ScreenTools.mediumFontPixelSize; }
QGCColoredImage {
x: planeWidth + 70
y: parent.height - height - 20
width: 80
height: parent.height / 2
source: "/qmlimages/SafetyComponentTree.svg"
fillMode: Image.Stretch
smooth: true
color: palette.windowShadeDark
}
Item { height: ScreenTools.defaultFontPixelHeight * 0.5; width: 1 } // spacer
QGCColoredImage {
x: planeWidth + 15
y: parent.height - height
width: 100
height: parent.height * .75
source: "/qmlimages/SafetyComponentTree.svg"
fillMode: Image.PreserveAspectFit
smooth: true
color: palette.button
}
Rectangle {
width: parent.width
height: settingsRow.height
color: palette.windowShade
QGCColoredImage {
x: parent.width - (arrowWidth/2) - 1
y: parent.height - homeWidth - arrowToHomeSpacing - 2
source: "/qmlimages/SafetyComponentArrowDown.png"
fillMode: Image.PreserveAspectFit
width: arrowWidth
height: arrowWidth
smooth: true
color: palette.button
Row {
id: settingsRow
anchors.margins: ScreenTools.defaultFontPixelWidth
anchors.left: parent.left
spacing: ScreenTools.defaultFontPixelWidth
Item {
width: firstColumnWidth
height: firstColumnWidth * 0.65
Image {
id: icon
width: parent.width
height: parent.width * 0.5
mipmap: true
fillMode: Image.PreserveAspectFit
visible: false
source: "/qmlimages/ReturnToHomeAltitude.svg"
anchors.verticalCenter: parent.verticalCenter
anchors.horizontalCenter: parent.horizontalCenter
}
QGCColoredImage {
id: homeImage
x: parent.width - (homeWidth / 2)
y: parent.height - homeWidth
source: "/qmlimages/SafetyComponentHome.png"
fillMode: Image.PreserveAspectFit
width: homeWidth
height: homeWidth
smooth: true
color: palette.button
ColorOverlay {
id: iconOverlay
anchors.fill: icon
source: icon
color: palette.button
}
anchors.verticalCenter: parent.verticalCenter
}
Column {
spacing: controlVerticalSpacing
width: parent.width - firstColumnWidth
spacing: ScreenTools.defaultFontPixelHeight * 0.5
anchors.margins: ScreenTools.defaultFontPixelWidth
anchors.verticalCenter: parent.verticalCenter
Item { height: ScreenTools.defaultFontPixelHeight * 0.5; width: 1 } // spacer
Row {
spacing: ScreenTools.defaultFontPixelWidth
QGCLabel {
text: "Climb to altitude of"
width: secondColumnWidth
anchors.verticalCenter: parent.verticalCenter
}
FactTextField {
id: climbField
fact: controller.getParameterFact(-1, "RTL_RETURN_ALT")
showUnits: true
anchors.verticalCenter: parent.verticalCenter
}
}
Row {
spacing: ScreenTools.defaultFontPixelWidth
QGCCheckBox {
id: homeLoiterCheckbox
width: secondColumnWidth
checked: fact.value > 0
text: "Loiter at Home altitude for"
anchors.verticalCenter: parent.verticalCenter
property Fact fact: controller.getParameterFact(-1, "RTL_LAND_DELAY")
onClicked: {
fact.value = checked ? 60 : -1
}
}
FactTextField {
id: landDelayField
fact: controller.getParameterFact(-1, "RTL_LAND_DELAY")
showUnits: true
enabled: homeLoiterCheckbox.checked === true
anchors.verticalCenter: parent.verticalCenter
}
QGCLabel {
text: "Home loiter altitude";
color: palette.text;
enabled: homeLoiterCheckbox.checked === true
}
FactTextField {
id: descendField;
fact: controller.getParameterFact(-1, "RTL_DESCEND_ALT")
enabled: homeLoiterCheckbox.checked === true
showUnits: true
Row {
spacing: ScreenTools.defaultFontPixelWidth
QGCLabel {
text: "Home loiter altitude";
color: palette.text;
enabled: homeLoiterCheckbox.checked === true
width: secondColumnWidth
anchors.verticalCenter: parent.verticalCenter
}
FactTextField {
id: descendField;
fact: controller.getParameterFact(-1, "RTL_DESCEND_ALT")
enabled: homeLoiterCheckbox.checked === true
showUnits: true
anchors.verticalCenter: parent.verticalCenter
}
}
Item { height: ScreenTools.defaultFontPixelHeight; width: 1 } // spacer
}
}
Item { height: shadedMargin; width: 10 } // bottom margin
}
}
QGCLabel {
width: parent.width
font.pixelSize: ScreenTools.mediumFontPixelSize
text: "Warning: You have an advanced safety configuration set using the NAV_RCL_OBC parameter. The above settings may not apply.";
visible: fact.value !== 0
wrapMode: Text.Wrap
QGCLabel {
width: parent.width
font.pixelSize: ScreenTools.mediumFontPixelSize
text: "Warning: You have an advanced safety configuration set using the NAV_RCL_OBC parameter. The above settings may not apply.";
visible: fact.value !== 0
wrapMode: Text.Wrap
property Fact fact: controller.getParameterFact(-1, "NAV_RCL_OBC")
}
property Fact fact: controller.getParameterFact(-1, "NAV_RCL_OBC")
}
QGCLabel {
width: parent.width
font.pixelSize: ScreenTools.mediumFontPixelSize
text: "Warning: You have an advanced safety configuration set using the NAV_DLL_OBC parameter. The above settings may not apply.";
visible: fact.value !== 0
wrapMode: Text.Wrap
QGCLabel {
width: parent.width
font.pixelSize: ScreenTools.mediumFontPixelSize
text: "Warning: You have an advanced safety configuration set using the NAV_DLL_OBC parameter. The above settings may not apply.";
visible: fact.value !== 0
wrapMode: Text.Wrap
property Fact fact: controller.getParameterFact(-1, "NAV_DLL_OBC")
property Fact fact: controller.getParameterFact(-1, "NAV_DLL_OBC")
}
}
}
} // QGCVIew
}
}
/*=====================================================================
QGroundControl Open Source Ground Control Station
(c) 2009 - 2014 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/>.
======================================================================*/
/// @file
......@@ -59,10 +59,10 @@ ParameterLoader::ParameterLoader(AutoPilotPlugin* autopilot, Vehicle* vehicle, Q
Q_ASSERT(_autopilot);
Q_ASSERT(_vehicle);
Q_ASSERT(_mavlink);
// We signal this to ouselves in order to start timer on our thread
connect(this, &ParameterLoader::restartWaitingParamTimer, this, &ParameterLoader::_restartWaitingParamTimer);
_waitingParamTimeoutTimer.setSingleShot(true);
_waitingParamTimeoutTimer.setInterval(1000);
connect(&_waitingParamTimeoutTimer, &QTimer::timeout, this, &ParameterLoader::_waitingParamTimeout);
......@@ -70,7 +70,7 @@ ParameterLoader::ParameterLoader(AutoPilotPlugin* autopilot, Vehicle* vehicle, Q
_cacheTimeoutTimer.setSingleShot(true);
_cacheTimeoutTimer.setInterval(2500);
connect(&_cacheTimeoutTimer, &QTimer::timeout, this, &ParameterLoader::refreshAllParameters);
// FIXME: Why not direct connect?
connect(_vehicle->uas(), SIGNAL(parameterUpdate(int, int, QString, int, int, int, QVariant)), this, SLOT(_parameterUpdate(int, int, QString, int, int, int, QVariant)));
......@@ -87,12 +87,12 @@ ParameterLoader::~ParameterLoader()
void ParameterLoader::_parameterUpdate(int uasId, int componentId, QString parameterName, int parameterCount, int parameterId, int mavType, QVariant value)
{
bool setMetaData = false;
// Is this for our uas?
if (uasId != _vehicle->id()) {
return;
}
qCDebug(ParameterLoaderLog) << "_parameterUpdate (usaId:" << uasId <<
"componentId:" << componentId <<
"name:" << parameterName <<
......@@ -101,7 +101,7 @@ void ParameterLoader::_parameterUpdate(int uasId, int componentId, QString param
"mavType:" << mavType <<
"value:" << value <<
")";
#if 0
// Handy for testing retry logic
static int counter = 0;
......@@ -118,10 +118,10 @@ void ParameterLoader::_parameterUpdate(int uasId, int componentId, QString param
return;
}
_dataMutex.lock();
// Restart our waiting for param timer
_waitingParamTimeoutTimer.start();
// Update our total parameter counts
if (!_paramCountMap.contains(componentId)) {
_paramCountMap[componentId] = parameterCount;
......@@ -129,7 +129,7 @@ void ParameterLoader::_parameterUpdate(int uasId, int componentId, QString param
}
_mapParameterId2Name[componentId][parameterId] = parameterName;
// If we've never seen this component id before, setup the wait lists.
if (!_waitingReadParamIndexMap.contains(componentId)) {
// Add all indices to the wait list, parameter index is 0-based
......@@ -137,14 +137,14 @@ void ParameterLoader::_parameterUpdate(int uasId, int componentId, QString param
// This will add the new component id, as well as the the new waiting index and set the retry count for that index to 0
_waitingReadParamIndexMap[componentId][waitingIndex] = 0;
}
// The read and write waiting lists for this component are initialized the empty
_waitingReadParamNameMap[componentId] = QMap<QString, int>();
_waitingWriteParamNameMap[componentId] = QMap<QString, int>();
qCDebug(ParameterLoaderLog) << "Seeing component for first time, id:" << componentId << "parameter count:" << parameterCount;
}
// Remove this parameter from the waiting lists
_waitingReadParamIndexMap[componentId].remove(parameterId);
_waitingReadParamNameMap[componentId].remove(parameterName);
......@@ -154,11 +154,11 @@ void ParameterLoader::_parameterUpdate(int uasId, int componentId, QString param
qCDebug(ParameterLoaderLog) << "_waitingWriteParamNameMap" << _waitingWriteParamNameMap[componentId];
// Track how many parameters we are still waiting for
int waitingReadParamIndexCount = 0;
int waitingReadParamNameCount = 0;
int waitingWriteParamNameCount = 0;
foreach(int waitingComponentId, _waitingReadParamIndexMap.keys()) {
waitingReadParamIndexCount += _waitingReadParamIndexMap[waitingComponentId].count();
}
......@@ -166,21 +166,21 @@ void ParameterLoader::_parameterUpdate(int uasId, int componentId, QString param
qCDebug(ParameterLoaderLog) << "waitingReadParamIndexCount:" << waitingReadParamIndexCount;
}
foreach(int waitingComponentId, _waitingReadParamNameMap.keys()) {
waitingReadParamNameCount += _waitingReadParamNameMap[waitingComponentId].count();
}
if (waitingReadParamNameCount) {
qCDebug(ParameterLoaderLog) << "waitingReadParamNameCount:" << waitingReadParamNameCount;
}
foreach(int waitingComponentId, _waitingWriteParamNameMap.keys()) {
waitingWriteParamNameCount += _waitingWriteParamNameMap[waitingComponentId].count();
}
if (waitingWriteParamNameCount) {
qCDebug(ParameterLoaderLog) << "waitingWriteParamNameCount:" << waitingWriteParamNameCount;
}
int waitingParamCount = waitingReadParamIndexCount + waitingReadParamNameCount + waitingWriteParamNameCount;
if (waitingParamCount) {
qCDebug(ParameterLoaderLog) << "waitingParamCount:" << waitingParamCount;
......@@ -195,7 +195,7 @@ void ParameterLoader::_parameterUpdate(int uasId, int componentId, QString param
} else {
emit parameterListProgress((float)(_totalParamCount - waitingParamCount) / (float)_totalParamCount);
}
// Attempt to determine default component id
if (_defaultComponentId == FactSystem::defaultComponentId && _defaultComponentIdParam.isEmpty()) {
_defaultComponentIdParam = _vehicle->firmwarePlugin()->getDefaultComponentIdParam();
......@@ -203,10 +203,10 @@ void ParameterLoader::_parameterUpdate(int uasId, int componentId, QString param
if (!_defaultComponentIdParam.isEmpty() && _defaultComponentIdParam == parameterName) {
_defaultComponentId = componentId;
}
if (!_mapParameterName2Variant.contains(componentId) || !_mapParameterName2Variant[componentId].contains(parameterName)) {
qCDebug(ParameterLoaderLog) << "Adding new fact";
FactMetaData::ValueType_t factType;
switch (mavType) {
case MAV_PARAM_TYPE_UINT8:
......@@ -238,34 +238,34 @@ void ParameterLoader::_parameterUpdate(int uasId, int componentId, QString param
qCritical() << "Unsupported fact type" << mavType;
break;
}
Fact* fact = new Fact(componentId, parameterName, factType, this);
setMetaData = true;
_mapParameterName2Variant[componentId][parameterName] = QVariant::fromValue(fact);
// We need to know when the fact changes from QML so that we can send the new value to the parameter manager
connect(fact, &Fact::_containerValueChanged, this, &ParameterLoader::_valueUpdated);
}
Q_ASSERT(_mapParameterName2Variant[componentId].contains(parameterName));
Fact* fact = _mapParameterName2Variant[componentId][parameterName].value<Fact*>();
Q_ASSERT(fact);
fact->_containerSetValue(value);
if (setMetaData) {
_vehicle->firmwarePlugin()->addMetaDataToFact(fact);
}
_dataMutex.unlock();
if (waitingParamCount == 0) {
// Now that we know vehicle is up to date persist
_saveToEEPROM();
_writeLocalParamCache();
}
_checkInitialLoadComplete();
}
......@@ -276,19 +276,19 @@ void ParameterLoader::_valueUpdated(const QVariant& value)
{
Fact* fact = qobject_cast<Fact*>(sender());
Q_ASSERT(fact);
int componentId = fact->componentId();
QString name = fact->name();
_dataMutex.lock();
Q_ASSERT(_waitingWriteParamNameMap.contains(componentId));
_waitingWriteParamNameMap[componentId].remove(name); // Remove any old entry
_waitingWriteParamNameMap[componentId][name] = 0; // Add new entry and set retry count
_waitingParamTimeoutTimer.start();
_dataMutex.unlock();
_writeParameterRaw(componentId, fact->name(), value);
qCDebug(ParameterLoaderLog) << "Set parameter (componentId:" << componentId << "name:" << name << value << ")";
}
......@@ -296,7 +296,7 @@ void ParameterLoader::_valueUpdated(const QVariant& value)
void ParameterLoader::refreshAllParameters(void)
{
_dataMutex.lock();
// Reset index wait lists
foreach (int componentId, _paramCountMap.keys()) {
// Add/Update all indices to the wait list, parameter index is 0-based
......@@ -305,16 +305,16 @@ void ParameterLoader::refreshAllParameters(void)
_waitingReadParamIndexMap[componentId][waitingIndex] = 0;
}
}
_dataMutex.unlock();
MAVLinkProtocol* mavlink = qgcApp()->toolbox()->mavlinkProtocol();
Q_ASSERT(mavlink);
mavlink_message_t msg;
mavlink_msg_param_request_list_pack(mavlink->getSystemId(), mavlink->getComponentId(), &msg, _vehicle->id(), MAV_COMP_ID_ALL);
_vehicle->sendMessage(msg);
qCDebug(ParameterLoaderLog) << "Request to refresh all parameters";
}
......@@ -324,7 +324,7 @@ void ParameterLoader::_determineDefaultComponentId(void)
// We don't have a default component id yet. That means the plugin can't provide
// the param to trigger off of. Instead we use the most prominent component id in
// the set of parameters. Better than nothing!
_defaultComponentId = -1;
foreach(int componentId, _mapParameterName2Variant.keys()) {
if (_mapParameterName2Variant[componentId].count() > _defaultComponentId) {
......@@ -342,7 +342,7 @@ int ParameterLoader::_actualComponentId(int componentId)
componentId = _defaultComponentId;
Q_ASSERT(componentId != FactSystem::defaultComponentId);
}
return componentId;
}
......@@ -350,17 +350,17 @@ void ParameterLoader::refreshParameter(int componentId, const QString& name)
{
componentId = _actualComponentId(componentId);
qCDebug(ParameterLoaderLog) << "refreshParameter (component id:" << componentId << "name:" << name << ")";
_dataMutex.lock();
Q_ASSERT(_waitingReadParamNameMap.contains(componentId));
if (_waitingReadParamNameMap.contains(componentId)) {
_waitingReadParamNameMap[componentId].remove(name); // Remove old wait entry if there
_waitingReadParamNameMap[componentId][name] = 0; // Add new wait entry and update retry count
emit restartWaitingParamTimer();
}
_dataMutex.unlock();
_readParameterRaw(componentId, name, -1);
......@@ -381,7 +381,7 @@ void ParameterLoader::refreshParametersPrefix(int componentId, const QString& na
bool ParameterLoader::parameterExists(int componentId, const QString& name)
{
bool ret = false;
componentId = _actualComponentId(componentId);
if (_mapParameterName2Variant.contains(componentId)) {
ret = _mapParameterName2Variant[componentId].contains(name);
......@@ -393,24 +393,24 @@ bool ParameterLoader::parameterExists(int componentId, const QString& name)
Fact* ParameterLoader::getFact(int componentId, const QString& name)
{
componentId = _actualComponentId(componentId);
if (!_mapParameterName2Variant.contains(componentId) || !_mapParameterName2Variant[componentId].contains(name)) {
qgcApp()->reportMissingParameter(componentId, name);
return &_defaultFact;
}
return _mapParameterName2Variant[componentId][name].value<Fact*>();
}
QStringList ParameterLoader::parameterNames(int componentId)
{
QStringList names;
foreach(QString paramName, _mapParameterName2Variant[_actualComponentId(componentId)].keys()) {
names << paramName;
}
return names;
QStringList names;
foreach(QString paramName, _mapParameterName2Variant[_actualComponentId(componentId)].keys()) {
names << paramName;
}
return names;
}
void ParameterLoader::_setupGroupMap(void)
......@@ -433,9 +433,9 @@ void ParameterLoader::_waitingParamTimeout(void)
bool paramsRequested = false;
const int maxBatchSize = 10;
int batchCount = 0;
// We timed out waiting for some parameters from the initial set. Re-request those.
batchCount = 0;
foreach(int componentId, _waitingReadParamIndexMap.keys()) {
foreach(int paramIndex, _waitingReadParamIndexMap[componentId].keys()) {
......@@ -450,7 +450,7 @@ void ParameterLoader::_waitingParamTimeout(void)
paramsRequested = true;
_readParameterRaw(componentId, "", paramIndex);
qCDebug(ParameterLoaderLog) << "Read re-request for (componentId:" << componentId << "paramIndex:" << paramIndex << "retryCount:" << _waitingReadParamIndexMap[componentId][paramIndex] << ")";
if (++batchCount > maxBatchSize) {
goto Out;
}
......@@ -459,7 +459,7 @@ void ParameterLoader::_waitingParamTimeout(void)
}
// We need to check for initial load complete here as well, since it could complete on a max retry failure
_checkInitialLoadComplete();
if (!paramsRequested) {
foreach(int componentId, _waitingWriteParamNameMap.keys()) {
foreach(QString paramName, _waitingWriteParamNameMap[componentId].keys()) {
......@@ -467,14 +467,14 @@ void ParameterLoader::_waitingParamTimeout(void)
_waitingWriteParamNameMap[componentId][paramName]++; // Bump retry count
_writeParameterRaw(componentId, paramName, _autopilot->getFact(FactSystem::ParameterProvider, componentId, paramName)->value());
qCDebug(ParameterLoaderLog) << "Write resend for (componentId:" << componentId << "paramName:" << paramName << "retryCount:" << _waitingWriteParamNameMap[componentId][paramName] << ")";
if (++batchCount > maxBatchSize) {
goto Out;
}
}
}
}
if (!paramsRequested) {
foreach(int componentId, _waitingReadParamNameMap.keys()) {
foreach(QString paramName, _waitingReadParamNameMap[componentId].keys()) {
......@@ -482,14 +482,14 @@ void ParameterLoader::_waitingParamTimeout(void)
_waitingReadParamNameMap[componentId][paramName]++; // Bump retry count
_readParameterRaw(componentId, paramName, -1);
qCDebug(ParameterLoaderLog) << "Read re-request for (componentId:" << componentId << "paramName:" << paramName << "retryCount:" << _waitingReadParamNameMap[componentId][paramName] << ")";
if (++batchCount > maxBatchSize) {
goto Out;
}
}
}
}
Out:
if (paramsRequested) {
_waitingParamTimeoutTimer.start();
......@@ -529,50 +529,50 @@ void ParameterLoader::_writeParameterRaw(int componentId, const QString& paramNa
{
mavlink_param_set_t p;
mavlink_param_union_t union_value;
FactMetaData::ValueType_t factType = _autopilot->getFact(FactSystem::ParameterProvider, componentId, paramName)->type();
p.param_type = _factTypeToMavType(factType);
switch (factType) {
case FactMetaData::valueTypeUint8:
union_value.param_uint8 = (uint8_t)value.toUInt();
break;
case FactMetaData::valueTypeInt8:
union_value.param_int8 = (int8_t)value.toInt();
break;
case FactMetaData::valueTypeUint16:
union_value.param_uint16 = (uint16_t)value.toUInt();
break;
case FactMetaData::valueTypeInt16:
union_value.param_int16 = (int16_t)value.toInt();
break;
case FactMetaData::valueTypeUint32:
union_value.param_uint32 = (uint32_t)value.toUInt();
break;
case FactMetaData::valueTypeFloat:
union_value.param_float = value.toFloat();
break;
default:
qCritical() << "Unsupported fact type" << factType;
// fall through
case FactMetaData::valueTypeInt32:
union_value.param_int32 = (int32_t)value.toInt();
break;
}
p.param_value = union_value.param_float;
p.target_system = (uint8_t)_vehicle->id();
p.target_component = (uint8_t)componentId;
strncpy(p.param_id, paramName.toStdString().c_str(), sizeof(p.param_id));
mavlink_message_t msg;
mavlink_msg_param_set_encode(_mavlink->getSystemId(), _mavlink->getComponentId(), &msg, &p);
_vehicle->sendMessage(msg);
......@@ -658,7 +658,7 @@ QString ParameterLoader::readParametersFromStream(QTextStream& stream)
{
QString errors;
bool userWarned = false;
while (!stream.atEnd()) {
QString line = stream.readLine();
if (!line.startsWith("#")) {
......@@ -675,13 +675,13 @@ QString ParameterLoader::readParametersFromStream(QTextStream& stream)
if (button == QGCMessageBox::Cancel) {
return QString();
}
}
}
int componentId = wpParams.at(1).toInt();
QString paramName = wpParams.at(2);
QString valStr = wpParams.at(3);
uint mavType = wpParams.at(4).toUInt();
if (!_autopilot->factExists(FactSystem::ParameterProvider, componentId, paramName)) {
QString error;
error = QString("Skipped parameter %1:%2 - does not exist on this vehicle\n").arg(componentId).arg(paramName);
......@@ -689,7 +689,7 @@ QString ParameterLoader::readParametersFromStream(QTextStream& stream)
qCDebug(ParameterLoaderLog) << error;
continue;
}
Fact* fact = _autopilot->getFact(FactSystem::ParameterProvider, componentId, paramName);
if (fact->type() != _mavTypeToFactType((MAV_PARAM_TYPE)mavType)) {
QString error;
......@@ -698,13 +698,13 @@ QString ParameterLoader::readParametersFromStream(QTextStream& stream)
qCDebug(ParameterLoaderLog) << error;
continue;
}
qCDebug(ParameterLoaderLog) << "Updating parameter" << componentId << paramName << valStr;
fact->setValue(valStr);
}
}
}
return errors;
}
......@@ -718,11 +718,11 @@ void ParameterLoader::writeParametersToStream(QTextStream &stream)
foreach (QString paramName, _mapParameterName2Variant[componentId].keys()) {
Fact* fact = _mapParameterName2Variant[componentId][paramName].value<Fact*>();
Q_ASSERT(fact);
stream << _vehicle->id() << "\t" << componentId << "\t" << paramName << "\t" << fact->valueString() << "\t" << QString("%1").arg(_factTypeToMavType(fact->type())) << "\n";
}
}
stream.flush();
}
......@@ -731,26 +731,26 @@ MAV_PARAM_TYPE ParameterLoader::_factTypeToMavType(FactMetaData::ValueType_t fac
switch (factType) {
case FactMetaData::valueTypeUint8:
return MAV_PARAM_TYPE_UINT8;
case FactMetaData::valueTypeInt8:
return MAV_PARAM_TYPE_INT8;
case FactMetaData::valueTypeUint16:
return MAV_PARAM_TYPE_UINT16;
case FactMetaData::valueTypeInt16:
return MAV_PARAM_TYPE_INT16;
case FactMetaData::valueTypeUint32:
return MAV_PARAM_TYPE_UINT32;
case FactMetaData::valueTypeFloat:
return MAV_PARAM_TYPE_REAL32;
default:
qWarning() << "Unsupported fact type" << factType;
// fall through
case FactMetaData::valueTypeInt32:
return MAV_PARAM_TYPE_INT32;
}
......@@ -761,26 +761,26 @@ FactMetaData::ValueType_t ParameterLoader::_mavTypeToFactType(MAV_PARAM_TYPE mav
switch (mavType) {
case MAV_PARAM_TYPE_UINT8:
return FactMetaData::valueTypeUint8;
case MAV_PARAM_TYPE_INT8:
return FactMetaData::valueTypeInt8;
case MAV_PARAM_TYPE_UINT16:
return FactMetaData::valueTypeUint16;
case MAV_PARAM_TYPE_INT16:
return FactMetaData::valueTypeInt16;
case MAV_PARAM_TYPE_UINT32:
return FactMetaData::valueTypeUint32;
case MAV_PARAM_TYPE_REAL32:
return FactMetaData::valueTypeFloat;
default:
qWarning() << "Unsupported mav param type" << mavType;
// fall through
case MAV_PARAM_TYPE_INT32:
return FactMetaData::valueTypeInt32;
}
......@@ -797,18 +797,18 @@ void ParameterLoader::_checkInitialLoadComplete(void)
if (_initialLoadComplete) {
return;
}
foreach (int componentId, _waitingReadParamIndexMap.keys()) {
if (_waitingReadParamIndexMap[componentId].count()) {
// We are still waiting on some parameters, not done yet
return;
}
}
// We aren't waiting for any more initial parameter updates, initial parameter loading is complete
_initialLoadComplete = true;
// Check for load failures
QString indexList;
bool initialLoadFailures = false;
......@@ -822,20 +822,20 @@ void ParameterLoader::_checkInitialLoadComplete(void)
qCDebug(ParameterLoaderLog) << "Gave up on initial load after max retries (componentId:" << componentId << "paramIndex:" << paramIndex << ")";
}
}
// Check for any errors during vehicle boot
UASMessageHandler* msgHandler = qgcApp()->toolbox()->uasMessageHandler();
if (msgHandler->getErrorCountTotal()) {
QString errors;
bool firstError = true;
bool errorsFound = false;
msgHandler->lockAccess();
foreach (UASMessage* msg, msgHandler->messages()) {
if (msg->severityIsError()) {
if (!firstError) {
errors += "\n";
errors += "<br>";
}
errors += " - ";
errors += msg->getText();
......@@ -845,15 +845,15 @@ void ParameterLoader::_checkInitialLoadComplete(void)
}
msgHandler->showErrorsInToolbar();
msgHandler->unlockAccess();
if (errorsFound) {
QString errorMsg = QString("Errors were detected during vehicle startup. You should resolve these prior to flight.\n%1").arg(errors);
QString errorMsg = QString("<b>Critical safety issue detected:</b><br>%1").arg(errors);
qgcApp()->showToolBarMessage(errorMsg);
}
}
// Warn of parameter load failure
if (initialLoadFailures) {
QGCMessageBox::critical("Parameter Load Failure",
"QGroundControl was unable to retrieve the full set of parameters from the vehicle. "
......
......@@ -62,7 +62,7 @@ QGCView {
id: editorDialogComponent
ParameterEditorDialog { fact: __editorDialogFact }
} // Component - Editor Dialog
}
Component {
id: searchDialogComponent
......@@ -207,14 +207,17 @@ QGCView {
id: groupedViewComponent
Item {
ScrollView {
id : groupScroll
width: defaultTextWidth * 25
height: parent.height
Component.onCompleted: flickableItem.flickableDirection = Flickable.VerticalFlick
Flickable {
id : groupScroll
width: defaultTextWidth * 25
height: parent.height
clip: true
contentHeight: groupedViewComponentColumn.height
contentWidth: groupedViewComponentColumn.width
boundsBehavior: Flickable.StopAtBounds
flickableDirection: Flickable.VerticalFlick
Column {
id: groupedViewComponentColumn
Repeater {
model: controller.componentIds
......@@ -261,24 +264,27 @@ QGCView {
} // Column - Component
} // Repeater - Components
} // Column - Component
} // ScrollView - Groups
} // Flickable - Groups
ScrollView {
Flickable {
id: factScrollView
anchors.left: groupScroll.right
anchors.right: parent.right
height: parent.height
contentHeight: factRowsLoader.height
contentWidth: panel.width * 2 //-- TODO: Find how to get actual resulting width. "factRowsLoader.sourceComponent.width" doesn't work.
boundsBehavior: Flickable.StopAtBounds
clip: true
Loader {
id: factRowsLoader
width: factScrollView.width
sourceComponent: factRowsComponent
property int componentId: controller.componentIds[0]
property string group: controller.getGroupsForComponent(controller.componentIds[0])[0]
property var parameterNames: controller.getParametersForGroup(componentId, group)
}
} // ScrollView - Facts
} // Flickable - Facts
} // Item
} // Component - groupedViewComponent
......@@ -291,6 +297,8 @@ QGCView {
anchors.left: parent.left
anchors.right: parent.right
height: parent.height
horizontalScrollBarPolicy: Qt.ScrollBarAlwaysOff
verticalScrollBarPolicy: Qt.ScrollBarAlwaysOff
Loader {
id: factRowsLoader
......
......@@ -8,20 +8,20 @@ import QGroundControl.Palette 1.0
Item {
property color color: "white" // Image color
property alias asynchronous: image.asynchronous
property alias cache: image.cache
property alias fillMode: image.fillMode
property alias asynchronous: image.asynchronous
property alias cache: image.cache
property alias fillMode: image.fillMode
property alias horizontalAlignment: image.horizontalAlignment
property alias mirror: image.mirror
property alias paintedHeight: image.paintedHeight
property alias paintedWidth: image.paintedWidth
property alias progress: image.progress
property alias smooth: image.smooth
property alias mipmap: image.mipmap
property alias source: image.source
property alias sourceSize: image.sourceSize
property alias status: image.status
property alias verticalAlignment: image.verticalAlignment
property alias mirror: image.mirror
property alias paintedHeight: image.paintedHeight
property alias paintedWidth: image.paintedWidth
property alias progress: image.progress
property alias smooth: image.smooth
property alias mipmap: image.mipmap
property alias source: image.source
property alias sourceSize: image.sourceSize
property alias status: image.status
property alias verticalAlignment: image.verticalAlignment
width: image.width
height: image.height
......@@ -32,6 +32,7 @@ Item {
mipmap: true
antialiasing: true
visible: false
fillMode: Image.PreserveAspectFit
anchors.fill: parent
}
......
......@@ -19,6 +19,7 @@ Item {
readonly property real _defaultFontHeight: 16
readonly property real fontHRatio: isTinyScreen ? (_textMeasure.contentHeight / _defaultFontHeight) * 0.75 : (_textMeasure.contentHeight / _defaultFontHeight)
readonly property real realFontHeight: _textMeasure.contentHeight
readonly property real realFontWidth : _textMeasure.contentWidth
// On OSX ElCapitan with Qt 5.4.0 any font pixel size above 19 shows garbage test. No idea why at this point.
// Will remove Math.min when problem is figure out.
......
......@@ -45,13 +45,11 @@ Button {
anchors.rightMargin: ScreenTools.defaultFontPixelWidth / 3
anchors.right: parent.right
anchors.verticalCenter: parent.verticalCenter
width: radius * 2
width: ScreenTools.defaultFontPixelWidth
height: width
radius: indicatorRadius
radius: width / 2
color: control.setupComplete ? "#00d932" : "red"
visible: control.setupIndicator
readonly property real indicatorRadius: (ScreenTools.defaultFontPixelHeight * .75) / 2
}
}
......
......@@ -36,6 +36,7 @@ import QGroundControl.ScreenTools 1.0
import QGroundControl.MultiVehicleManager 1.0
Rectangle {
//color: qgcPal.windowShadeDark
color: qgcPal.window
z: QGroundControl.zOrderTopMost
......@@ -203,133 +204,115 @@ Rectangle {
}
Rectangle {
//-- Fill entire screen, including behind tool bar
anchors.fill: parent
color: qgcPal.windowShadeDark
/* I think this takes too much space and is not exactly necessary
QGCLabel {
id: title
anchors.topMargin: _margin
anchors.top: parent.top
anchors.left: parent.left
anchors.right: parent.right
horizontalAlignment: Text.AlignHCenter
font.pixelSize: ScreenTools.largeFontPixelSize
text: "Vehicle Setup"
}
*/
Rectangle {
//-- Limit height to available height (below tool bar)
anchors.topMargin: _margin
//anchors.top: title.bottom
height: mainWindow.avaiableHeight
//-- Limit height to available height (below tool bar)
anchors.topMargin: _margin
height: mainWindow.avaiableHeight
anchors.bottom: parent.bottom
anchors.left: parent.left
anchors.right: parent.right
color: qgcPal.window
Flickable {
id: buttonScroll
width: _buttonWidth
anchors.topMargin: _defaultTextHeight / 2
anchors.top: parent.top
anchors.bottom: parent.bottom
anchors.left: parent.left
anchors.right: parent.right
color: qgcPal.window
ScrollView {
id: buttonScroll
width: _buttonWidth
anchors.topMargin: _defaultTextHeight / 2
anchors.top: parent.top
anchors.bottom: parent.bottom
frameVisible: false
horizontalScrollBarPolicy: Qt.ScrollBarAlwaysOff
verticalScrollBarPolicy: Qt.ScrollBarAlwaysOff
Column {
id: buttonColumn
width: _buttonWidth
spacing: _defaultTextHeight / 2
SubMenuButton {
id: summaryButton
width: _buttonWidth
imageResource: "/qmlimages/VehicleSummaryIcon.png"
setupIndicator: false
checked: true
exclusiveGroup: setupButtonGroup
text: "SUMMARY"
onClicked: showSummaryPanel()
}
SubMenuButton {
id: firmwareButton
width: _buttonWidth
imageResource: "/qmlimages/FirmwareUpgradeIcon.png"
setupIndicator: false
exclusiveGroup: setupButtonGroup
visible: !ScreenTools.isMobile
text: "FIRMWARE"
onClicked: showFirmwarePanel()
}
clip: true
contentHeight: buttonColumn.height
contentWidth: parent.width
boundsBehavior: Flickable.StopAtBounds
flickableDirection: Flickable.VerticalFlick
Column {
id: buttonColumn
width: _buttonWidth
spacing: _defaultTextHeight / 2
SubMenuButton {
id: summaryButton
width: _buttonWidth
imageResource: "/qmlimages/VehicleSummaryIcon.png"
setupIndicator: false
checked: true
exclusiveGroup: setupButtonGroup
text: "SUMMARY"
onClicked: showSummaryPanel()
}
SubMenuButton {
id: firmwareButton
width: _buttonWidth
imageResource: "/qmlimages/FirmwareUpgradeIcon.png"
setupIndicator: false
exclusiveGroup: setupButtonGroup
visible: !ScreenTools.isMobile
text: "FIRMWARE"
onClicked: showFirmwarePanel()
}
SubMenuButton {
id: joystickButton
width: _buttonWidth
setupIndicator: true
setupComplete: joystickManager.activeJoystick ? joystickManager.activeJoystick.calibrated : false
exclusiveGroup: setupButtonGroup
visible: _fullParameterVehicleAvailable && joystickManager.joysticks.length != 0
text: "JOYSTICK"
onClicked: showJoystickPanel()
}
Repeater {
model: _fullParameterVehicleAvailable ? multiVehicleManager.activeVehicle.autopilot.vehicleComponents : 0
SubMenuButton {
id: joystickButton
width: _buttonWidth
setupIndicator: true
setupComplete: joystickManager.activeJoystick ? joystickManager.activeJoystick.calibrated : false
imageResource: modelData.iconResource
setupIndicator: modelData.requiresSetup
setupComplete: modelData.setupComplete
exclusiveGroup: setupButtonGroup
visible: _fullParameterVehicleAvailable && joystickManager.joysticks.length != 0
text: "JOYSTICK"
text: modelData.name.toUpperCase()
onClicked: showJoystickPanel()
onClicked: showVehicleComponentPanel(modelData)
}
}
Repeater {
model: _fullParameterVehicleAvailable ? multiVehicleManager.activeVehicle.autopilot.vehicleComponents : 0
SubMenuButton {
width: _buttonWidth
imageResource: modelData.iconResource
setupIndicator: modelData.requiresSetup
setupComplete: modelData.setupComplete
exclusiveGroup: setupButtonGroup
text: modelData.name.toUpperCase()
SubMenuButton {
width: _buttonWidth
setupIndicator: false
exclusiveGroup: setupButtonGroup
visible: multiVehicleManager.parameterReadyVehicleAvailable
text: "PARAMETERS"
onClicked: showVehicleComponentPanel(modelData)
}
}
SubMenuButton {
width: _buttonWidth
setupIndicator: false
exclusiveGroup: setupButtonGroup
visible: multiVehicleManager.parameterReadyVehicleAvailable
text: "PARAMETERS"
onClicked: showParametersPanel()
}
onClicked: showParametersPanel()
}
SubMenuButton {
width: _buttonWidth
setupIndicator: false
exclusiveGroup: setupButtonGroup
visible: ScreenTools.isDebug
text: "DEBUG"
SubMenuButton {
width: _buttonWidth
setupIndicator: false
exclusiveGroup: setupButtonGroup
visible: ScreenTools.isDebug
text: "DEBUG"
onClicked: showDebugPanel()
}
onClicked: showDebugPanel()
}
} // Column
} // ScrollView
Loader {
id: panelLoader
anchors.topMargin: _margin
anchors.bottomMargin: _margin
anchors.leftMargin: _defaultTextWidth
anchors.rightMargin: _defaultTextWidth
anchors.left: buttonScroll.right
anchors.right: parent.right
anchors.top: parent.top
anchors.bottom: parent.bottom
}
}
Loader {
id: panelLoader
anchors.topMargin: _margin
anchors.bottomMargin: _margin
anchors.leftMargin: _defaultTextWidth
anchors.rightMargin: _defaultTextWidth
anchors.left: buttonScroll.right
anchors.right: parent.right
anchors.top: parent.top
anchors.bottom: parent.bottom
}
}
}
......@@ -32,81 +32,126 @@ import QGroundControl.MultiVehicleManager 1.0
import QGroundControl.Palette 1.0
Rectangle {
color: qgcPal.window
id: _summaryRoot
anchors.fill: parent
color: qgcPal.window
property real _minSummaryW: ScreenTools.defaultFontPixelWidth * 30
property real _summaryBoxWidth: _minSummaryW
property real _summaryBoxSpace: ScreenTools.defaultFontPixelWidth
function computeSummaryBoxSize() {
var sw = 0
var rw = 0
var idx = Math.floor(_summaryRoot.width / (_minSummaryW + ScreenTools.defaultFontPixelWidth))
if(idx < 1) {
_summaryBoxWidth = _summaryRoot.width
_summaryBoxSpace = 0
} else {
_summaryBoxSpace = 0
if(idx > 1) {
_summaryBoxSpace = ScreenTools.defaultFontPixelWidth
sw = _summaryBoxSpace * (idx - 1)
}
rw = _summaryRoot.width - sw
_summaryBoxWidth = rw / idx
}
}
function capitalizeWords(sentence) {
return sentence.replace(/(?:^|\s)\S/g, function(a) { return a.toUpperCase(); });
}
QGCPalette {
id: qgcPal
colorGroupEnabled: enabled
}
Column {
anchors.fill: parent
spacing: ScreenTools.defaultFontPixelHeight
QGCLabel {
width: parent.width
wrapMode: Text.WordWrap
color: setupComplete ? qgcPal.text : qgcPal.warningText
font.pixelSize: ScreenTools.mediumFontPixelSize
text: setupComplete ?
"Below you will find a summary of the settings for your vehicle. To the left are the setup menus for each component." :
"WARNING: Your vehicle requires setup prior to flight. Please resolve the items marked in red using the menu on the left."
property bool setupComplete: multiVehicleManager.activeVehicle.autopilot.setupComplete
}
Flow {
width: parent.width
spacing: ScreenTools.defaultFontPixelWidth
Component.onCompleted: {
computeSummaryBoxSize()
}
Repeater {
model: multiVehicleManager.activeVehicle.autopilot.vehicleComponents
onWidthChanged: {
computeSummaryBoxSize()
}
Flickable {
clip: true
anchors.fill: parent
contentHeight: summaryColumn.height
contentWidth: _summaryRoot.width
flickableDirection: Flickable.VerticalFlick
boundsBehavior: Flickable.StopAtBounds
Column {
id: summaryColumn
width: _summaryRoot.width
spacing: ScreenTools.defaultFontPixelHeight
QGCLabel {
width: parent.width
wrapMode: Text.WordWrap
color: setupComplete ? qgcPal.text : qgcPal.warningText
font.pixelSize: ScreenTools.mediumFontPixelSize
text: setupComplete ?
"Below you will find a summary of the settings for your vehicle. To the left are the setup menus for each component." :
"WARNING: Your vehicle requires setup prior to flight. Please resolve the items marked in red using the menu on the left."
property bool setupComplete: multiVehicleManager.activeVehicle.autopilot.setupComplete
}
// Outer summary item rectangle
Rectangle {
width: ScreenTools.defaultFontPixelWidth * 28
height: ScreenTools.defaultFontPixelHeight * 13
color: qgcPal.window
Flow {
id: _flowCtl
width: _summaryRoot.width
spacing: _summaryBoxSpace
readonly property real titleHeight: ScreenTools.defaultFontPixelHeight * 2
Repeater {
model: multiVehicleManager.activeVehicle.autopilot.vehicleComponents
// Title bar
// Outer summary item rectangle
Rectangle {
id: titleBar
width: parent.width
height: titleHeight
color: qgcPal.windowShade
// Title text
QGCLabel {
anchors.fill: parent
verticalAlignment: TextEdit.AlignVCenter
horizontalAlignment: TextEdit.AlignHCenter
text: modelData.name.toUpperCase()
}
width: _summaryBoxWidth
height: ScreenTools.defaultFontPixelHeight * 13
color: qgcPal.window
readonly property real titleHeight: ScreenTools.defaultFontPixelHeight * 2
// Setup indicator
// Title bar
Rectangle {
anchors.rightMargin: ScreenTools.defaultFontPixelWidth / 3
anchors.right: parent.right
anchors.verticalCenter: parent.verticalCenter
width: 10//radius * 2
height: 10//height
radius: (ScreenTools.defaultFontPixelHeight * .75) * 2
color: modelData.setupComplete ? "#00d932" : "red"
visible: modelData.requiresSetup
id: titleBar
width: parent.width
height: titleHeight
color: qgcPal.windowShade
// Title text
QGCLabel {
anchors.fill: parent
verticalAlignment: TextEdit.AlignVCenter
horizontalAlignment: TextEdit.AlignHCenter
text: capitalizeWords(modelData.name)
}
// Setup indicator
Rectangle {
anchors.rightMargin: ScreenTools.defaultFontPixelWidth / 3
anchors.right: parent.right
anchors.verticalCenter: parent.verticalCenter
width: ScreenTools.defaultFontPixelWidth
height: width
radius: width / 2
color: modelData.setupComplete ? "#00d932" : "red"
visible: modelData.requiresSetup
}
}
}
// Summary Qml
Rectangle {
anchors.top: titleBar.bottom
width: parent.width
Loader {
anchors.fill: parent
source: modelData.summaryQmlSource
// Summary Qml
Rectangle {
anchors.top: titleBar.bottom
width: parent.width
Loader {
anchors.fill: parent
source: modelData.summaryQmlSource
}
}
}
}
......
......@@ -98,6 +98,7 @@ Item {
anchors.left: parent.left
anchors.right: parent.right
anchors.top: parent.top
mainWindow: mainWindow
isBackgroundDark: flightView.isBackgroundDark
z: QGroundControl.zOrderTopMost
}
......@@ -118,11 +119,9 @@ Item {
Loader {
id: setupViewLoader
anchors.bottom: parent.bottom
anchors.right: parent.right
anchors.left: parent.left
height: mainWindow.avaiableHeight
anchors.fill: parent
visible: false
property var tabletPosition: mainWindow.tabletPosition
}
}
......@@ -45,6 +45,7 @@ Rectangle {
QGCPalette { id: qgcPal; colorGroupEnabled: true }
property var activeVehicle: multiVehicleManager.activeVehicle
property var mainWindow: null
property bool isMessageImportant: activeVehicle ? !activeVehicle.messageTypeNormal && !activeVehicle.messageTypeNone : false
property bool isBackgroundDark: true
......@@ -395,22 +396,27 @@ Rectangle {
height: ScreenTools.defaultFontPixelHeight * ScreenTools.fontHRatio * 6
color: Qt.rgba(0,0,0,0.65)
visible: false
QGCLabel {
id: toolBarMessage
ScrollView {
width: toolBarMessageArea.width - toolBarMessageCloseButton.width
wrapMode: Text.WordWrap
color: qgcPal.warningText
lineHeightMode: Text.ProportionalHeight
lineHeight: 1.25
anchors.left: parent.left
anchors.top: parent.top
anchors.bottom: parent.bottom
anchors.margins: tbSpacing
frameVisible: false
horizontalScrollBarPolicy: Qt.ScrollBarAlwaysOff
verticalScrollBarPolicy: Qt.ScrollBarAlwaysOff
QGCLabel {
id: toolBarMessage
width: toolBarMessageArea.width - toolBarMessageCloseButton.width
wrapMode: Text.WordWrap
color: qgcPal.warningText
lineHeightMode: Text.ProportionalHeight
lineHeight: 1.15
anchors.margins: tbSpacing
}
}
QGCButton {
id: toolBarMessageCloseButton
primary: true
text: "Close Message"
text: "Close"
anchors.right: parent.right
anchors.bottom: parent.bottom
anchors.margins: tbSpacing
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment