You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
510 lines
22 KiB
510 lines
22 KiB
/**************************************************************************** |
|
* |
|
* (c) 2009-2016 QGROUNDCONTROL PROJECT <http://www.qgroundcontrol.org> |
|
* |
|
* QGroundControl is licensed according to the terms in the file |
|
* COPYING.md in the root of the source code directory. |
|
* |
|
****************************************************************************/ |
|
|
|
|
|
import QtQuick 2.3 |
|
import QtQuick.Controls 1.2 |
|
import QtQuick.Controls.Styles 1.4 |
|
import QtQuick.Dialogs 1.2 |
|
import QtLocation 5.3 |
|
import QtPositioning 5.3 |
|
import QtMultimedia 5.5 |
|
import QtQuick.Layouts 1.2 |
|
|
|
import QGroundControl 1.0 |
|
import QGroundControl.FlightDisplay 1.0 |
|
import QGroundControl.FlightMap 1.0 |
|
import QGroundControl.ScreenTools 1.0 |
|
import QGroundControl.Controls 1.0 |
|
import QGroundControl.Palette 1.0 |
|
import QGroundControl.Vehicle 1.0 |
|
import QGroundControl.Controllers 1.0 |
|
import QGroundControl.FactSystem 1.0 |
|
|
|
/// Flight Display View |
|
QGCView { |
|
id: root |
|
viewPanel: _panel |
|
|
|
QGCPalette { id: qgcPal; colorGroupEnabled: enabled } |
|
|
|
property bool activeVehicleJoystickEnabled: _activeVehicle ? _activeVehicle.joystickEnabled : false |
|
|
|
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 real _savedZoomLevel: 0 |
|
property real _margins: ScreenTools.defaultFontPixelWidth / 2 |
|
property real _pipSize: mainWindow.width * 0.2 |
|
property alias _guidedController: guidedActionsController |
|
property alias _altitudeSlider: altitudeSlider |
|
|
|
|
|
readonly property bool isBackgroundDark: _mainIsMap ? (_flightMap ? _flightMap.isSatelliteMap : true) : true |
|
readonly property real _defaultRoll: 0 |
|
readonly property real _defaultPitch: 0 |
|
readonly property real _defaultHeading: 0 |
|
readonly property real _defaultAltitudeAMSL: 0 |
|
readonly property real _defaultGroundSpeed: 0 |
|
readonly property real _defaultAirSpeed: 0 |
|
readonly property string _mapName: "FlightDisplayView" |
|
readonly property string _showMapBackgroundKey: "/showMapBackground" |
|
readonly property string _mainIsMapKey: "MainFlyWindowIsMap" |
|
readonly property string _PIPVisibleKey: "IsPIPVisible" |
|
|
|
function setStates() { |
|
QGroundControl.saveBoolGlobalSetting(_mainIsMapKey, _mainIsMap) |
|
if(_mainIsMap) { |
|
//-- Adjust Margins |
|
_flightMapContainer.state = "fullMode" |
|
_flightVideo.state = "pipMode" |
|
//-- Save/Restore Map Zoom Level |
|
if(_savedZoomLevel != 0) |
|
_flightMap.zoomLevel = _savedZoomLevel |
|
else |
|
_savedZoomLevel = _flightMap.zoomLevel |
|
} else { |
|
//-- Adjust Margins |
|
_flightMapContainer.state = "pipMode" |
|
_flightVideo.state = "fullMode" |
|
//-- Set Map Zoom Level |
|
_savedZoomLevel = _flightMap.zoomLevel |
|
_flightMap.zoomLevel = _savedZoomLevel - 3 |
|
} |
|
} |
|
|
|
function setPipVisibility(state) { |
|
_isPipVisible = state; |
|
QGroundControl.saveBoolGlobalSetting(_PIPVisibleKey, state) |
|
} |
|
|
|
function px4JoystickCheck() { |
|
if ( _activeVehicle && !_activeVehicle.supportsManualControl && (QGroundControl.settingsManager.appSettings.virtualJoystick.value || _activeVehicle.joystickEnabled)) { |
|
px4JoystickSupport.open() |
|
} |
|
} |
|
|
|
MissionController { |
|
id: flyMissionController |
|
Component.onCompleted: start(false /* editMode */) |
|
onResumeMissionReady: guidedActionsController.confirmAction(guidedActionsController.actionResumeMissionReady) |
|
} |
|
|
|
MessageDialog { |
|
id: px4JoystickSupport |
|
text: qsTr("Joystick support requires MAVLink MANUAL_CONTROL support. ") + |
|
qsTr("The firmware you are running does not normally support this. ") + |
|
qsTr("It will only work if you have modified the firmware to add MANUAL_CONTROL support.") |
|
} |
|
|
|
Connections { |
|
target: QGroundControl.multiVehicleManager |
|
onActiveVehicleChanged: px4JoystickCheck() |
|
} |
|
|
|
Connections { |
|
target: QGroundControl.settingsManager.appSettings.virtualJoystick |
|
onValueChanged: px4JoystickCheck() |
|
} |
|
|
|
onActiveVehicleJoystickEnabledChanged: px4JoystickCheck() |
|
|
|
Component.onCompleted: { |
|
setStates() |
|
px4JoystickCheck() |
|
if(QGroundControl.corePlugin.options.flyViewOverlay.toString().length) { |
|
flyViewOverlay.source = QGroundControl.corePlugin.options.flyViewOverlay |
|
} |
|
} |
|
|
|
QGCMapPalette { id: mapPal; lightColors: _mainIsMap ? _flightMap.isSatelliteMap : true } |
|
|
|
QGCViewPanel { |
|
id: _panel |
|
anchors.fill: parent |
|
|
|
//-- Map View |
|
// For whatever reason, if FlightDisplayViewMap is the _panel item, changing |
|
// width/height has no effect. |
|
Item { |
|
id: _flightMapContainer |
|
z: _mainIsMap ? _panel.z + 1 : _panel.z + 2 |
|
anchors.left: _panel.left |
|
anchors.bottom: _panel.bottom |
|
visible: _mainIsMap || _isPipVisible |
|
width: _mainIsMap ? _panel.width : _pipSize |
|
height: _mainIsMap ? _panel.height : _pipSize * (9/16) |
|
states: [ |
|
State { |
|
name: "pipMode" |
|
PropertyChanges { |
|
target: _flightMapContainer |
|
anchors.margins: ScreenTools.defaultFontPixelHeight |
|
} |
|
}, |
|
State { |
|
name: "fullMode" |
|
PropertyChanges { |
|
target: _flightMapContainer |
|
anchors.margins: 0 |
|
} |
|
} |
|
] |
|
FlightDisplayViewMap { |
|
id: _flightMap |
|
anchors.fill: parent |
|
missionController: flyMissionController |
|
guidedActionsController: _guidedController |
|
flightWidgets: flightDisplayViewWidgets |
|
rightPanelWidth: ScreenTools.defaultFontPixelHeight * 9 |
|
qgcView: root |
|
scaleState: (_mainIsMap && flyViewOverlay.item) ? (flyViewOverlay.item.scaleState ? flyViewOverlay.item.scaleState : "bottomMode") : "bottomMode" |
|
} |
|
} |
|
|
|
//-- Video View |
|
Item { |
|
id: _flightVideo |
|
z: _mainIsMap ? _panel.z + 2 : _panel.z + 1 |
|
width: !_mainIsMap ? _panel.width : _pipSize |
|
height: !_mainIsMap ? _panel.height : _pipSize * (9/16) |
|
anchors.left: _panel.left |
|
anchors.bottom: _panel.bottom |
|
visible: QGroundControl.videoManager.hasVideo && (!_mainIsMap || _isPipVisible) |
|
states: [ |
|
State { |
|
name: "pipMode" |
|
PropertyChanges { |
|
target: _flightVideo |
|
anchors.margins: ScreenTools.defaultFontPixelHeight |
|
} |
|
}, |
|
State { |
|
name: "fullMode" |
|
PropertyChanges { |
|
target: _flightVideo |
|
anchors.margins: 0 |
|
} |
|
} |
|
] |
|
//-- Video Streaming |
|
FlightDisplayViewVideo { |
|
anchors.fill: parent |
|
visible: QGroundControl.videoManager.isGStreamer |
|
} |
|
//-- UVC Video (USB Camera or Video Device) |
|
Loader { |
|
id: cameraLoader |
|
anchors.fill: parent |
|
visible: !QGroundControl.videoManager.isGStreamer |
|
source: QGroundControl.videoManager.uvcEnabled ? "qrc:/qml/FlightDisplayViewUVC.qml" : "qrc:/qml/FlightDisplayViewDummy.qml" |
|
} |
|
} |
|
|
|
QGCPipable { |
|
id: _flightVideoPipControl |
|
z: _flightVideo.z + 3 |
|
width: _pipSize |
|
height: _pipSize * (9/16) |
|
anchors.left: _panel.left |
|
anchors.bottom: _panel.bottom |
|
anchors.margins: ScreenTools.defaultFontPixelHeight |
|
visible: QGroundControl.videoManager.hasVideo |
|
isHidden: !_isPipVisible |
|
isDark: isBackgroundDark |
|
onActivated: { |
|
_mainIsMap = !_mainIsMap |
|
setStates() |
|
} |
|
onHideIt: { |
|
setPipVisibility(!state) |
|
} |
|
} |
|
|
|
Row { |
|
id: singleMultiSelector |
|
anchors.topMargin: ScreenTools.toolbarHeight + _margins |
|
anchors.rightMargin: _margins |
|
anchors.right: parent.right |
|
anchors.top: parent.top |
|
spacing: ScreenTools.defaultFontPixelWidth |
|
z: _panel.z + 4 |
|
visible: QGroundControl.multiVehicleManager.vehicles.count > 1 |
|
|
|
ExclusiveGroup { id: multiVehicleSelectorGroup } |
|
|
|
QGCRadioButton { |
|
id: singleVehicleView |
|
exclusiveGroup: multiVehicleSelectorGroup |
|
text: qsTr("Single") |
|
checked: true |
|
color: mapPal.text |
|
} |
|
|
|
QGCRadioButton { |
|
exclusiveGroup: multiVehicleSelectorGroup |
|
text: qsTr("Multi-Vehicle (WIP)") |
|
color: mapPal.text |
|
} |
|
} |
|
|
|
FlightDisplayViewWidgets { |
|
id: flightDisplayViewWidgets |
|
z: _panel.z + 4 |
|
height: ScreenTools.availableHeight |
|
anchors.left: parent.left |
|
anchors.right: altitudeSlider.visible ? altitudeSlider.left : parent.right |
|
anchors.bottom: parent.bottom |
|
qgcView: root |
|
useLightColors: isBackgroundDark |
|
missionController: _flightMap.missionController |
|
visible: singleVehicleView.checked |
|
} |
|
|
|
//------------------------------------------------------------------------- |
|
//-- Loader helper for plugins to overlay elements over the fly view |
|
Loader { |
|
id: flyViewOverlay |
|
z: flightDisplayViewWidgets.z + 1 |
|
height: ScreenTools.availableHeight |
|
anchors.left: parent.left |
|
anchors.right: altitudeSlider.visible ? altitudeSlider.left : parent.right |
|
anchors.bottom: parent.bottom |
|
} |
|
|
|
// Button to start/stop video recording |
|
Item { |
|
z: _flightVideoPipControl.z + 1 |
|
anchors.margins: ScreenTools.defaultFontPixelHeight / 2 |
|
anchors.bottom: _flightVideo.bottom |
|
anchors.right: _flightVideo.right |
|
height: ScreenTools.defaultFontPixelHeight * 2 |
|
width: height |
|
visible: QGroundControl.videoManager.videoRunning && QGroundControl.videoManager.recordingEnabled |
|
opacity: 0.75 |
|
|
|
Rectangle { |
|
anchors.top: parent.top |
|
anchors.bottom: parent.bottom |
|
width: height |
|
radius: QGroundControl.videoManager && QGroundControl.videoManager.videoReceiver && QGroundControl.videoManager.videoReceiver.recording ? 0 : height |
|
color: "red" |
|
} |
|
|
|
QGCColoredImage { |
|
anchors.top: parent.top |
|
anchors.bottom: parent.bottom |
|
anchors.horizontalCenter: parent.horizontalCenter |
|
width: height * 0.625 |
|
sourceSize.width: width |
|
source: "/qmlimages/CameraIcon.svg" |
|
fillMode: Image.PreserveAspectFit |
|
color: "white" |
|
} |
|
|
|
MouseArea { |
|
anchors.fill: parent |
|
onClicked: QGroundControl.videoManager.videoReceiver && QGroundControl.videoManager.videoReceiver.recording ? QGroundControl.videoManager.videoReceiver.stopRecording() : QGroundControl.videoManager.videoReceiver.startRecording() |
|
} |
|
} |
|
|
|
MultiVehicleList { |
|
anchors.margins: _margins |
|
anchors.top: singleMultiSelector.bottom |
|
anchors.right: parent.right |
|
anchors.bottom: parent.bottom |
|
width: ScreenTools.defaultFontPixelWidth * 30 |
|
visible: !singleVehicleView.checked |
|
z: _panel.z + 4 |
|
} |
|
|
|
|
|
//-- Virtual Joystick |
|
Loader { |
|
id: virtualJoystickMultiTouch |
|
z: _panel.z + 5 |
|
width: parent.width - (_flightVideoPipControl.width / 2) |
|
height: Math.min(ScreenTools.availableHeight * 0.25, ScreenTools.defaultFontPixelWidth * 16) |
|
visible: _virtualJoystick ? _virtualJoystick.value : false |
|
anchors.bottom: _flightVideoPipControl.top |
|
anchors.bottomMargin: ScreenTools.defaultFontPixelHeight * 2 |
|
anchors.horizontalCenter: flightDisplayViewWidgets.horizontalCenter |
|
source: "qrc:/qml/VirtualJoystick.qml" |
|
active: _virtualJoystick ? _virtualJoystick.value : false |
|
|
|
property bool useLightColors: isBackgroundDark |
|
|
|
property Fact _virtualJoystick: QGroundControl.settingsManager.appSettings.virtualJoystick |
|
} |
|
|
|
ToolStrip { |
|
visible: _activeVehicle ? _activeVehicle.guidedModeSupported : true |
|
id: toolStrip |
|
anchors.leftMargin: ScreenTools.defaultFontPixelWidth |
|
anchors.left: _panel.left |
|
anchors.topMargin: ScreenTools.toolbarHeight + _margins |
|
anchors.top: _panel.top |
|
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 ] |
|
|
|
property bool _anyActionAvailable: _guidedController.showEmergenyStop || _guidedController.showStartMission || _guidedController.showResumeMission || _guidedController.showChangeAlt || _guidedController.showLandAbort |
|
property bool _anySmartShotAvailable: _guidedController.showOrbit |
|
property var _actionModel: [ |
|
{ |
|
title: _guidedController.startMissionTitle, |
|
text: _guidedController.startMissionMessage, |
|
action: _guidedController.actionStartMission, |
|
visible: _guidedController.showStartMission |
|
}, |
|
{ |
|
title: _guidedController.resumeMissionTitle, |
|
text: _guidedController.resumeMissionMessage, |
|
action: _guidedController.actionResumeMission, |
|
visible: _guidedController.showResumeMission |
|
}, |
|
{ |
|
title: _guidedController.changeAltTitle, |
|
text: _guidedController.changeAltMessage, |
|
action: _guidedController.actionChangeAlt, |
|
visible: _guidedController.showChangeAlt |
|
}, |
|
{ |
|
title: _guidedController.landAbortTitle, |
|
text: _guidedController.landAbortMessage, |
|
action: _guidedController.actionLandAbort, |
|
visible: _guidedController.showLandAbort |
|
} |
|
] |
|
property var _smartShotModel: [ |
|
{ |
|
title: _guidedController.orbitTitle, |
|
text: _guidedController.orbitMessage, |
|
action: _guidedController.actionOrbit, |
|
visible: _guidedController.showOrbit |
|
} |
|
] |
|
|
|
model: [ |
|
{ |
|
name: _guidedController.takeoffTitle, |
|
iconSource: "/res/takeoff.svg", |
|
action: _guidedController.actionTakeoff |
|
}, |
|
{ |
|
name: _guidedController.landTitle, |
|
iconSource: "/res/land.svg", |
|
action: _guidedController.actionLand |
|
}, |
|
{ |
|
name: _guidedController.rtlTitle, |
|
iconSource: "/res/rtl.svg", |
|
action: _guidedController.actionRTL |
|
}, |
|
{ |
|
name: _guidedController.pauseTitle, |
|
iconSource: "/res/pause-mission.svg", |
|
action: _guidedController.actionPause |
|
}, |
|
{ |
|
name: qsTr("Action"), |
|
iconSource: "/res/action.svg", |
|
action: -1 |
|
}, |
|
/* |
|
No firmware support any smart shots yet |
|
{ |
|
name: qsTr("Smart"), |
|
iconSource: "/qmlimages/MapCenter.svg", |
|
action: -1 |
|
}, |
|
*/ |
|
] |
|
|
|
onClicked: { |
|
guidedActionConfirm.visible = false |
|
guidedActionList.visible = false |
|
altitudeSlider.visible = false |
|
var action = model[index].action |
|
if (action === -1) { |
|
if (index == 4) { |
|
guidedActionList.model = _actionModel |
|
guidedActionList.visible = true |
|
} else if (index == 5) { |
|
guidedActionList.model = _smartShotModel |
|
guidedActionList.visible = true |
|
} |
|
} else { |
|
_guidedController.confirmAction(action) |
|
} |
|
} |
|
} |
|
|
|
GuidedActionsController { |
|
id: guidedActionsController |
|
missionController: flyMissionController |
|
z: _flightVideoPipControl.z + 1 |
|
|
|
onShowStartMissionChanged: { |
|
if (showStartMission) { |
|
confirmAction(actionStartMission) |
|
} |
|
} |
|
|
|
onShowResumeMissionChanged: { |
|
if (showResumeMission) { |
|
confirmAction(actionResumeMission) |
|
} |
|
} |
|
|
|
onShowConfirmAction: { |
|
guidedActionConfirm.title = title |
|
guidedActionConfirm.message = message |
|
guidedActionConfirm.action = action |
|
guidedActionConfirm.actionData = actionData |
|
guidedActionConfirm.visible = true |
|
} |
|
} |
|
|
|
GuidedActionConfirm { |
|
id: guidedActionConfirm |
|
anchors.margins: _margins |
|
anchors.bottom: parent.bottom |
|
anchors.horizontalCenter: parent.horizontalCenter |
|
guidedController: _guidedController |
|
altitudeSlider: _altitudeSlider |
|
} |
|
|
|
GuidedActionList { |
|
id: guidedActionList |
|
anchors.margins: _margins |
|
anchors.bottom: parent.bottom |
|
anchors.horizontalCenter: parent.horizontalCenter |
|
guidedController: _guidedController |
|
altitudeSlider: _altitudeSlider |
|
} |
|
|
|
//-- Altitude slider |
|
GuidedAltitudeSlider { |
|
id: altitudeSlider |
|
anchors.margins: _margins |
|
anchors.right: parent.right |
|
anchors.topMargin: ScreenTools.toolbarHeight + _margins |
|
anchors.top: parent.top |
|
anchors.bottom: parent.bottom |
|
z: _guidedController.z |
|
radius: ScreenTools.defaultFontPixelWidth / 2 |
|
width: ScreenTools.defaultFontPixelWidth * 10 |
|
color: qgcPal.window |
|
visible: false |
|
} |
|
} |
|
}
|
|
|