地面站终端 App
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.

597 lines
21 KiB

/*=====================================================================
QGroundControl Open Source Ground Control Station
(c) 2009, 2015 QGROUNDCONTROL PROJECT <http://www.qgroundcontrol.org>
This file is part of the QGROUNDCONTROL project
QGROUNDCONTROL is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
QGROUNDCONTROL is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with QGROUNDCONTROL. If not, see <http://www.gnu.org/licenses/>.
======================================================================*/
import QtQuick 2.5
import QtQuick.Controls 1.2
import QtGraphicalEffects 1.0
import QtQuick.Controls.Styles 1.2
import QtQuick.Dialogs 1.1
import QGroundControl 1.0
import QGroundControl.Controls 1.0
import QGroundControl.ScreenTools 1.0
Row {
spacing: tbSpacing * 2
function getSatStrength(count) {
if (count < 1)
return 0
if (count < 4)
return 20
if (count < 6)
return 40
if (count < 8)
return 60
if (count < 10)
return 80
return 100
}
function getMessageColor() {
if (activeVehicle) {
if (activeVehicle.messageTypeNone)
return colorGrey
if (activeVehicle.messageTypeNormal)
return colorBlue;
if (activeVehicle.messageTypeWarning)
return colorOrange;
if (activeVehicle.messageTypeError)
return colorRed;
}
// Cannot be so make make it obnoxious to show error
console.log("Invalid vehicle message type")
return "purple";
}
function getBatteryVoltageText() {
if (activeVehicle.batteryVoltage > 0) {
//-- TODO: Need number of cells so I can show cell voltage instead of total voltage
//if (battNumCells && battNumCells.value) {
// return (activeVehicle.batteryVoltage / battNumCells.value).toFixed(2) + 'V'
//} else {
return activeVehicle.batteryVoltage.toFixed(1) + 'V'
//}
}
return 'N/A';
}
function getBatteryPercentageText() {
if(activeVehicle) {
if(activeVehicle.batteryPercent > 98.9) {
return "100%"
}
if(activeVehicle.batteryPercent > 0.1) {
return activeVehicle.batteryPercent.toFixed(0) + "%"
}
}
return "N/A"
}
//-------------------------------------------------------------------------
//-- Message Indicator
Item {
id: messages
width: mainWindow.tbCellHeight
height: mainWindow.tbCellHeight
visible: activeVehicle ? activeVehicle.messageCount : false
anchors.verticalCenter: parent.verticalCenter
Item {
id: criticalMessage
anchors.fill: parent
visible: activeVehicle ? (activeVehicle.messageCount > 0 && isMessageImportant) : false
Image {
source: "/qmlimages/Yield.svg"
height: mainWindow.tbCellHeight * 0.75
fillMode: Image.PreserveAspectFit
mipmap: true
smooth: true
cache: false
visible: isMessageImportant
anchors.verticalCenter: parent.verticalCenter
anchors.horizontalCenter: parent.horizontalCenter
}
SequentialAnimation {
id: loopAnimation
loops: Animation.Infinite
NumberAnimation { target: criticalMessage; property: "opacity"; duration: 1000; from: 0.25; to: 1 }
NumberAnimation { target: criticalMessage; property: "opacity"; duration: 1000; from: 1; to: 0.25 }
}
onVisibleChanged: {
if(messages.visible) {
loopAnimation.start()
} else {
loopAnimation.stop()
}
}
}
Item {
anchors.fill: parent
visible: !criticalMessage.visible
Image {
id: messageIcon
source: "/qmlimages/Megaphone.svg"
height: mainWindow.tbCellHeight * 0.5
fillMode: Image.PreserveAspectFit
mipmap: true
smooth: true
visible: false
anchors.verticalCenter: parent.verticalCenter
anchors.horizontalCenter: parent.horizontalCenter
}
ColorOverlay {
anchors.fill: messageIcon
source: messageIcon
color: getMessageColor()
}
}
MouseArea {
anchors.fill: parent
onClicked: {
mainWindow.showMessageArea()
}
}
}
//-------------------------------------------------------------------------
//-- GPS Indicator
Item {
id: satelitte
width: gpsRow.width * 1.1
height: mainWindow.tbCellHeight
Row {
id: gpsRow
height: parent.height
Image {
id: gpsIcon
source: "/qmlimages/Gps.svg"
fillMode: Image.PreserveAspectFit
mipmap: true
smooth: true
width: mainWindow.tbCellHeight * 0.65
height: mainWindow.tbCellHeight * 0.5
opacity: activeVehicle ? (activeVehicle.satelliteCount < 1 ? 0.5 : 1) : 0.5
anchors.verticalCenter: parent.verticalCenter
}
SignalStrength {
size: mainWindow.tbCellHeight * 0.5
percent: activeVehicle ? getSatStrength(activeVehicle.satelliteCount) : ""
anchors.verticalCenter: parent.verticalCenter
}
}
QGCLabel {
text: activeVehicle ? activeVehicle.satelliteCount : 0
font.pixelSize: tbFontSmall
color: colorWhite
opacity: activeVehicle ? (activeVehicle.satelliteCount < 1 ? 0.5 : 1) : 0.5
anchors.top: parent.top
anchors.leftMargin: gpsIcon.width
anchors.left: parent.left
}
MouseArea {
anchors.fill: parent
onClicked: {
var centerX = mapToItem(toolBar, x, y).x + (width / 2)
mainWindow.showPopUp(gpsInfo, centerX)
}
}
}
//-------------------------------------------------------------------------
//-- RC RSSI
Item {
id: rcRssi
width: rssiRow.width * 1.1
height: mainWindow.tbCellHeight
Row {
id: rssiRow
height: parent.height
Image {
source: "/qmlimages/RC.svg"
fillMode: Image.PreserveAspectFit
mipmap: true
smooth: true
width: mainWindow.tbCellHeight * 0.65
height: mainWindow.tbCellHeight * 0.5
opacity: activeVehicle ? (activeVehicle.rcRSSI < 1 ? 0.5 : 1) : 0.5
anchors.verticalCenter: parent.verticalCenter
}
SignalStrength {
size: mainWindow.tbCellHeight * 0.5
percent: activeVehicle ? activeVehicle.rcRSSI : 0
anchors.verticalCenter: parent.verticalCenter
}
}
MouseArea {
anchors.fill: parent
onClicked: {
var centerX = mapToItem(toolBar, x, y).x + (width / 2)
mainWindow.showPopUp(rcRSSIInfo, centerX)
}
}
}
//-------------------------------------------------------------------------
//-- Telemetry RSSI
Item {
id: telemRssi
width: telemIcon.width
height: mainWindow.tbCellHeight
visible: _controller.telemetryLRSSI < 0
Image {
id: telemIcon
source: "/qmlimages/TelemRSSI.svg"
fillMode: Image.PreserveAspectFit
mipmap: true
smooth: true
height: parent.height * 0.5
width: height * 1.5
visible: false
anchors.verticalCenter: parent.verticalCenter
}
ColorOverlay {
id: telemOverlay
anchors.fill: telemIcon
source: telemIcon
color: getRSSIColor(_controller.telemetryLRSSI)
}
MouseArea {
anchors.fill: parent
onClicked: {
var centerX = mapToItem(toolBar, x, y).x + (width / 2)
mainWindow.showPopUp(telemRSSIInfo, centerX)
}
}
}
//-------------------------------------------------------------------------
//-- Battery Indicator
Item {
id: batteryStatus
width: battRow.width * 1.1
height: mainWindow.tbCellHeight
opacity: activeVehicle ? ((activeVehicle.batteryVoltage > 0) ? 1 : 0.5) : 0.5
Row {
id: battRow
height: mainWindow.tbCellHeight
anchors.horizontalCenter: parent.horizontalCenter
Image {
source: "/qmlimages/Battery.svg"
fillMode: Image.PreserveAspectFit
mipmap: true
smooth: true
height: mainWindow.tbCellHeight * 0.65
anchors.verticalCenter: parent.verticalCenter
}
QGCLabel {
text: getBatteryPercentageText()
font.pixelSize: tbFontLarge
color: getBatteryColor()
anchors.verticalCenter: parent.verticalCenter
}
}
MouseArea {
anchors.fill: parent
onClicked: {
var centerX = mapToItem(toolBar, x, y).x + (width / 2)
mainWindow.showPopUp(batteryInfo, centerX)
}
}
}
//-------------------------------------------------------------------------
//-- Vehicle Selector
QGCButton {
id: vehicleSelectorButton
width: ScreenTools.defaultFontPixelSize * 8
text: "Vehicle " + (activeVehicle ? activeVehicle.id : "None")
visible: QGroundControl.multiVehicleManager.vehicles.count > 1
anchors.verticalCenter: parent.verticalCenter
menu: vehicleMenu
Menu {
id: vehicleMenu
}
Component {
id: vehicleMenuItemComponent
MenuItem {
checkable: true
checked: vehicle.active
onTriggered: multiVehicleManager.activeVehicle = vehicle
property int vehicleId: Number(text.split(" ")[1])
property var vehicle: multiVehicleManager.getVehicleById(vehicleId)
}
}
property var vehicleMenuItems: []
function updateVehicleMenu() {
// Remove old menu items
for (var i = 0; i < vehicleMenuItems.length; i++) {
vehicleMenu.removeItem(vehicleMenuItems[i])
}
vehicleMenuItems.length = 0
// Add new items
for (var i=0; i<multiVehicleManager.vehicles.count; i++) {
var vehicle = multiVehicleManager.vehicles.get(i)
var menuItem = vehicleMenuItemComponent.createObject(null, { "text": "Vehicle " + vehicle.id })
vehicleMenuItems.push(menuItem)
vehicleMenu.insertItem(i, menuItem)
}
}
Component.onCompleted: updateVehicleMenu()
Connections {
target: multiVehicleManager.vehicles
onCountChanged: vehicleSelectorButton.updateVehicleMenu
}
}
//-------------------------------------------------------------------------
//-- Mode Selector
Item {
width: selectorRow.width * 1.1
height: mainWindow.tbCellHeight
anchors.verticalCenter: parent.verticalCenter
Row {
id: selectorRow
spacing: tbSpacing
anchors.verticalCenter: parent.verticalCenter
anchors.horizontalCenter: parent.horizontalCenter
Image {
width: mainWindow.tbCellHeight * 0.65
height: mainWindow.tbCellHeight * 0.65
fillMode: Image.PreserveAspectFit
mipmap: true
smooth: true
source: "/qmlimages/Quad.svg"
anchors.verticalCenter: parent.verticalCenter
}
QGCLabel {
text: activeVehicle ? activeVehicle.flightMode : "N/A"
font.pixelSize: tbFontLarge
color: colorWhite
anchors.verticalCenter: parent.verticalCenter
}
}
Menu {
id: flightModesMenu
}
Component {
id: flightModeMenuItemComponent
MenuItem {
checkable: true
checked: activeVehicle ? (activeVehicle.flightMode === text) : false
onTriggered: {
if(activeVehicle) {
activeVehicle.flightMode = text
}
}
}
}
property var flightModesMenuItems: []
function updateFlightModesMenu() {
if (activeVehicle.flightModeSetAvailable) {
// Remove old menu items
for (var i = 0; i < flightModesMenuItems.length; i++) {
flightModesMenu.removeItem(flightModesMenuItems[i])
}
flightModesMenuItems.length = 0
// Add new items
for (var i = 0; i < activeVehicle.flightModes.length; i++) {
var menuItem = flightModeMenuItemComponent.createObject(null, { "text": activeVehicle.flightModes[i] })
flightModesMenuItems.push(menuItem)
flightModesMenu.insertItem(i, menuItem)
}
}
}
Component.onCompleted: updateFlightModesMenu()
Connections {
target: multiVehicleManager
onActiveVehicleChanged: parent.updateFlightModesMenu
}
MouseArea {
visible: activeVehicle ? activeVehicle.flightModeSetAvailable : false
anchors.fill: parent
onClicked: {
flightModesMenu.popup()
}
}
}
//-------------------------------------------------------------------------
//-- Arm/Disarm
Item {
width: armCol.width * 1.1
height: mainWindow.tbCellHeight
anchors.verticalCenter: parent.verticalCenter
Row {
id: armCol
spacing: tbSpacing * 0.5
anchors.verticalCenter: parent.verticalCenter
Image {
width: mainWindow.tbCellHeight * 0.5
height: mainWindow.tbCellHeight * 0.5
fillMode: Image.PreserveAspectFit
mipmap: true
smooth: true
source: activeVehicle ? (activeVehicle.armed ? "/qmlimages/Disarmed.svg" : "/qmlimages/Armed.svg") : "/qmlimages/Disarmed.svg"
anchors.verticalCenter: parent.verticalCenter
}
QGCLabel {
text: activeVehicle ? (activeVehicle.armed ? "Armed" : "Disarmed") : ""
font.pixelSize: tbFontLarge
color: colorWhite
anchors.verticalCenter: parent.verticalCenter
}
}
MouseArea {
anchors.fill: parent
onClicked: {
armDialog.visible = true
}
}
MessageDialog {
id: armDialog
visible: false
icon: StandardIcon.Warning
standardButtons: StandardButton.Yes | StandardButton.No
title: activeVehicle ? (activeVehicle.armed ? "Disarming Vehicle" : "Arming Vehicle") : ""
text: activeVehicle ? (activeVehicle.armed ? "Do you want to disarm? This will cut power to all motors." : "Do you want to arm? This will enable all motors.") : ""
onYes: {
activeVehicle.armed = !activeVehicle.armed
armDialog.visible = false
}
}
}
/*
property var colorOrangeText: (qgcPal.globalTheme === QGCPalette.Light) ? "#b75711" : "#ea8225"
property var colorRedText: (qgcPal.globalTheme === QGCPalette.Light) ? "#ee1112" : "#ef2526"
property var colorGreenText: (qgcPal.globalTheme === QGCPalette.Light) ? "#046b1b" : "#00d930"
property var colorWhiteText: (qgcPal.globalTheme === QGCPalette.Light) ? "#343333" : "#f0f0f0"
function getRSSIColor(value) {
if(value < 10)
return colorRed;
if(value < 50)
return colorOrange;
return colorGreen;
}
Rectangle {
id: rssiRC
width: getProportionalDimmension(55)
height: mainWindow.tbCellHeight
visible: _controller.remoteRSSI <= 100
anchors.verticalCenter: parent.verticalCenter
color: getRSSIColor(_controller.remoteRSSI);
border.color: "#00000000"
border.width: 0
Image {
source: "qrc:/res/AntennaRC";
width: mainWindow.tbCellHeight * 0.7
fillMode: Image.PreserveAspectFit
anchors.verticalCenter: parent.verticalCenter
anchors.left: parent.left
anchors.leftMargin: getProportionalDimmension(6)
mipmap: true
smooth: true
}
QGCLabel {
text: _controller.remoteRSSI
anchors.right: parent.right
anchors.rightMargin: getProportionalDimmension(6)
anchors.verticalCenter: parent.verticalCenter
horizontalAlignment: Text.AlignRight
font.pixelSize: ScreenTools.smallFontPixelSize
font.weight: Font.DemiBold
color: colorWhite
}
}
Rectangle {
id: rssiTelemetry
width: getProportionalDimmension(80)
height: mainWindow.tbCellHeight
visible: (_controller.telemetryRRSSI > 0) && (_controller.telemetryLRSSI > 0)
anchors.verticalCenter: parent.verticalCenter
color: getRSSIColor(Math.min(_controller.telemetryRRSSI,_controller.telemetryLRSSI));
border.color: "#00000000"
border.width: 0
Image {
source: "qrc:/res/AntennaT";
width: mainWindow.tbCellHeight * 0.7
fillMode: Image.PreserveAspectFit
anchors.verticalCenter: parent.verticalCenter
anchors.left: parent.left
anchors.leftMargin: getProportionalDimmension(6)
mipmap: true
smooth: true
}
Column {
anchors.verticalCenter: parent.verticalCenter
anchors.right: parent.right
anchors.rightMargin: getProportionalDimmension(6)
Row {
anchors.right: parent.right
QGCLabel {
text: 'R '
font.pixelSize: ScreenTools.smallFontPixelSize
font.weight: Font.DemiBold
color: colorWhite
}
QGCLabel {
text: _controller.telemetryRRSSI + 'dBm'
width: getProportionalDimmension(30)
horizontalAlignment: Text.AlignRight
font.pixelSize: ScreenTools.smallFontPixelSize
font.weight: Font.DemiBold
color: colorWhite
}
}
Row {
anchors.right: parent.right
QGCLabel {
text: 'L '
font.pixelSize: ScreenTools.smallFontPixelSize
font.weight: Font.DemiBold
color: colorWhite
}
QGCLabel {
text: _controller.telemetryLRSSI + 'dBm'
width: getProportionalDimmension(30)
horizontalAlignment: Text.AlignRight
font.pixelSize: ScreenTools.smallFontPixelSize
font.weight: Font.DemiBold
color: colorWhite
}
}
}
}
*/
} // Row