From 4466d28909bd6d9cf0bd947c54265bb5893e633a Mon Sep 17 00:00:00 2001 From: Philipp Oettershagen Date: Tue, 17 Apr 2018 15:16:42 +0200 Subject: [PATCH 1/3] Automated preflight checklist: Initial commit. Note that this requires an autopilot firmware that writes the respective health flags in the SYS_STATUS mavlink message --- qgcresources.qrc | 1 + qgroundcontrol.qrc | 1 + resources/check.svg | 80 +++++++ src/FlightDisplay/FlightDisplayView.qml | 299 ++++++++++++++++++++++++- src/QmlControls/DropPanel.qml | 2 +- src/QmlControls/QGCCheckListItem.qml | 76 +++++++ src/QmlControls/QGroundControl.Controls.qmldir | 1 + src/Settings/App.SettingsGroup.json | 7 + src/Settings/AppSettings.cc | 11 + src/Settings/AppSettings.h | 4 + src/ui/preferences/GeneralSettings.qml | 10 + 11 files changed, 488 insertions(+), 4 deletions(-) create mode 100644 resources/check.svg create mode 100644 src/QmlControls/QGCCheckListItem.qml diff --git a/qgcresources.qrc b/qgcresources.qrc index 5b6fa54..ff5c03e 100644 --- a/qgcresources.qrc +++ b/qgcresources.qrc @@ -171,6 +171,7 @@ src/FirmwarePlugin/APM/APMBrandImageSub.png src/FirmwarePlugin/PX4/PX4BrandImage.png src/FlightMap/Images/sub.png + resources/check.svg resources/action.svg diff --git a/qgroundcontrol.qrc b/qgroundcontrol.qrc index bf57edb..50ba35c 100644 --- a/qgroundcontrol.qrc +++ b/qgroundcontrol.qrc @@ -87,6 +87,7 @@ src/QmlControls/ParameterEditorDialog.qml src/PlanView/PlanToolBar.qml src/QmlControls/QGCButton.qml + src/QmlControls/QGCCheckListItem.qml src/QmlControls/QGCCheckBox.qml src/QmlControls/QGCColoredImage.qml src/QmlControls/QGCComboBox.qml diff --git a/resources/check.svg b/resources/check.svg new file mode 100644 index 0000000..f5c4901 --- /dev/null +++ b/resources/check.svg @@ -0,0 +1,80 @@ + + + +image/svg+xml \ No newline at end of file diff --git a/src/FlightDisplay/FlightDisplayView.qml b/src/FlightDisplay/FlightDisplayView.qml index 85a4876..e9cdd56 100644 --- a/src/FlightDisplay/FlightDisplayView.qml +++ b/src/FlightDisplay/FlightDisplayView.qml @@ -504,8 +504,8 @@ QGCView { z: _panel.z + 4 title: qsTr("Fly") maxHeight: (_flightVideo.visible ? _flightVideo.y : parent.height) - toolStrip.y - buttonVisible: [ _guidedController.showTakeoff || !_guidedController.showLand, _guidedController.showLand && !_guidedController.showTakeoff, true, true, true, _guidedController.smartShotsAvailable ] - buttonEnabled: [ _guidedController.showTakeoff, _guidedController.showLand, _guidedController.showRTL, _guidedController.showPause, _anyActionAvailable, _anySmartShotAvailable ] + buttonVisible: [ QGroundControl.settingsManager.appSettings.useChecklist.rawValue, _guidedController.showTakeoff || !_guidedController.showLand, _guidedController.showLand && !_guidedController.showTakeoff, true, true, true, _guidedController.smartShotsAvailable ] + buttonEnabled: [ QGroundControl.settingsManager.appSettings.useChecklist.rawValue, _guidedController.showTakeoff, _guidedController.showLand, _guidedController.showRTL, _guidedController.showPause, _anyActionAvailable, _anySmartShotAvailable ] property bool _anyActionAvailable: _guidedController.showStartMission || _guidedController.showResumeMission || _guidedController.showChangeAlt || _guidedController.showLandAbort property bool _anySmartShotAvailable: _guidedController.showOrbit @@ -552,6 +552,11 @@ QGCView { model: [ { + name: "Checklist", + iconSource: "/qmlimages/check.svg", + dropPanelComponent: checklistDropPanel + }, + { name: _guidedController.takeoffTitle, iconSource: "/res/takeoff.svg", action: _guidedController.actionTakeoff @@ -677,4 +682,292 @@ QGCView { visible: false } } -} + + Component { + id: checklistDropPanel + + Rectangle { + id: checklist + width: mainColumn.width + (ScreenTools.defaultFontPixelWidth * 4) + height: (headerColumn.height+mainColumn.height) * 1.07 + color: qgcPal.windowShade + radius: 20 + enabled: QGroundControl.multiVehicleManager.vehicles.count > 0; + + onBatPercentRemainingChanged: {if(_initialized) buttonBattery.updateItem();} + onGpsLockChanged: {buttonSensors.updateItem();} + + // Connections + Connections { + target: _activeVehicle + onUnhealthySensorsChanged: checklist.onUnhealthySensorsChanged(); + } + Connections { + target: QGroundControl.multiVehicleManager + onActiveVehicleChanged: checklist.onActiveVehicleChanged(); + onActiveVehicleAvailableChanged: {} + } + Connections { + target: QGroundControl.settingsManager.appSettings.audioMuted + onValueChanged: buttonSoundOutput.updateItem(); //TODO(philippoe): We are binding to a signal which is explicitly marked as "only for QT internal use" here. + } + Component.onCompleted: { + if(QGroundControl.multiVehicleManager.vehicles.count > 0) { + onActiveVehicleChanged(); + _initialized=true; + } + } + + function updateVehicleDependentItems() { + buttonSensors.updateItem(); + buttonBattery.updateItem(); + buttonRC.updateItem(); + buttonEstimator.updateItem(); + } + function onActiveVehicleChanged() { + buttonSoundOutput.updateItem(); // Just updated here for initialization once we connect to a vehicle + onUnhealthySensorsChanged(); // The health states could all have changed - need to update them. + } + function onUnhealthySensorsChanged() { + var unhealthySensorsStr = _activeVehicle.unhealthySensors; + + // Set to healthy per default + for(var i=0;i<32;i++) _healthFlags[i]=true; + + for(i=0;i 0; + opacity : 0.2+0.8*(QGroundControl.multiVehicleManager.vehicles.count > 0); + + // Checklist items: Standard + QGCCheckListItem { + id: buttonHardware + name: "Hardware" + defaulttext: "Props mounted? Wings secured? Tail secured?" + } + + QGCCheckListItem { + id: buttonBattery + name: "Battery" + pendingtext: "Healthy & charged > 40%. Battery connector firmly plugged?" + function updateItem() { + if (!_activeVehicle) { + _state = 0; + } else { + if (checklist._healthFlags[25] && batPercentRemaining>=40.0) _state = 1+3*(_nrClicked>0); + else { + if(!checklist._healthFlags[25]) buttonBattery.failuretext="Not healthy. Check console."; + else if(batPercentRemaining<40.0) buttonBattery.failuretext="Low (below 40%). Please recharge."; + buttonBattery._state = 3; + } + } + } + } + + QGCCheckListItem { + id: buttonSensors + name: "Sensors" + function updateItem() { + if (!_activeVehicle) { + _state = 0; + } else { + if(checklist._healthFlags[0] && + checklist._healthFlags[1] && + checklist._healthFlags[2] && + checklist._healthFlags[3] && + checklist._healthFlags[4] && + checklist._healthFlags[5]) { + if(!gpsLock) { + buttonSensors.pendingtext="Pending. Waiting for GPS lock."; + buttonSensors._state=1; + } else { + _state = 4; // All OK + } + } else { + if(!checklist._healthFlags[0]) failuretext="Failure. Gyroscope issues. Check console."; + else if(!checklist._healthFlags[1]) failuretext="Failure. Accelerometer issues. Check console."; + else if(!checklist._healthFlags[2]) failuretext="Failure. Magnetometer issues. Check console."; + else if(!checklist._healthFlags[3]) failuretext="Failure. Barometer issues. Check console."; + else if(!checklist._healthFlags[4]) failuretext="Failure. Airspeed sensor issues. Check console."; + else if(!checklist._healthFlags[5]) failuretext="Failure. No valid or low quality GPS signal. Check console."; + _state = 3; + } + } + } + } + QGCCheckListItem { + id: buttonRC + name: "Radio Control" + pendingtext: "Receiving signal. Perform range test & confirm." + failuretext: "No signal or invalid autopilot-RC config. Check RC and console." + function updateItem() { + if (!_activeVehicle) { + _state = 0; + } else { + if (_healthFlags[16]) {_state = 1+3*(_nrClicked>0);} + else {_state = 3;} + } + } + } + + QGCCheckListItem { + id: buttonEstimator + name: "Global position estimate" + function updateItem() { + if (!_activeVehicle) { + _state = 0; + } else { + if (_healthFlags[21]) {_state = 4;} + else {_state = 3;} + } + } + } + + // Arming header + //Rectangle {anchors.left:parent.left ; anchors.right:parent.right ; height:1 ; color:qgcPal.text} + QGCLabel {anchors.horizontalCenter:parent.horizontalCenter ; text:qsTr("Please arm the vehicle here.")} + //Rectangle {anchors.left:parent.left ; anchors.right:parent.right ; height:1 ; color:qgcPal.text} + + QGCCheckListItem { + id: buttonActuators + name: "Actuators" + group: 1 + defaulttext: "Move all control surfaces. Did they work properly?" + } + + QGCCheckListItem { + id: buttonMotors + name: "Motors" + group: 1 + defaulttext: "Propellers free? Then throttle up gently. Working properly?" + } + + QGCCheckListItem { + id: buttonMission + name: "Mission" + group: 1 + defaulttext: "Please confirm mission is valid (waypoints valid, no terrain collision)." + } + + QGCCheckListItem { + id: buttonSoundOutput + name: "Sound output" + group: 1 + pendingtext: "QGC audio output enabled. System audio output enabled, too?" + failuretext: "Failure, QGC audio output is disabled. Please enable it under application settings->general to hear audio warnings!" + function updateItem() { + if (!_activeVehicle) { + _state = 0; + } else { + if (QGroundControl.settingsManager.appSettings.audioMuted.rawValue) {_state = 3;_nrClicked=0;} + else {_state = 1+3*(_nrClicked>0);} + } + } + } + + // Directly before launch header + //Rectangle {anchors.left:parent.left ; anchors.right:parent.right ; height:1 ; color:qgcPal.text} + QGCLabel {anchors.horizontalCenter:parent.horizontalCenter ; text:qsTr("Last preparations before launch") ; opacity : 0.2+0.8*(_checkState >= 2);} + //Rectangle {anchors.left:parent.left ; anchors.right:parent.right ; height:1 ; color:qgcPal.text} + + QGCCheckListItem { + id: buttonPayload + name: "Payload" + group: 2 + defaulttext: "Configured and started?" + pendingtext: "Payload lid closed?" + } + + QGCCheckListItem { + id: buttonWeather + name: "Wind & weather" + group: 2 + defaulttext: "OK for your platform?" + pendingtext: "Launching into the wind?" + } + + QGCCheckListItem { + id: buttonFlightAreaFree + name: "Flight area" + group: 2 + defaulttext: "Launch area and path free of obstacles/people?" + } + + } // Column + + property bool _initialized:false + property var _healthFlags: [] + property int _checkState: _activeVehicle ? (_activeVehicle.armed ? 1 + (buttonActuators._state + buttonMotors._state + buttonMission._state + buttonSoundOutput._state) / 4 / 4 : 0) : 0 ; // Shows progress of checks inside the checklist - unlocks next check steps in groups + property bool gpsLock: _activeVehicle ? _activeVehicle.gps.lock.rawValue>=3 : 0 + property var batPercentRemaining: _activeVehicle ? _activeVehicle.battery.getFact("percentRemaining").value : 0 + + // TODO: Having access to MAVLINK enums (or at least QML consts) would be much cleaner than the code below + property int subsystem_type_gyro : 1 + property int subsystem_type_acc : 2 + property int subsystem_type_mag : 4 + property int subsystem_type_abspressure : 8 + property int subsystem_type_diffpressure : 16 + property int subsystem_type_gps : 32 + property int subsystem_type_positioncontrol : 16384 + property int subsystem_type_motorcontrol : 32768 + property int subsystem_type_rcreceiver : 65536 + property int subsystem_type_ahrs : 2097152 + property int subsystem_type_terrain : 4194304 + property int subsystem_type_reversemotor : 8388608 + property int subsystem_type_logging : 16777216 + property int subsystem_type_sensorbattery : 33554432 + property int subsystem_type_rangefinder : 67108864 + } //Rectangle + } //Component +} //QGC View diff --git a/src/QmlControls/DropPanel.qml b/src/QmlControls/DropPanel.qml index 91fe3dc..1de3e1c 100644 --- a/src/QmlControls/DropPanel.qml +++ b/src/QmlControls/DropPanel.qml @@ -64,7 +64,7 @@ Item { } if (visible) { visible = false - _dropDownComponent = undefined + //_dropDownComponent = undefined //TODO (philippoe) such that drop down component state is not deleted - check with don gagne whether this is necessary toolStrip.uncheckAll() } } diff --git a/src/QmlControls/QGCCheckListItem.qml b/src/QmlControls/QGCCheckListItem.qml new file mode 100644 index 0000000..cd1e82c --- /dev/null +++ b/src/QmlControls/QGCCheckListItem.qml @@ -0,0 +1,76 @@ +import QtQuick 2.3 +import QtQuick.Controls 1.2 +import QtQuick.Controls.Styles 1.4 + +import QGroundControl 1.0 +import QGroundControl.Palette 1.0 +import QGroundControl.ScreenTools 1.0 + +QGCButton { + property string name: "" + property int _state: 0 + property var _color: qgcPal.button;//qgcPal.windowShade;//qgcPal.windowShadeDark;//Qt.rgba(0.5,0.5,0.5,1) //qgcPal.window;// + property int _nrClicked: 0 + property int group: 0 + property string defaulttext: "Not checked yet" + property string pendingtext: "" + property string failuretext: "Failure. Check console." + property string _text: qsTr(name)+ ": " + qsTr(defaulttext) + + enabled : (_activeVehicle==null || _activeVehicle.connectionLost) ? false : _checkState>=group + opacity : (_activeVehicle==null || _activeVehicle.connectionLost) ? 0.4 : 0.2+0.8*(_checkState >= group); + + width: parent.width + style: ButtonStyle { + background: Rectangle {color:_color; border.color: qgcPal.button; radius:3} + label: Label { + text: _text + wrapMode: Text.WordWrap + horizontalAlignment: Text.AlignHCenter + color: _state>0 ? qgcPal.mapWidgetBorderLight : qgcPal.buttonText + } + } + + onClicked: { + if(_state<2) _nrClicked=_nrClicked+1; //Only allow click-counter to increase when not failed yet + updateItem(); + } + onPendingtextChanged: { if(_state==1) {getTextFromState(); getColorFromState();} } + onFailuretextChanged: { if(_state==3) {getTextFromState(); getColorFromState();} } + on_StateChanged: { getTextFromState(); getColorFromState(); } +// onEnabledChanged: { //Dont do this for now, because if we only accidentially lose connection, we don't want to delete the checklist state. Instead, we'd need to detect a re-connect, maybe based on the timesincesystemstart (i.e. when it decreases)? +// if(enabled==false && group > 0) { +// // Reset all check list items of group > 0 if it is disabled again (which e.g. happens after a vehicle reboot or disarm). +// _nrClicked = 0; +// _state = 0; +// } +// } + + function updateItem() { + // This is the default updateFunction. It assumes the item is a MANUAL check list item, i.e. one that + // only requires user clicks (one click if pendingtext="", two clicks otherwise) for completion. + //if(_nrClicked>0) _state = 4; + + if(_nrClicked===1) { + if(pendingtext.length === 0) _state = 4; + else _state = 1; + } else if(_nrClicked>1) _state = 4; + + getTextFromState(); + getColorFromState(); + } + function getTextFromState() { + if(_state === 0) {_text= qsTr(name) + ": " + qsTr(defaulttext)} // Not checked yet + else if(_state === 1) {_text= ""+qsTr(name)+"" +": " + qsTr(pendingtext)} // Pending + else if(_state === 2) {_text= ""+qsTr(name)+"" +": " + qsTr("Minor problem")} // Small problem or need further user action to resolve + else if(_state === 3) {_text= ""+qsTr(name)+"" +": " + qsTr(failuretext)} // Big problem + else {_text= ""+qsTr(name)+"" +": " + qsTr("OK")} // All OK + } + function getColorFromState() { + if(_state === 0) {_color=qgcPal.button} // Not checked yet + else if(_state === 1) {_color=Qt.rgba(0.9,0.47,0.2,1)} // Pending + else if(_state === 2) {_color=Qt.rgba(1.0,0.6,0.2,1)} // Small problem or need further user action to resolve + else if(_state === 3) {_color=Qt.rgba(0.92,0.22,0.22,1)} // Big problem + else {_color=Qt.rgba(0.27,0.67,0.42,1)} // All OK + } +} diff --git a/src/QmlControls/QGroundControl.Controls.qmldir b/src/QmlControls/QGroundControl.Controls.qmldir index 6bbe56f..22e8f16 100644 --- a/src/QmlControls/QGroundControl.Controls.qmldir +++ b/src/QmlControls/QGroundControl.Controls.qmldir @@ -34,6 +34,7 @@ ParameterEditor 1.0 ParameterEditor.qml ParameterEditorDialog 1.0 ParameterEditorDialog.qml PlanToolBar 1.0 PlanToolBar.qml QGCButton 1.0 QGCButton.qml +QGCCheckListItem 1.0 QGCCheckListItem.qml QGCCheckBox 1.0 QGCCheckBox.qml QGCColoredImage 1.0 QGCColoredImage.qml QGCComboBox 1.0 QGCComboBox.qml diff --git a/src/Settings/App.SettingsGroup.json b/src/Settings/App.SettingsGroup.json index 8e60817..32d51f2 100644 --- a/src/Settings/App.SettingsGroup.json +++ b/src/Settings/App.SettingsGroup.json @@ -118,6 +118,13 @@ "defaultValue": false }, { + "name": "UseChecklist", + "shortDescription": "Use preflight checklist", + "longDescription": "If this option is enabled the preflight checklist will be used.", + "type": "bool", + "defaultValue": false +}, +{ "name": "BaseDeviceFontPointSize", "shortDescription": "Application font size", "longDescription": "The point size for the default font used.", diff --git a/src/Settings/AppSettings.cc b/src/Settings/AppSettings.cc index 56177c3..264181c 100644 --- a/src/Settings/AppSettings.cc +++ b/src/Settings/AppSettings.cc @@ -33,6 +33,7 @@ const char* AppSettings::indoorPaletteName = "StyleIs const char* AppSettings::showLargeCompassName = "ShowLargeCompass"; const char* AppSettings::savePathName = "SavePath"; const char* AppSettings::autoLoadMissionsName = "AutoLoadMissions"; +const char* AppSettings::useChecklistName = "UseChecklist"; const char* AppSettings::mapboxTokenName = "MapboxToken"; const char* AppSettings::esriTokenName = "EsriToken"; const char* AppSettings::defaultFirmwareTypeName = "DefaultFirmwareType"; @@ -75,6 +76,7 @@ AppSettings::AppSettings(QObject* parent) , _showLargeCompassFact (NULL) , _savePathFact (NULL) , _autoLoadMissionsFact (NULL) + , _useChecklistFact (NULL) , _mapboxTokenFact (NULL) , _esriTokenFact (NULL) , _defaultFirmwareTypeFact (NULL) @@ -220,6 +222,15 @@ Fact* AppSettings::audioMuted(void) return _audioMutedFact; } +Fact* AppSettings::useChecklist(void) +{ + if (!_useChecklistFact) { + _useChecklistFact = _createSettingsFact(useChecklistName); + } + + return _useChecklistFact; +} + Fact* AppSettings::appFontPointSize(void) { if (!_appFontPointSizeFact) { diff --git a/src/Settings/AppSettings.h b/src/Settings/AppSettings.h index d1a7e2f..3b7b88f 100644 --- a/src/Settings/AppSettings.h +++ b/src/Settings/AppSettings.h @@ -37,6 +37,7 @@ public: Q_PROPERTY(Fact* showLargeCompass READ showLargeCompass CONSTANT) Q_PROPERTY(Fact* savePath READ savePath CONSTANT) Q_PROPERTY(Fact* autoLoadMissions READ autoLoadMissions CONSTANT) + Q_PROPERTY(Fact* useChecklist READ useChecklist CONSTANT) Q_PROPERTY(Fact* mapboxToken READ mapboxToken CONSTANT) Q_PROPERTY(Fact* esriToken READ esriToken CONSTANT) Q_PROPERTY(Fact* defaultFirmwareType READ defaultFirmwareType CONSTANT) @@ -75,6 +76,7 @@ public: Fact* showLargeCompass (void); Fact* savePath (void); Fact* autoLoadMissions (void); + Fact* useChecklist (void); Fact* mapboxToken (void); Fact* esriToken (void); Fact* defaultFirmwareType (void); @@ -110,6 +112,7 @@ public: static const char* showLargeCompassName; static const char* savePathName; static const char* autoLoadMissionsName; + static const char* useChecklistName; static const char* mapboxTokenName; static const char* esriTokenName; static const char* defaultFirmwareTypeName; @@ -160,6 +163,7 @@ private: SettingsFact* _showLargeCompassFact; SettingsFact* _savePathFact; SettingsFact* _autoLoadMissionsFact; + SettingsFact* _useChecklistFact; SettingsFact* _mapboxTokenFact; SettingsFact* _esriTokenFact; SettingsFact* _defaultFirmwareTypeFact; diff --git a/src/ui/preferences/GeneralSettings.qml b/src/ui/preferences/GeneralSettings.qml index f302b34..70aa6cb 100644 --- a/src/ui/preferences/GeneralSettings.qml +++ b/src/ui/preferences/GeneralSettings.qml @@ -411,6 +411,16 @@ QGCView { } } } + + //----------------------------------------------------------------- + //-- Checklist Settings + FactCheckBox { + text: qsTr("Use preflight checklist") + fact: _useChecklist + visible: _useChecklist.visible + + property Fact _useChecklist: QGroundControl.settingsManager.appSettings.useChecklist + } } } From 13358501e3736921da3d0c7641e506c094a471af Mon Sep 17 00:00:00 2001 From: Philipp Oettershagen Date: Tue, 8 May 2018 13:31:40 +0200 Subject: [PATCH 2/3] Fixes and cleanup according to comments by @dongagne --- qgroundcontrol.qrc | 1 + src/FlightDisplay/CheckList.qml | 206 ++++++++++++++++++++ src/FlightDisplay/FlightDisplayView.qml | 320 +++++--------------------------- src/FlightDisplay/qmldir | 1 + src/QmlControls/DropPanel.qml | 2 +- src/QmlControls/QGCCheckListItem.qml | 60 +++--- src/Vehicle/Vehicle.h | 2 +- 7 files changed, 285 insertions(+), 307 deletions(-) create mode 100644 src/FlightDisplay/CheckList.qml diff --git a/qgroundcontrol.qrc b/qgroundcontrol.qrc index 50ba35c..7555cd3 100644 --- a/qgroundcontrol.qrc +++ b/qgroundcontrol.qrc @@ -193,6 +193,7 @@ src/FlightMap/Widgets/VibrationPageWidget.qml src/FlightMap/Widgets/VideoPageWidget.qml src/FlightDisplay/VirtualJoystick.qml + src/FlightDisplay/CheckList.qml src/MissionManager/CameraCalc.FactMetaData.json diff --git a/src/FlightDisplay/CheckList.qml b/src/FlightDisplay/CheckList.qml new file mode 100644 index 0000000..21c7733 --- /dev/null +++ b/src/FlightDisplay/CheckList.qml @@ -0,0 +1,206 @@ +import QtQuick 2.3 +import QtQml.Models 2.1 + +import QGroundControl 1.0 +import QGroundControl.FlightDisplay 1.0 +import QGroundControl.ScreenTools 1.0 +import QGroundControl.Controls 1.0 +import QGroundControl.Palette 1.0 +import QGroundControl.Vehicle 1.0 + +// This class stores the data and functions of the check list but NOT the GUI (which is handled somewhere else). +Item { + // Properties + property int unhealthySensors: _activeVehicle ? _activeVehicle.sensorsUnhealthyBits : 0 + property bool gpsLock: _activeVehicle ? _activeVehicle.gps.lock.rawValue>=3 : 0 + property var batPercentRemaining: _activeVehicle ? _activeVehicle.battery.percentRemaining.value : 0 + property bool audioMuted: QGroundControl.settingsManager.appSettings.audioMuted.rawValue + property ObjectModel checkListItems: _checkListItems + property var _activeVehicle: QGroundControl.multiVehicleManager.activeVehicle + property int _checkState: _activeVehicle ? (_activeVehicle.armed ? 1 + (buttonActuators._state + buttonMotors._state + buttonMission._state + buttonSoundOutput._state) / 4 / 4 : 0) : 0 ; // Shows progress of checks inside the checklist - unlocks next check steps in groups + + // Connections + onBatPercentRemainingChanged: buttonBattery.updateItem(); + onGpsLockChanged: buttonSensors.updateItem(); + onAudioMutedChanged: buttonSoundOutput.updateItem(); + onUnhealthySensorsChanged: updateVehicleDependentItems(); + + Connections { + target: QGroundControl.multiVehicleManager + onActiveVehicleChanged: onActiveVehicleChanged(); + } + Component.onCompleted: { + if(QGroundControl.multiVehicleManager.vehicles.count > 0) { + onActiveVehicleChanged(); + } + } + + // Functions + function updateVehicleDependentItems() { + buttonSensors.updateItem(); + buttonBattery.updateItem(); + buttonRC.updateItem(); + buttonEstimator.updateItem(); + } + function onActiveVehicleChanged() { + buttonSoundOutput.updateItem(); // Just updated here for initialization once we connect to a vehicle + updateVehicleDependentItems(); + } + function resetNrClicks() { + buttonHardware.resetNrClicks(); + buttonBattery.resetNrClicks(); + buttonRC.resetNrClicks(); + buttonActuators.resetNrClicks(); + buttonMotors.resetNrClicks(); + buttonMission.resetNrClicks(); + buttonSoundOutput.resetNrClicks(); + buttonPayload.resetNrClicks(); + buttonWeather.resetNrClicks(); + buttonFlightAreaFree.resetNrClicks(); + } + + // Check list item data + ObjectModel { + id: _checkListItems + + // Standard check list items (group 0) - Available from the start + QGCCheckListItem { + id: buttonHardware + name: "Hardware" + defaulttext: "Props mounted? Wings secured? Tail secured?" + } + QGCCheckListItem { + id: buttonBattery + name: "Battery" + pendingtext: "Healthy & charged > 40%. Battery connector firmly plugged?" + function updateItem() { + if (!_activeVehicle) { + _state = 0; + } else { + if (!(unhealthySensors & Vehicle.SysStatusSensorBattery) && batPercentRemaining>=40.0) _state = 1+3*(_nrClicked>0); + else { + if(unhealthySensors & Vehicle.SysStatusSensorBattery) failuretext="Not healthy. Check console."; + else if(batPercentRemaining<40.0) failuretext="Low (below 40%). Please recharge."; + _state = 3; + } + } + } + } + QGCCheckListItem { + id: buttonSensors + name: "Sensors" + function updateItem() { + if (!_activeVehicle) { + _state = 0; + } else { + if(!(unhealthySensors & Vehicle.SysStatusSensor3dMag) && + !(unhealthySensors & Vehicle.SysStatusSensor3dAccel) && + !(unhealthySensors & Vehicle.SysStatusSensor3dGyro) && + !(unhealthySensors & Vehicle.SysStatusSensorAbsolutePressure) && + !(unhealthySensors & Vehicle.SysStatusSensorDifferentialPressure) && + !(unhealthySensors & Vehicle.SysStatusSensorGPS)) { + if(!gpsLock) { + pendingtext="Pending. Waiting for GPS lock."; + _state=1; + } else { + _state = 4; // All OK + } + } else { + if(unhealthySensors & Vehicle.SysStatusSensor3dMag) failuretext="Failure. Magnetometer issues. Check console."; + else if(unhealthySensors & Vehicle.SysStatusSensor3dAccel) failuretext="Failure. Accelerometer issues. Check console."; + else if(unhealthySensors & Vehicle.SysStatusSensor3dGyro) failuretext="Failure. Gyroscope issues. Check console."; + else if(unhealthySensors & Vehicle.SysStatusSensorAbsolutePressure) failuretext="Failure. Barometer issues. Check console."; + else if(unhealthySensors & Vehicle.SysStatusSensorDifferentialPressure) failuretext="Failure. Airspeed sensor issues. Check console."; + else if(unhealthySensors & Vehicle.SysStatusSensorGPS) failuretext="Failure. No valid or low quality GPS signal. Check console."; + _state = 3; + } + } + } + } + QGCCheckListItem { + id: buttonRC + name: "Radio Control" + pendingtext: "Receiving signal. Perform range test & confirm." + failuretext: "No signal or invalid autopilot-RC config. Check RC and console." + function updateItem() { + if (!_activeVehicle) { + _state = 0; + } else { + if (unhealthySensors & Vehicle.SysStatusSensorRCReceiver) {_state = 3} + else {_state = 1+3*(_nrClicked>0);} + } + } + } + QGCCheckListItem { + id: buttonEstimator + name: "Global position estimate" + function updateItem() { + if (!_activeVehicle) { + _state = 0; + } else { + if (unhealthySensors & Vehicle.SysStatusSensorAHRS) {_state = 3;} + else {_state = 4;} + } + } + } + + // Check list item group 1 - Require arming + QGCLabel {text:qsTr("Please arm the vehicle here.") ; opacity: 0.2+0.8*(QGroundControl.multiVehicleManager.vehicles.count > 0) ; anchors.horizontalCenter:buttonHardware.horizontalCenter ; anchors.topMargin:40 ; anchors.bottomMargin:40;} + QGCCheckListItem { + id: buttonActuators + name: "Actuators" + group: 1 + defaulttext: "Move all control surfaces. Did they work properly?" + } + QGCCheckListItem { + id: buttonMotors + name: "Motors" + group: 1 + defaulttext: "Propellers free? Then throttle up gently. Working properly?" + } + QGCCheckListItem { + id: buttonMission + name: "Mission" + group: 1 + defaulttext: "Please confirm mission is valid (waypoints valid, no terrain collision)." + } + QGCCheckListItem { + id: buttonSoundOutput + name: "Sound output" + group: 1 + pendingtext: "QGC audio output enabled. System audio output enabled, too?" + failuretext: "Failure, QGC audio output is disabled. Please enable it under application settings->general to hear audio warnings!" + function updateItem() { + if (!_activeVehicle) { + _state = 0; + } else { + if (audioMuted) {_state = 3 ; _nrClicked=0;} + else {_state = 1+3*(_nrClicked>0);} + } + } + } + + // Check list item group 2 - Final checks before launch + QGCLabel {text:qsTr("Last preparations before launch") ; opacity : 0.2+0.8*(_checkState >= 2); anchors.horizontalCenter:buttonHardware.horizontalCenter} + QGCCheckListItem { + id: buttonPayload + name: "Payload" + group: 2 + defaulttext: "Configured and started?" + pendingtext: "Payload lid closed?" + } + QGCCheckListItem { + id: buttonWeather + name: "Wind & weather" + group: 2 + defaulttext: "OK for your platform?" + pendingtext: "Launching into the wind?" + } + QGCCheckListItem { + id: buttonFlightAreaFree + name: "Flight area" + group: 2 + defaulttext: "Launch area and path free of obstacles/people?" + } + } // Object Model +} diff --git a/src/FlightDisplay/FlightDisplayView.qml b/src/FlightDisplay/FlightDisplayView.qml index e9cdd56..4f143fe 100644 --- a/src/FlightDisplay/FlightDisplayView.qml +++ b/src/FlightDisplay/FlightDisplayView.qml @@ -17,6 +17,7 @@ import QtPositioning 5.3 import QtMultimedia 5.5 import QtQuick.Layouts 1.2 import QtQuick.Window 2.2 +import QtQml.Models 2.1 import QGroundControl 1.0 import QGroundControl.FlightDisplay 1.0 @@ -46,13 +47,13 @@ QGCView { property var _activeVehicle: QGroundControl.multiVehicleManager.activeVehicle property bool _mainIsMap: QGroundControl.videoManager.hasVideo ? QGroundControl.loadBoolGlobalSetting(_mainIsMapKey, true) : true property bool _isPipVisible: QGroundControl.videoManager.hasVideo ? QGroundControl.loadBoolGlobalSetting(_PIPVisibleKey, true) : false + property bool _useChecklist: QGroundControl.settingsManager.appSettings.useChecklist.rawValue property real _savedZoomLevel: 0 property real _margins: ScreenTools.defaultFontPixelWidth / 2 property real _pipSize: flightView.width * 0.2 property alias _guidedController: guidedActionsController property alias _altitudeSlider: altitudeSlider - readonly property var _dynamicCameras: _activeVehicle ? _activeVehicle.dynamicCameras : null readonly property bool _isCamera: _dynamicCameras ? _dynamicCameras.cameras.count > 0 : false readonly property bool isBackgroundDark: _mainIsMap ? (_flightMap ? _flightMap.isSatelliteMap : true) : true @@ -112,6 +113,10 @@ QGCView { Component.onCompleted: start(true /* flyView */) } + CheckList { + id: checklist + } + Connections { target: _missionController onResumeMissionReady: guidedActionsController.confirmAction(guidedActionsController.actionResumeMissionReady) @@ -504,8 +509,8 @@ QGCView { z: _panel.z + 4 title: qsTr("Fly") maxHeight: (_flightVideo.visible ? _flightVideo.y : parent.height) - toolStrip.y - buttonVisible: [ QGroundControl.settingsManager.appSettings.useChecklist.rawValue, _guidedController.showTakeoff || !_guidedController.showLand, _guidedController.showLand && !_guidedController.showTakeoff, true, true, true, _guidedController.smartShotsAvailable ] - buttonEnabled: [ QGroundControl.settingsManager.appSettings.useChecklist.rawValue, _guidedController.showTakeoff, _guidedController.showLand, _guidedController.showRTL, _guidedController.showPause, _anyActionAvailable, _anySmartShotAvailable ] + buttonVisible: [ _useChecklist, _guidedController.showTakeoff || !_guidedController.showLand, _guidedController.showLand && !_guidedController.showTakeoff, true, true, true, _guidedController.smartShotsAvailable ] + buttonEnabled: [ _useChecklist, _guidedController.showTakeoff, _guidedController.showLand, _guidedController.showRTL, _guidedController.showPause, _anyActionAvailable, _anySmartShotAvailable ] property bool _anyActionAvailable: _guidedController.showStartMission || _guidedController.showResumeMission || _guidedController.showChangeAlt || _guidedController.showLandAbort property bool _anySmartShotAvailable: _guidedController.showOrbit @@ -683,291 +688,58 @@ QGCView { } } + //-- Checklist GUI Component { id: checklistDropPanel Rectangle { - id: checklist - width: mainColumn.width + (ScreenTools.defaultFontPixelWidth * 4) - height: (headerColumn.height+mainColumn.height) * 1.07 - color: qgcPal.windowShade - radius: 20 - enabled: QGroundControl.multiVehicleManager.vehicles.count > 0; - - onBatPercentRemainingChanged: {if(_initialized) buttonBattery.updateItem();} - onGpsLockChanged: {buttonSensors.updateItem();} - - // Connections - Connections { - target: _activeVehicle - onUnhealthySensorsChanged: checklist.onUnhealthySensorsChanged(); - } - Connections { - target: QGroundControl.multiVehicleManager - onActiveVehicleChanged: checklist.onActiveVehicleChanged(); - onActiveVehicleAvailableChanged: {} - } - Connections { - target: QGroundControl.settingsManager.appSettings.audioMuted - onValueChanged: buttonSoundOutput.updateItem(); //TODO(philippoe): We are binding to a signal which is explicitly marked as "only for QT internal use" here. - } - Component.onCompleted: { - if(QGroundControl.multiVehicleManager.vehicles.count > 0) { - onActiveVehicleChanged(); - _initialized=true; - } - } - - function updateVehicleDependentItems() { - buttonSensors.updateItem(); - buttonBattery.updateItem(); - buttonRC.updateItem(); - buttonEstimator.updateItem(); - } - function onActiveVehicleChanged() { - buttonSoundOutput.updateItem(); // Just updated here for initialization once we connect to a vehicle - onUnhealthySensorsChanged(); // The health states could all have changed - need to update them. - } - function onUnhealthySensorsChanged() { - var unhealthySensorsStr = _activeVehicle.unhealthySensors; - - // Set to healthy per default - for(var i=0;i<32;i++) _healthFlags[i]=true; - - for(i=0;i 0; Column { - id: headerColumn - x: 2*ScreenTools.defaultFontPixelWidth - y: 2*ScreenTools.defaultFontPixelWidth - width: 320 - spacing: 8 + id: mainColumn + x: 1.5*ScreenTools.defaultFontPixelWidth + y: 0.4*ScreenTools.defaultFontPixelWidth + width: 40*ScreenTools.defaultFontPixelWidth + spacing: 0.8*ScreenTools.defaultFontPixelWidth // Header/title of checklist - QGCLabel {anchors.horizontalCenter: parent.horizontalCenter ; font.pointSize: ScreenTools.mediumFontPointSize ; text: _activeVehicle ? qsTr("Pre-flight checklist")+" (MAV ID:"+_activeVehicle.id+")" : qsTr("Pre-flight checklist (awaiting vehicle...)");} - Rectangle {anchors.left:parent.left ; anchors.right:parent.right ; height:1 ; color:qgcPal.text} - } + Item { + width: parent.width + height: 1.75*ScreenTools.defaultFontPixelHeight - Column { - id: mainColumn - x: 2*ScreenTools.defaultFontPixelWidth - anchors.top:headerColumn.bottom - anchors.topMargin:ScreenTools.defaultFontPixelWidth - width: 320 - spacing: 6 - enabled : QGroundControl.multiVehicleManager.vehicles.count > 0; - opacity : 0.2+0.8*(QGroundControl.multiVehicleManager.vehicles.count > 0); - - // Checklist items: Standard - QGCCheckListItem { - id: buttonHardware - name: "Hardware" - defaulttext: "Props mounted? Wings secured? Tail secured?" - } + QGCLabel { + text: _activeVehicle ? qsTr("Pre-flight checklist")+" (MAV ID:"+_activeVehicle.id+")" : qsTr("Pre-flight checklist (no vehicle)") + anchors.left: parent.left + anchors.verticalCenter: parent.verticalCenter + font.pointSize: ScreenTools.mediumFontPointSize + } + QGCButton { + width: 1.2*ScreenTools.defaultFontPixelHeight + height: 1.2*ScreenTools.defaultFontPixelHeight + anchors.right: parent.right + anchors.verticalCenter: parent.verticalCenter + opacity : 0.2+0.8*(QGroundControl.multiVehicleManager.vehicles.count > 0) + tooltip: "Reset the checklist (e.g. after a vehicle reboot)" - QGCCheckListItem { - id: buttonBattery - name: "Battery" - pendingtext: "Healthy & charged > 40%. Battery connector firmly plugged?" - function updateItem() { - if (!_activeVehicle) { - _state = 0; - } else { - if (checklist._healthFlags[25] && batPercentRemaining>=40.0) _state = 1+3*(_nrClicked>0); - else { - if(!checklist._healthFlags[25]) buttonBattery.failuretext="Not healthy. Check console."; - else if(batPercentRemaining<40.0) buttonBattery.failuretext="Low (below 40%). Please recharge."; - buttonBattery._state = 3; - } - } - } - } + onClicked: checklist.resetNrClicks() - QGCCheckListItem { - id: buttonSensors - name: "Sensors" - function updateItem() { - if (!_activeVehicle) { - _state = 0; - } else { - if(checklist._healthFlags[0] && - checklist._healthFlags[1] && - checklist._healthFlags[2] && - checklist._healthFlags[3] && - checklist._healthFlags[4] && - checklist._healthFlags[5]) { - if(!gpsLock) { - buttonSensors.pendingtext="Pending. Waiting for GPS lock."; - buttonSensors._state=1; - } else { - _state = 4; // All OK - } - } else { - if(!checklist._healthFlags[0]) failuretext="Failure. Gyroscope issues. Check console."; - else if(!checklist._healthFlags[1]) failuretext="Failure. Accelerometer issues. Check console."; - else if(!checklist._healthFlags[2]) failuretext="Failure. Magnetometer issues. Check console."; - else if(!checklist._healthFlags[3]) failuretext="Failure. Barometer issues. Check console."; - else if(!checklist._healthFlags[4]) failuretext="Failure. Airspeed sensor issues. Check console."; - else if(!checklist._healthFlags[5]) failuretext="Failure. No valid or low quality GPS signal. Check console."; - _state = 3; - } - } - } - } - QGCCheckListItem { - id: buttonRC - name: "Radio Control" - pendingtext: "Receiving signal. Perform range test & confirm." - failuretext: "No signal or invalid autopilot-RC config. Check RC and console." - function updateItem() { - if (!_activeVehicle) { - _state = 0; - } else { - if (_healthFlags[16]) {_state = 1+3*(_nrClicked>0);} - else {_state = 3;} - } - } - } - - QGCCheckListItem { - id: buttonEstimator - name: "Global position estimate" - function updateItem() { - if (!_activeVehicle) { - _state = 0; - } else { - if (_healthFlags[21]) {_state = 4;} - else {_state = 3;} - } + Image { source:"/qmlimages/MapSyncBlack.svg" ; anchors.fill: parent } } - } - - // Arming header - //Rectangle {anchors.left:parent.left ; anchors.right:parent.right ; height:1 ; color:qgcPal.text} - QGCLabel {anchors.horizontalCenter:parent.horizontalCenter ; text:qsTr("Please arm the vehicle here.")} - //Rectangle {anchors.left:parent.left ; anchors.right:parent.right ; height:1 ; color:qgcPal.text} - - QGCCheckListItem { - id: buttonActuators - name: "Actuators" - group: 1 - defaulttext: "Move all control surfaces. Did they work properly?" - } - - QGCCheckListItem { - id: buttonMotors - name: "Motors" - group: 1 - defaulttext: "Propellers free? Then throttle up gently. Working properly?" - } - - QGCCheckListItem { - id: buttonMission - name: "Mission" - group: 1 - defaulttext: "Please confirm mission is valid (waypoints valid, no terrain collision)." - } - - QGCCheckListItem { - id: buttonSoundOutput - name: "Sound output" - group: 1 - pendingtext: "QGC audio output enabled. System audio output enabled, too?" - failuretext: "Failure, QGC audio output is disabled. Please enable it under application settings->general to hear audio warnings!" - function updateItem() { - if (!_activeVehicle) { - _state = 0; - } else { - if (QGroundControl.settingsManager.appSettings.audioMuted.rawValue) {_state = 3;_nrClicked=0;} - else {_state = 1+3*(_nrClicked>0);} - } - } - } - - // Directly before launch header - //Rectangle {anchors.left:parent.left ; anchors.right:parent.right ; height:1 ; color:qgcPal.text} - QGCLabel {anchors.horizontalCenter:parent.horizontalCenter ; text:qsTr("Last preparations before launch") ; opacity : 0.2+0.8*(_checkState >= 2);} - //Rectangle {anchors.left:parent.left ; anchors.right:parent.right ; height:1 ; color:qgcPal.text} - - QGCCheckListItem { - id: buttonPayload - name: "Payload" - group: 2 - defaulttext: "Configured and started?" - pendingtext: "Payload lid closed?" - } - - QGCCheckListItem { - id: buttonWeather - name: "Wind & weather" - group: 2 - defaulttext: "OK for your platform?" - pendingtext: "Launching into the wind?" - } - - QGCCheckListItem { - id: buttonFlightAreaFree - name: "Flight area" - group: 2 - defaulttext: "Launch area and path free of obstacles/people?" - } + } - } // Column + Rectangle {width:parent.width ; height:1 ; color:qgcPal.text} - property bool _initialized:false - property var _healthFlags: [] - property int _checkState: _activeVehicle ? (_activeVehicle.armed ? 1 + (buttonActuators._state + buttonMotors._state + buttonMission._state + buttonSoundOutput._state) / 4 / 4 : 0) : 0 ; // Shows progress of checks inside the checklist - unlocks next check steps in groups - property bool gpsLock: _activeVehicle ? _activeVehicle.gps.lock.rawValue>=3 : 0 - property var batPercentRemaining: _activeVehicle ? _activeVehicle.battery.getFact("percentRemaining").value : 0 - - // TODO: Having access to MAVLINK enums (or at least QML consts) would be much cleaner than the code below - property int subsystem_type_gyro : 1 - property int subsystem_type_acc : 2 - property int subsystem_type_mag : 4 - property int subsystem_type_abspressure : 8 - property int subsystem_type_diffpressure : 16 - property int subsystem_type_gps : 32 - property int subsystem_type_positioncontrol : 16384 - property int subsystem_type_motorcontrol : 32768 - property int subsystem_type_rcreceiver : 65536 - property int subsystem_type_ahrs : 2097152 - property int subsystem_type_terrain : 4194304 - property int subsystem_type_reversemotor : 8388608 - property int subsystem_type_logging : 16777216 - property int subsystem_type_sensorbattery : 33554432 - property int subsystem_type_rangefinder : 67108864 + // All check list items + Repeater { + model: checklist.checkListItems + } + } // Column } //Rectangle } //Component } //QGC View diff --git a/src/FlightDisplay/qmldir b/src/FlightDisplay/qmldir index f29069e..bc327b9 100644 --- a/src/FlightDisplay/qmldir +++ b/src/FlightDisplay/qmldir @@ -9,4 +9,5 @@ GuidedActionsController 1.0 GuidedActionsController.qml GuidedActionList 1.0 GuidedActionList.qml GuidedAltitudeSlider 1.0 GuidedAltitudeSlider.qml MultiVehicleList 1.0 MultiVehicleList.qml +CheckList 1.0 CheckList.qml diff --git a/src/QmlControls/DropPanel.qml b/src/QmlControls/DropPanel.qml index 1de3e1c..91fe3dc 100644 --- a/src/QmlControls/DropPanel.qml +++ b/src/QmlControls/DropPanel.qml @@ -64,7 +64,7 @@ Item { } if (visible) { visible = false - //_dropDownComponent = undefined //TODO (philippoe) such that drop down component state is not deleted - check with don gagne whether this is necessary + _dropDownComponent = undefined toolStrip.uncheckAll() } } diff --git a/src/QmlControls/QGCCheckListItem.qml b/src/QmlControls/QGCCheckListItem.qml index cd1e82c..0d0c113 100644 --- a/src/QmlControls/QGCCheckListItem.qml +++ b/src/QmlControls/QGCCheckListItem.qml @@ -7,20 +7,19 @@ import QGroundControl.Palette 1.0 import QGroundControl.ScreenTools 1.0 QGCButton { - property string name: "" - property int _state: 0 - property var _color: qgcPal.button;//qgcPal.windowShade;//qgcPal.windowShadeDark;//Qt.rgba(0.5,0.5,0.5,1) //qgcPal.window;// - property int _nrClicked: 0 - property int group: 0 - property string defaulttext: "Not checked yet" - property string pendingtext: "" - property string failuretext: "Failure. Check console." - property string _text: qsTr(name)+ ": " + qsTr(defaulttext) + property string name: "" + property int group: 0 + property string defaulttext: "Not checked yet" + property string pendingtext: "" + property string failuretext: "Failure. Check console." + property int _state: 0 + property var _color: qgcPal.button + property int _nrClicked: 0 + property string _text: qsTr(name)+ ": " + qsTr(defaulttext) - enabled : (_activeVehicle==null || _activeVehicle.connectionLost) ? false : _checkState>=group - opacity : (_activeVehicle==null || _activeVehicle.connectionLost) ? 0.4 : 0.2+0.8*(_checkState >= group); - - width: parent.width + enabled : (_activeVehicle==null || _activeVehicle.connectionLost) ? false : checklist._checkState>=group + opacity : (_activeVehicle==null || _activeVehicle.connectionLost) ? 0.4 : 0.2+0.8*(checklist._checkState >= group); + width: 40*ScreenTools.defaultFontPixelWidth style: ButtonStyle { background: Rectangle {color:_color; border.color: qgcPal.button; radius:3} label: Label { @@ -31,46 +30,45 @@ QGCButton { } } + // Connections + onPendingtextChanged: { if(_state==1) {getTextFromState(); getColorFromState();} } + onFailuretextChanged: { if(_state==3) {getTextFromState(); getColorFromState();} } + on_StateChanged: { getTextFromState(); getColorFromState(); } onClicked: { if(_state<2) _nrClicked=_nrClicked+1; //Only allow click-counter to increase when not failed yet updateItem(); } - onPendingtextChanged: { if(_state==1) {getTextFromState(); getColorFromState();} } - onFailuretextChanged: { if(_state==3) {getTextFromState(); getColorFromState();} } - on_StateChanged: { getTextFromState(); getColorFromState(); } -// onEnabledChanged: { //Dont do this for now, because if we only accidentially lose connection, we don't want to delete the checklist state. Instead, we'd need to detect a re-connect, maybe based on the timesincesystemstart (i.e. when it decreases)? -// if(enabled==false && group > 0) { -// // Reset all check list items of group > 0 if it is disabled again (which e.g. happens after a vehicle reboot or disarm). -// _nrClicked = 0; -// _state = 0; -// } -// } + //Functions function updateItem() { // This is the default updateFunction. It assumes the item is a MANUAL check list item, i.e. one that // only requires user clicks (one click if pendingtext="", two clicks otherwise) for completion. - //if(_nrClicked>0) _state = 4; - if(_nrClicked===1) { + if(_nrClicked===0) _state = 0; + else if(_nrClicked===1) { if(pendingtext.length === 0) _state = 4; else _state = 1; - } else if(_nrClicked>1) _state = 4; + } else _state = 4; getTextFromState(); getColorFromState(); } function getTextFromState() { - if(_state === 0) {_text= qsTr(name) + ": " + qsTr(defaulttext)} // Not checked yet - else if(_state === 1) {_text= ""+qsTr(name)+"" +": " + qsTr(pendingtext)} // Pending - else if(_state === 2) {_text= ""+qsTr(name)+"" +": " + qsTr("Minor problem")} // Small problem or need further user action to resolve - else if(_state === 3) {_text= ""+qsTr(name)+"" +": " + qsTr(failuretext)} // Big problem + if(_state === 0) {_text= qsTr(name) + ": " + qsTr(defaulttext)} // Not checked yet + else if(_state === 1) {_text= ""+qsTr(name)+"" +": " + qsTr(pendingtext)} // Pending + else if(_state === 2) {_text= ""+qsTr(name)+"" +": " + qsTr("Minor problem")} // Small problem or need further user action to resolve + else if(_state === 3) {_text= ""+qsTr(name)+"" +": " + qsTr(failuretext)} // Big problem else {_text= ""+qsTr(name)+"" +": " + qsTr("OK")} // All OK } function getColorFromState() { - if(_state === 0) {_color=qgcPal.button} // Not checked yet + if(_state === 0) {_color=qgcPal.button} // Not checked yet else if(_state === 1) {_color=Qt.rgba(0.9,0.47,0.2,1)} // Pending else if(_state === 2) {_color=Qt.rgba(1.0,0.6,0.2,1)} // Small problem or need further user action to resolve else if(_state === 3) {_color=Qt.rgba(0.92,0.22,0.22,1)} // Big problem else {_color=Qt.rgba(0.27,0.67,0.42,1)} // All OK } + function resetNrClicks() { + _nrClicked=0; + updateItem(); + } } diff --git a/src/Vehicle/Vehicle.h b/src/Vehicle/Vehicle.h index 6b22bc5..1323f6f 100644 --- a/src/Vehicle/Vehicle.h +++ b/src/Vehicle/Vehicle.h @@ -380,7 +380,7 @@ public: SysStatusSensor3dGyro = MAV_SYS_STATUS_SENSOR_3D_GYRO, SysStatusSensor3dAccel = MAV_SYS_STATUS_SENSOR_3D_ACCEL, SysStatusSensor3dMag = MAV_SYS_STATUS_SENSOR_3D_MAG, - SysStatusSensorAsolutePressure = MAV_SYS_STATUS_SENSOR_ABSOLUTE_PRESSURE, + SysStatusSensorAbsolutePressure = MAV_SYS_STATUS_SENSOR_ABSOLUTE_PRESSURE, SysStatusSensorDifferentialPressure = MAV_SYS_STATUS_SENSOR_DIFFERENTIAL_PRESSURE, SysStatusSensorGPS = MAV_SYS_STATUS_SENSOR_GPS, SysStatusSensorOpticalFlow = MAV_SYS_STATUS_SENSOR_OPTICAL_FLOW, From 193e1a4abc92b32e94030d79028efa853e014dbd Mon Sep 17 00:00:00 2001 From: Philipp Oettershagen Date: Sat, 12 May 2018 14:11:48 +0200 Subject: [PATCH 3/3] Fixes round 2 based on comments by @dongagne --- src/FlightDisplay/FlightDisplayView.qml | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/src/FlightDisplay/FlightDisplayView.qml b/src/FlightDisplay/FlightDisplayView.qml index 4f143fe..7cd41be 100644 --- a/src/FlightDisplay/FlightDisplayView.qml +++ b/src/FlightDisplay/FlightDisplayView.qml @@ -696,17 +696,19 @@ QGCView { id: checklistRect visible: true width: mainColumn.width + 3*ScreenTools.defaultFontPixelWidth - height: mainColumn.height * 1.04 + height: mainColumn.height + ScreenTools.defaultFontPixelHeight color: qgcPal.windowShade radius: 3 enabled: QGroundControl.multiVehicleManager.vehicles.count > 0; Column { - id: mainColumn - x: 1.5*ScreenTools.defaultFontPixelWidth - y: 0.4*ScreenTools.defaultFontPixelWidth - width: 40*ScreenTools.defaultFontPixelWidth - spacing: 0.8*ScreenTools.defaultFontPixelWidth + id: mainColumn + width: 40*ScreenTools.defaultFontPixelWidth + spacing: 0.8*ScreenTools.defaultFontPixelWidth + anchors.left: parent.left + anchors.top: parent.top + anchors.topMargin: 0.6*ScreenTools.defaultFontPixelWidth + anchors.leftMargin: 1.5*ScreenTools.defaultFontPixelWidth // Header/title of checklist Item {