From f970a839b3417994803fa6718b5e4edeefa7e456 Mon Sep 17 00:00:00 2001 From: dogmaphobic Date: Tue, 3 Nov 2015 20:56:23 -0500 Subject: [PATCH] UI Tweaks --- qgcresources.qrc | 51 +- .../PX4/AirframeComponent.qml | 49 +- .../PX4/Images/ReturnToHomeAltitude.svg | 81 ++++ .../PX4/Images/SafetyComponentArrowDown.png | Bin 210 -> 0 bytes .../PX4/Images/SafetyComponentHome.png | Bin 628 -> 0 bytes .../PX4/Images/SafetyComponentPlane.png | Bin 502 -> 0 bytes .../PX4/Images/SafetyComponentTree.svg | 19 - src/AutoPilotPlugins/PX4/PowerComponent.qml | 11 +- src/AutoPilotPlugins/PX4/SafetyComponent.qml | 434 ++++++++---------- src/FactSystem/ParameterLoader.cc | 232 +++++----- src/QmlControls/ParameterEditor.qml | 32 +- src/QmlControls/QGCColoredImage.qml | 27 +- src/QmlControls/ScreenTools.qml | 1 + src/QmlControls/SubMenuButton.qml | 6 +- src/VehicleSetup/SetupView.qml | 211 ++++----- src/VehicleSetup/VehicleSummary.qml | 163 ++++--- src/ui/MainWindow.qml | 7 +- src/ui/toolbar/MainToolBar.qml | 24 +- 18 files changed, 715 insertions(+), 633 deletions(-) create mode 100644 src/AutoPilotPlugins/PX4/Images/ReturnToHomeAltitude.svg delete mode 100644 src/AutoPilotPlugins/PX4/Images/SafetyComponentArrowDown.png delete mode 100644 src/AutoPilotPlugins/PX4/Images/SafetyComponentHome.png delete mode 100644 src/AutoPilotPlugins/PX4/Images/SafetyComponentPlane.png delete mode 100644 src/AutoPilotPlugins/PX4/Images/SafetyComponentTree.svg diff --git a/qgcresources.qrc b/qgcresources.qrc index f0886b88a..c6f2e7aac 100644 --- a/qgcresources.qrc +++ b/qgcresources.qrc @@ -1,44 +1,41 @@ - src/AutoPilotPlugins/PX4/Images/SafetyComponentTree.svg - src/AutoPilotPlugins/PX4/Images/SafetyComponentHome.png - src/AutoPilotPlugins/PX4/Images/SafetyComponentArrowDown.png - src/AutoPilotPlugins/PX4/Images/SafetyComponentPlane.png - src/AutoPilotPlugins/PX4/Images/VehicleDown.png - src/AutoPilotPlugins/PX4/Images/VehicleUpsideDown.png - src/AutoPilotPlugins/PX4/Images/VehicleLeft.png - src/AutoPilotPlugins/PX4/Images/VehicleRight.png - src/AutoPilotPlugins/PX4/Images/VehicleNoseDown.png - src/AutoPilotPlugins/PX4/Images/VehicleTailDown.png - src/AutoPilotPlugins/PX4/Images/VehicleDownRotate.png - src/AutoPilotPlugins/PX4/Images/VehicleLeftRotate.png - src/AutoPilotPlugins/PX4/Images/VehicleNoseDownRotate.png - src/AutoPilotPlugins/PX4/Images/AirframeStandardPlane.png + src/AutoPilotPlugins/PX4/Images/AirframeComponentIcon.png src/AutoPilotPlugins/PX4/Images/AirframeFlyingWing.png - src/AutoPilotPlugins/PX4/Images/AirframeQuadRotorX.png - src/AutoPilotPlugins/PX4/Images/AirframeQuadRotorPlus.png - src/AutoPilotPlugins/PX4/Images/AirframeOctoRotorX.png - src/AutoPilotPlugins/PX4/Images/AirframeOctoRotorPlus.png - src/AutoPilotPlugins/PX4/Images/AirframeHexaRotorX.png src/AutoPilotPlugins/PX4/Images/AirframeHexaRotorPlus.png + src/AutoPilotPlugins/PX4/Images/AirframeHexaRotorX.png + src/AutoPilotPlugins/PX4/Images/AirframeOctoRotorPlus.png + src/AutoPilotPlugins/PX4/Images/AirframeOctoRotorX.png src/AutoPilotPlugins/PX4/Images/AirframeQuadRotorH.png + src/AutoPilotPlugins/PX4/Images/AirframeQuadRotorPlus.png + src/AutoPilotPlugins/PX4/Images/AirframeQuadRotorX.png src/AutoPilotPlugins/PX4/Images/AirframeSimulation.png + src/AutoPilotPlugins/PX4/Images/AirframeStandardPlane.png src/QmlControls/arrow-down.png - resources/CogWheels.png - src/AutoPilotPlugins/PX4/Images/SensorsComponentIcon.png - src/AutoPilotPlugins/PX4/Images/RadioComponentIcon.png - src/AutoPilotPlugins/PX4/Images/FlightModesComponentIcon.png - src/AutoPilotPlugins/PX4/Images/AirframeComponentIcon.png - src/AutoPilotPlugins/PX4/Images/SafetyComponentIcon.png - src/AutoPilotPlugins/PX4/Images/PowerComponentIcon.png src/VehicleSetup/FirmwareUpgradeIcon.png - src/VehicleSetup/VehicleSummaryIcon.png + src/AutoPilotPlugins/PX4/Images/FlightModesComponentIcon.png src/AutoPilotPlugins/PX4/Images/PowerComponentBattery_01cell.svg src/AutoPilotPlugins/PX4/Images/PowerComponentBattery_02cell.svg src/AutoPilotPlugins/PX4/Images/PowerComponentBattery_03cell.svg src/AutoPilotPlugins/PX4/Images/PowerComponentBattery_04cell.svg src/AutoPilotPlugins/PX4/Images/PowerComponentBattery_05cell.svg src/AutoPilotPlugins/PX4/Images/PowerComponentBattery_06cell.svg + src/AutoPilotPlugins/PX4/Images/PowerComponentIcon.png + src/AutoPilotPlugins/PX4/Images/RadioComponentIcon.png + src/AutoPilotPlugins/PX4/Images/ReturnToHomeAltitude.svg + src/AutoPilotPlugins/PX4/Images/SafetyComponentIcon.png + src/AutoPilotPlugins/PX4/Images/SensorsComponentIcon.png + resources/CogWheels.png + src/AutoPilotPlugins/PX4/Images/VehicleDown.png + src/AutoPilotPlugins/PX4/Images/VehicleDownRotate.png + src/AutoPilotPlugins/PX4/Images/VehicleLeft.png + src/AutoPilotPlugins/PX4/Images/VehicleLeftRotate.png + src/AutoPilotPlugins/PX4/Images/VehicleNoseDown.png + src/AutoPilotPlugins/PX4/Images/VehicleNoseDownRotate.png + src/AutoPilotPlugins/PX4/Images/VehicleRight.png + src/VehicleSetup/VehicleSummaryIcon.png + src/AutoPilotPlugins/PX4/Images/VehicleTailDown.png + src/AutoPilotPlugins/PX4/Images/VehicleUpsideDown.png src/FlightMap/Images/attitudeDial.svg src/FlightMap/Images/attitudeInstrument.svg diff --git a/src/AutoPilotPlugins/PX4/AirframeComponent.qml b/src/AutoPilotPlugins/PX4/AirframeComponent.qml index f14ed8f69..cd69b4be3 100644 --- a/src/AutoPilotPlugins/PX4/AirframeComponent.qml +++ b/src/AutoPilotPlugins/PX4/AirframeComponent.qml @@ -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 diff --git a/src/AutoPilotPlugins/PX4/Images/ReturnToHomeAltitude.svg b/src/AutoPilotPlugins/PX4/Images/ReturnToHomeAltitude.svg new file mode 100644 index 000000000..2964cb5bf --- /dev/null +++ b/src/AutoPilotPlugins/PX4/Images/ReturnToHomeAltitude.svg @@ -0,0 +1,81 @@ + + + + + + Layer 1 + + + + + + + + + + + + + + + Layer 1 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/AutoPilotPlugins/PX4/Images/SafetyComponentArrowDown.png b/src/AutoPilotPlugins/PX4/Images/SafetyComponentArrowDown.png deleted file mode 100644 index ba7cddb82c325dc18bca9f8713065c9d6b9a05a9..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 210 zcmeAS@N?(olHy`uVBq!ia0vp@K+MU(1|(lrEz1IN3Opi<85p>QL70(Y)*K0-pk#?_ zL`iUdT1k0gQ7VIDN`6wRf@f}GdTLN=VoGJ<$y6JlqIgdi$B>F!Nk9Jo-_Ia$|G&SD z#d!uMhc@PkQumlQGBNWoSpId%&`NM%S6KZqBjS7mFM}%22Mg~8MsWs9#_nYdY)%X- zGVCX{)v+ZpXtXTw+tq(PGQxzd;ZKJzpTYr#LizuJm!6-D1X{)5>FVdQ&MBb@0NJ8H A{{R30 diff --git a/src/AutoPilotPlugins/PX4/Images/SafetyComponentHome.png b/src/AutoPilotPlugins/PX4/Images/SafetyComponentHome.png deleted file mode 100644 index 6a1ef2af464b546e5d93dd3251101b4b97530568..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 628 zcmV-)0*n2LP){#th!!QsHQUBu&+6@R3kPXNNWQ4Fmn1C_?VS_LM=>&ug+zqmUIZIdJwsGV0 zM@cK6^rU<__B%g6oqZ#ONCHO*V1RYdUL=u#XvAO0YZj`nPy|+hUL1#fmR$;w0x$@D z4EW8giPXY8)^j8xwciPPbiUS2>cKBEKo5AZXe--rK<+w-)PuEt1C|c|xCMLxs{gQG zc3`ciq9@3%wUwGrYn@uqHGy~*n#h#3suo)YXzzuHuZ-Hxs523YwT_h`*$6S}8e^_R zGD9iIs7BhCN_*XVVJNlSmPkeD#5CirX2!Tfvb01f)81(Yc4`f94e{2+q7&jErWRu9 zC`D64IZB4DH5LxDIF;Sp#-ewP*ACW7nMG5nQ7pRI5vd%kl_Dh@shQ4lZK})Clay?v zW|FLWs`}jm?g7m~+1>%30vsVc;+7y&o;6tJZ*9x?jk4EJ%XUfPF5r2{61N6wS-&Iq zNhR`vSs3u1VP@WO|8S0Y1+>_Af@3KF&$|6cJz=e`uH+hHu6AhAdu!wer>{M;lx(CX z$F#yR?@8+erNotwt20Z4hVSb4Mz~&Q&|7Z z&UwJ@ya9HBqBx1P)|D|~jGYBW85^yg3FfMA>TTaE1&sNT#y*VM?;of8n{sAmb;d5v ze@+Qw)dJLAlrS2yOnPkt6^w0b0LoXJ8)gQo!9o%_VWy?AMG=6O#<5&5Q|*DVRb=cn z7tECMj?WMocgX=`r5xXWWvs-)FsLb8VIDTEUyBx0V_-Us)96-ZnAugOg1M)>6Gv?H z>r=qYDPK9UIKo#Q4Wr>eb%AQ+{%b-|9Wuzjl=m_e8>@;fUxNgc0iXf9?3gmJ1}FkP z{oa{=7H|yJlpT9g9C6;UK%3f;B*8n=0H~ZdoiCme>fy2mfXo|L`!|i0kA&D6$0H?1Qb3707*qoM6N<$f(`)6&Hw-a diff --git a/src/AutoPilotPlugins/PX4/Images/SafetyComponentTree.svg b/src/AutoPilotPlugins/PX4/Images/SafetyComponentTree.svg deleted file mode 100644 index 2b9645a77..000000000 --- a/src/AutoPilotPlugins/PX4/Images/SafetyComponentTree.svg +++ /dev/null @@ -1,19 +0,0 @@ - - - - - Layer 1 - - - - - - - - - - diff --git a/src/AutoPilotPlugins/PX4/PowerComponent.qml b/src/AutoPilotPlugins/PX4/PowerComponent.qml index c2fe07239..f1202c9bd 100644 --- a/src/AutoPilotPlugins/PX4/PowerComponent.qml +++ b/src/AutoPilotPlugins/PX4/PowerComponent.qml @@ -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() } } diff --git a/src/AutoPilotPlugins/PX4/SafetyComponent.qml b/src/AutoPilotPlugins/PX4/SafetyComponent.qml index 9c6ca9601..9d67694ff 100644 --- a/src/AutoPilotPlugins/PX4/SafetyComponent.qml +++ b/src/AutoPilotPlugins/PX4/SafetyComponent.qml @@ -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 + } } diff --git a/src/FactSystem/ParameterLoader.cc b/src/FactSystem/ParameterLoader.cc index 57a80deff..553c0efff 100644 --- a/src/FactSystem/ParameterLoader.cc +++ b/src/FactSystem/ParameterLoader.cc @@ -1,24 +1,24 @@ /*===================================================================== - + QGroundControl Open Source Ground Control Station - + (c) 2009 - 2014 QGROUNDCONTROL PROJECT - + 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 . - + ======================================================================*/ /// @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(); _waitingWriteParamNameMap[componentId] = QMap(); - + 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(); 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(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(); } 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(); 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 += "
"; } 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("Critical safety issue detected:
%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. " diff --git a/src/QmlControls/ParameterEditor.qml b/src/QmlControls/ParameterEditor.qml index 2e04d8274..16dd51276 100644 --- a/src/QmlControls/ParameterEditor.qml +++ b/src/QmlControls/ParameterEditor.qml @@ -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 diff --git a/src/QmlControls/QGCColoredImage.qml b/src/QmlControls/QGCColoredImage.qml index 716ccf718..84e377f93 100644 --- a/src/QmlControls/QGCColoredImage.qml +++ b/src/QmlControls/QGCColoredImage.qml @@ -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 } diff --git a/src/QmlControls/ScreenTools.qml b/src/QmlControls/ScreenTools.qml index 3852467be..b2c3c4c39 100644 --- a/src/QmlControls/ScreenTools.qml +++ b/src/QmlControls/ScreenTools.qml @@ -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. diff --git a/src/QmlControls/SubMenuButton.qml b/src/QmlControls/SubMenuButton.qml index 708e8bcde..64b0cb4fe 100644 --- a/src/QmlControls/SubMenuButton.qml +++ b/src/QmlControls/SubMenuButton.qml @@ -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 } } diff --git a/src/VehicleSetup/SetupView.qml b/src/VehicleSetup/SetupView.qml index 68b071121..e34cd48ad 100644 --- a/src/VehicleSetup/SetupView.qml +++ b/src/VehicleSetup/SetupView.qml @@ -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 + } } } diff --git a/src/VehicleSetup/VehicleSummary.qml b/src/VehicleSetup/VehicleSummary.qml index a000abdaf..7a0605910 100644 --- a/src/VehicleSetup/VehicleSummary.qml +++ b/src/VehicleSetup/VehicleSummary.qml @@ -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 + } } } } diff --git a/src/ui/MainWindow.qml b/src/ui/MainWindow.qml index cadd828a4..91f0664fa 100644 --- a/src/ui/MainWindow.qml +++ b/src/ui/MainWindow.qml @@ -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 } + } diff --git a/src/ui/toolbar/MainToolBar.qml b/src/ui/toolbar/MainToolBar.qml index fd299ef58..f17c4de32 100644 --- a/src/ui/toolbar/MainToolBar.qml +++ b/src/ui/toolbar/MainToolBar.qml @@ -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 -- 2.22.0