Commit 4d4c024d authored by Gus Grubba's avatar Gus Grubba

Initial example of custom build

parent 903af1d7
message("Adding Custom Plugin")
#-- Version control
# Major and minor versions are defined here (manually)
CUSTOM_QGC_VER_MAJOR = 0
CUSTOM_QGC_VER_MINOR = 0
CUSTOM_QGC_VER_FIRST_BUILD = 0
# Build number is automatic
# Uses the current branch. This way it works on any branch including build-server's PR branches
CUSTOM_QGC_VER_BUILD = $$system(git --git-dir ../.git rev-list $$GIT_BRANCH --first-parent --count)
win32 {
CUSTOM_QGC_VER_BUILD = $$system("set /a $$CUSTOM_QGC_VER_BUILD - $$CUSTOM_QGC_VER_FIRST_BUILD")
} else {
CUSTOM_QGC_VER_BUILD = $$system("echo $(($$CUSTOM_QGC_VER_BUILD - $$CUSTOM_QGC_VER_FIRST_BUILD))")
}
CUSTOM_QGC_VERSION = $${CUSTOM_QGC_VER_MAJOR}.$${CUSTOM_QGC_VER_MINOR}.$${CUSTOM_QGC_VER_BUILD}
DEFINES -= GIT_VERSION=\"\\\"$$GIT_VERSION\\\"\"
DEFINES += GIT_VERSION=\"\\\"$$CUSTOM_QGC_VERSION\\\"\"
message(Custom QGC Version: $${CUSTOM_QGC_VERSION})
# Disable APM support
MAVLINK_CONF = common
CONFIG += QGC_DISABLE_APM_MAVLINK
CONFIG += QGC_DISABLE_APM_PLUGIN QGC_DISABLE_APM_PLUGIN_FACTORY QGC_DISABLE_PX4_PLUGIN_FACTORY
# MAVLink Development
exists($$PWD/mavlink_dev) {
MAVLINKPATH_REL = $$PWD/mavlink_dev
MAVLINKPATH = $$PWD/mavlink_dev
message($$sprintf("Using user-supplied mavlink development path '%1'", $$MAVLINKPATH))
}
# Branding
DEFINES += CUSTOMHEADER=\"\\\"CustomPlugin.h\\\"\"
DEFINES += CUSTOMCLASS=CustomPlugin
TARGET = CustomQGC
DEFINES += QGC_APPLICATION_NAME=\"\\\"CustomQGC\\\"\"
DEFINES += QGC_ORG_NAME=\"\\\"qgroundcontrol.org\\\"\"
DEFINES += QGC_ORG_DOMAIN=\"\\\"org.qgroundcontrol\\\"\"
RESOURCES += \
$$QGCROOT/custom/custom.qrc
QGC_APP_NAME = "Custom GS"
QGC_BINARY_NAME = "CustomQGC"
QGC_ORG_NAME = "Custom"
QGC_ORG_DOMAIN = "org.qgroundcontrol"
QGC_APP_DESCRIPTION = "Custom QGC Ground Station"
QGC_APP_COPYRIGHT = "Copyright (C) 2019 QGroundControl Development Team. All rights reserved."
QML_IMPORT_PATH += \
$$QGCROOT/custom/res
SOURCES += \
$$PWD/src/CustomPlugin.cc \
$$PWD/src/CustomQuickInterface.cc
HEADERS += \
$$PWD/src/CustomPlugin.h \
$$PWD/src/CustomQuickInterface.h
INCLUDEPATH += \
$$PWD/src \
#-------------------------------------------------------------------------------------
# Custom Firmware/AutoPilot Plugin
INCLUDEPATH += \
$$QGCROOT/custom/src/FirmwarePlugin \
$$QGCROOT/custom/src/AutoPilotPlugin
HEADERS+= \
$$QGCROOT/custom/src/AutoPilotPlugin/CustomAutoPilotPlugin.h \
$$QGCROOT/custom/src/FirmwarePlugin/CustomCameraControl.h \
$$QGCROOT/custom/src/FirmwarePlugin/CustomCameraManager.h \
$$QGCROOT/custom/src/FirmwarePlugin/CustomFirmwarePlugin.h \
$$QGCROOT/custom/src/FirmwarePlugin/CustomFirmwarePluginFactory.h \
SOURCES += \
$$QGCROOT/custom/src/AutoPilotPlugin/CustomAutoPilotPlugin.cc \
$$QGCROOT/custom/src/FirmwarePlugin/CustomCameraControl.cc \
$$QGCROOT/custom/src/FirmwarePlugin/CustomCameraManager.cc \
$$QGCROOT/custom/src/FirmwarePlugin/CustomFirmwarePlugin.cc \
$$QGCROOT/custom/src/FirmwarePlugin/CustomFirmwarePluginFactory.cc \
<RCC>
<qresource prefix="/custom">
<file alias="CustomArmedIndicator.qml">res/MainToolbar/CustomArmedIndicator.qml</file>
<file alias="CustomBatteryIndicator.qml">res/MainToolbar/CustomBatteryIndicator.qml</file>
<file alias="CustomCameraControl.qml">res/CustomCameraControl.qml</file>
<file alias="CustomFlyView.qml">res/CustomFlyView.qml</file>
<file alias="CustomGPSIndicator.qml">res/MainToolbar/CustomGPSIndicator.qml</file>
<file alias="CustomMainToolBar.qml">res/MainToolbar/CustomMainToolBar.qml</file>
<file alias="CustomMainToolBarIndicators.qml">res/MainToolbar/CustomMainToolBarIndicators.qml</file>
<file alias="CustomModeIndicator.qml">res/MainToolbar/CustomModeIndicator.qml</file>
<file alias="CustomMultiVehicleSelector.qml">res/MainToolbar/CustomMultiVehicleSelector.qml</file>
<file alias="CustomRCRSSIIndicator.qml">res/MainToolbar/CustomRCRSSIIndicator.qml</file>
</qresource>
<qresource prefix="custom/img">
<file alias="altitude.svg">res/Images/altitude.svg</file>
<file alias="attitude_crosshair.svg">res/Images/attitude_crosshair.svg</file>
<file alias="attitude_dial.svg">res/Images/attitude_dial.svg</file>
<file alias="attitude_pointer.svg">res/Images/attitude_pointer.svg</file>
<file alias="camera_photo.svg">res/Images/camera_photo.svg</file>
<file alias="camera_settings.svg">res/Images/camera_settings.svg</file>
<file alias="camera_video.svg">res/Images/camera_video.svg</file>
<file alias="chronometer.svg">res/Images/chronometer.svg</file>
<file alias="compass_needle.svg">res/Images/compass_needle.svg</file>
<file alias="compass_pointer.svg">res/Images/compass_pointer.svg</file>
<file alias="distance.svg">res/Images/distance.svg</file>
<file alias="horizontal_speed.svg">res/Images/horizontal_speed.svg</file>
<file alias="microSD.svg">res/Images/microSD.svg</file>
<file alias="odometer.svg">res/Images/odometer.svg</file>
<file alias="vertical_speed.svg">res/Images/vertical_speed.svg</file>
<file alias="void.png">res/Images/void.png</file>
</qresource>
<qresource prefix="Custom/Widgets">
<file alias="Custom/Widgets/CustomArtificialHorizon.qml">res/Custom/Widgets/CustomArtificialHorizon.qml</file>
<file alias="Custom/Widgets/CustomAttitudeWidget.qml">res/Custom/Widgets/CustomAttitudeWidget.qml</file>
<file alias="Custom/Widgets/CustomComboBox.qml">res/Custom/Widgets/CustomComboBox.qml</file>
<file alias="Custom/Widgets/CustomIconButton.qml">res/Custom/Widgets/CustomIconButton.qml</file>
<file alias="Custom/Widgets/CustomOnOffSwitch.qml">res/Custom/Widgets/CustomOnOffSwitch.qml</file>
<file alias="Custom/Widgets/CustomSignalStrength.qml">res/Custom/Widgets/CustomSignalStrength.qml</file>
<file alias="Custom/Widgets/CustomToolBarButton.qml">res/Custom/Widgets/CustomToolBarButton.qml</file>
<file alias="Custom/Widgets/CustomVehicleButton.qml">res/Custom/Widgets/CustomVehicleButton.qml</file>
<file alias="Custom/Widgets/qmldir">res/Custom/Widgets/qmldir</file>
</qresource>
</RCC>
/****************************************************************************
*
* (c) 2009-2019 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.
*
* @file
* @author Gus Grubba <gus@auterion.com>
*/
import QtQuick 2.11
Item {
id: root
property real rollAngle : 0
property real pitchAngle: 0
property color skyColor1: Qt.hsla(0.6, 1.0, 0.25)
property color skyColor2: Qt.hsla(0.6, 0.5, 0.55)
property color groundColor1: Qt.hsla(0.25, 0.5, 0.45)
property color groundColor2: Qt.hsla(0.25, 0.75, 0.25)
clip: true
anchors.fill: parent
property real angularScale: pitchAngle * root.height / 45
Item {
id: artificialHorizon
width: root.width * 4
height: root.height * 8
anchors.centerIn: parent
Rectangle {
id: sky
anchors.fill: parent
smooth: true
antialiasing: true
gradient: Gradient {
GradientStop { position: 0.25; color: root.skyColor1 }
GradientStop { position: 0.5; color: root.skyColor2 }
}
}
Rectangle {
id: ground
height: sky.height / 2
anchors {
left: sky.left;
right: sky.right;
bottom: sky.bottom
}
smooth: true
antialiasing: true
gradient: Gradient {
GradientStop { position: 0.0; color: root.groundColor1 }
GradientStop { position: 0.25; color: root.groundColor2 }
}
}
transform: [
Translate {
y: angularScale
},
Rotation {
origin.x: artificialHorizon.width / 2
origin.y: artificialHorizon.height / 2
angle: -rollAngle
}]
}
}
/****************************************************************************
*
* (c) 2009-2019 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.
*
* @file
* @author Gus Grubba <gus@auterion.com>
*/
import QtQuick 2.11
import QtGraphicalEffects 1.0
import QGroundControl 1.0
import QGroundControl.Controls 1.0
import QGroundControl.ScreenTools 1.0
import QGroundControl.Palette 1.0
import QGroundControl.FlightMap 1.0
Item {
id: root
property bool showPitch: true
property var vehicle: null
property real size
property bool showHeading: false
property real _rollAngle: vehicle ? vehicle.roll.rawValue : 0
property real _pitchAngle: vehicle ? vehicle.pitch.rawValue : 0
width: size
height: size
Item {
id: instrument
anchors.fill: parent
visible: false
//----------------------------------------------------
//-- Artificial Horizon
CustomArtificialHorizon {
rollAngle: _rollAngle
pitchAngle: _pitchAngle
skyColor1: "#0a2e50"
skyColor2: "#2f85d4"
groundColor1: "#897459"
groundColor2: "#4b3820"
anchors.fill: parent
}
//----------------------------------------------------
//-- Instrument Dial
Image {
id: instrumentDial
source: "/custom/img/attitude_dial.svg"
mipmap: true
fillMode: Image.PreserveAspectFit
anchors.fill: parent
sourceSize.height: parent.height
transform: Rotation {
origin.x: root.width / 2
origin.y: root.height / 2
angle: -_rollAngle
}
}
//----------------------------------------------------
//-- Pointer
Image {
id: pointer
height: size * 0.0625
width: height
source: "/custom/img/attitude_pointer.svg"
antialiasing: true
fillMode: Image.PreserveAspectFit
sourceSize.height: height
anchors.top: parent.top
anchors.horizontalCenter: parent.horizontalCenter
}
//----------------------------------------------------
//-- Pitch
QGCPitchIndicator {
id: pitchWidget
visible: root.showPitch
size: root.size * 0.5
anchors.verticalCenter: parent.verticalCenter
pitchAngle: _pitchAngle
rollAngle: _rollAngle
color: Qt.rgba(0,0,0,0)
}
//----------------------------------------------------
//-- Cross Hair
Image {
id: crossHair
anchors.centerIn: parent
source: "/custom/img/attitude_crosshair.svg"
mipmap: true
width: size * 0.75
sourceSize.width: width
fillMode: Image.PreserveAspectFit
}
}
Rectangle {
id: mask
anchors.fill: instrument
radius: width / 2
color: "black"
visible: false
}
OpacityMask {
anchors.fill: instrument
source: instrument
maskSource: mask
}
Rectangle {
id: borderRect
anchors.fill: parent
radius: width / 2
color: Qt.rgba(0,0,0,0)
border.color: "#000"
border.width: 1
}
QGCLabel {
anchors.bottomMargin: Math.round(ScreenTools.defaultFontPixelHeight * 0.5)
anchors.bottom: parent.bottom
anchors.horizontalCenter: parent.horizontalCenter
text: _headingString3
color: "white"
visible: showHeading
font.pointSize: ScreenTools.smallFontPointSize
property string _headingString: vehicle ? vehicle.heading.rawValue.toFixed(0) : "OFF"
property string _headingString2: _headingString.length === 1 ? "0" + _headingString : _headingString
property string _headingString3: _headingString2.length === 2 ? "0" + _headingString2 : _headingString2
}
}
/****************************************************************************
*
* (c) 2009-2019 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.
*
* @file
* @author Gus Grubba <gus@auterion.com>
*/
import QtQuick 2.11
import QtQuick.Controls 1.4
import QtQuick.Controls.Styles 1.4
import QGroundControl.Controls 1.0
import QGroundControl.Palette 1.0
import QGroundControl.ScreenTools 1.0
Button {
id: combo
property real pointSize: ScreenTools.defaultFontPointSize ///< Point size for button text
property bool centeredLabel: false
property alias model: popupItems.model
property alias textRole: popup.textRole
property alias currentIndex: popup.__selectedIndex
readonly property alias count: popupItems.count
readonly property alias currentText: popup.currentText
property var _qgcPal: QGCPalette { colorGroupEnabled: enabled }
property int _verticalPadding: Math.round(ScreenTools.defaultFontPixelHeight * 0.5)
property real _dropImageWidth: ScreenTools.defaultFontPixelHeight * 0.5
property real _dropImageMargin: _dropImageWidth * 0.5
property var __popup: popup
signal activated(int index)
style: ButtonStyle {
/*! This defines the background of the button. */
background: Rectangle {
implicitWidth: Math.round(ScreenTools.defaultFontPixelWidth * 6)
implicitHeight: Math.round(ScreenTools.defaultFontPixelHeight)
color: Qt.rgba(0,0,0,0)
/*
Image {
id: image
width: _dropImageWidth
height: _dropImageWidth
anchors.verticalCenter: parent.verticalCenter
anchors.rightMargin: _dropImageMargin
anchors.right: parent.right
source: "/custom/img/menu_dropdown.svg"
}
*/
}
/*! This defines the label of the button. */
label: Item {
implicitWidth: text.implicitWidth
implicitHeight: text.implicitHeight
baselineOffset: text.y + text.baselineOffset
QGCLabel {
id: text
anchors.verticalCenter: parent.verticalCenter
anchors.horizontalCenter: centeredLabel ? parent.horizontalCenter : undefined
text: control.currentText
color: "#FFF"
font.pointSize: combo.pointSize
}
}
}
onClicked: {
combo.focus = true
popup.toggleShow()
}
Component.onCompleted: {
if (currentIndex === -1) {
currentIndex = 0
}
popup.resolveTextValue(textRole)
}
function textAt (index) {
if (index >= count || index < 0)
return null;
return popupItems.objectAt(index).text;
}
function find (text) {
for (var i = 0 ; i < popupItems.count ; ++i) {
var currentString = popupItems.objectAt(i).text
if (text === currentString) {
return i
}
}
return -1
}
ExclusiveGroup { id: eg }
Menu {
id: popup
__minimumWidth: combo.width
__visualItem: combo
style: MenuStyle {
font.pointSize: combo.pointSize
font.family: ScreenTools.normalFontFamily
__labelColor: combo._qgcPal.buttonText
__selectedLabelColor: combo._qgcPal.buttonHighlightText
__selectedBackgroundColor: combo._qgcPal.buttonHighlight
__backgroundColor: combo._qgcPal.button
__maxPopupHeight: 600
__menuItemType: "comboboxitem"
__scrollerStyle: ScrollViewStyle { }
}
property string textRole: ""
property bool showing: false
property string currentText: selectedText
property string selectedText
onSelectedTextChanged: popup.currentText = selectedText
on__SelectedIndexChanged: {
if (__selectedIndex === -1)
popup.currentText = ""
else
updateSelectedText()
}
property int _y: combo.height
property bool _modelIsArray: false
onAboutToShow: showing = true
onAboutToHide: showing = false
function toggleShow() {
if (popup._popupVisible) {
popup.__dismissAndDestroy()
} else {
__popup(Qt.rect(0, _y, 0, 0), 0)
}
}
function resolveTextValue(initialTextRole) {
if (!model) {
return
}
var get = model['get'];
if (!get && popup._modelIsArray && !!model[0]) {
if (model[0].constructor !== String && model[0].constructor !== Number)
get = function(i) { return model[i]; }
}
var modelMayHaveRoles = get !== undefined
textRole = initialTextRole
if (textRole === "" && modelMayHaveRoles && get(0)) {
// No text role set, check whether model has a suitable role
// If 'text' is found, or there's only one role, pick that.
var listElement = get(0)
var roleName = ""
var roleCount = 0
for (var role in listElement) {
if (listElement[role].constructor === Function)
continue;
if (role === "text") {
roleName = role
break
} else if (!roleName) {
roleName = role
}
++roleCount
}
if (roleCount > 1 && roleName !== "text") {
console.warn("No suitable 'textRole' found for ComboBox.")
} else {
textRole = roleName
}
}
updateSelectedText()
}
function updateSelectedText() {
var selectedItem
if (__selectedIndex !== -1 && (selectedItem = items[__selectedIndex])) {
selectedText = Qt.binding(function () { return selectedItem.text })
if (currentText !== selectedText) // __selectedIndex went form -1 to 0
selectedTextChanged()
}
}
Instantiator {
id: popupItems
onModelChanged: {
popup._modelIsArray = !!model ? model.constructor === Array : false
popup.resolveTextValue(popup.textRole)
}
onObjectAdded: {
// There is a bug in Instantiator which can cause objects to be added out of order from an index standpoint.
// If not handled correctly this will cause menu items to be added incorrectly due to the way Menu.insertItem works.
//console.log("menu add", index, object.text)
if (index === popup.__selectedIndex) {
popup.selectedText = object["text"]
}
// Find the correct place for menu item. We can't just add at index, due to possible bad ordering
var insertIndex = -1
for (var i=0; i<popup.items.length; i++) {
//console.log("position search", i, popup.items[i].itemIndex)
if (popup.items[i].itemIndex > index) {
insertIndex = i
break
}
}
if (insertIndex === -1) {
popup.insertItem(popup.items.length, object)
} else {
//console.log("out of order menu add", index, insertIndex)
popup.insertItem(insertIndex, object)
}
}
onObjectRemoved: popup.removeItem(object)
MenuItem {
text: popup.textRole === '' ? modelData : ((popup._modelIsArray ? modelData[popup.textRole] : model[popup.textRole]) || '')
checked: index == currentIndex
checkable: true
exclusiveGroup: eg
property int itemIndex: index
onTriggered: {
//console.log("onTriggered", index, currentIndex)
if (index !== currentIndex) {
//console.log("activated", index)
activated(index)
}
}
}
}
}
}
/****************************************************************************
*
* (c) 2009-2019 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.
*
* @file
* @author Gus Grubba <gus@auterion.com>
*/
import QtQuick 2.11
import QtQuick.Controls 2.4
import QGroundControl 1.0
import QGroundControl.Controls 1.0
import QGroundControl.Palette 1.0
import QGroundControl.ScreenTools 1.0
import QtGraphicalEffects 1.0
Button {
id: _rootButton
width: parent.height * 1.25
height: parent.height
flat: true
contentItem: Item {
id: _content
anchors.fill: _rootButton
Row {
id: _edge
spacing: ScreenTools.defaultFontPixelWidth * 0.25
anchors.left: parent.left
anchors.leftMargin: ScreenTools.defaultFontPixelWidth
anchors.verticalCenter: parent.verticalCenter
Repeater {
model: [1,2,3]
Rectangle {
height: ScreenTools.defaultFontPixelHeight
width: ScreenTools.defaultFontPixelWidth * 0.25
color: qgcPal.text
opacity: 0.75
}
}
}
Image {
id: _icon
height: _rootButton.height * 0.75
width: height
smooth: true
mipmap: true
antialiasing: true
fillMode: Image.PreserveAspectFit
source: "/res/QGCLogoWhite"
sourceSize.height: height
anchors.left: _edge.right
anchors.leftMargin: ScreenTools.defaultFontPixelWidth
anchors.verticalCenter: parent.verticalCenter
}
}
background: Item {
anchors.fill: parent
}
}
/****************************************************************************
*
* (c) 2009-2019 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.
*
* @file
* @author Gus Grubba <gus@auterion.com>
*/
import QtQuick 2.3
import QGroundControl.Palette 1.0
import QGroundControl.ScreenTools 1.0
import QGroundControl.Controls 1.0
Rectangle {
id: _root
height: Math.round(ScreenTools.defaultFontPixelHeight * 2)
width: ScreenTools.defaultFontPixelWidth * 10
color: qgcPal.button
border.color: qgcPal.text
border.width: 1
property bool checked: true
signal clicked
QGCPalette { id: qgcPal; colorGroupEnabled: true }
Rectangle {
width: parent.width * 0.5
height: parent.height
color: qgcPal.windowShade
visible: !checked
border.color: qgcPal.text
border.width: 1
anchors.left: parent.left
anchors.verticalCenter: parent.verticalCenter
QGCLabel {
text: qsTr("Off")
anchors.centerIn: parent
}
}
Rectangle {
width: parent.width * 0.5
height: parent.height * 0.95
color: qgcPal.buttonHighlight
visible: checked
border.color: qgcPal.text
border.width: 1
anchors.right: parent.right
anchors.verticalCenter: parent.verticalCenter
QGCLabel {
text: qsTr("On")
color: qgcPal.buttonHighlightText
anchors.centerIn: parent
}
}
MouseArea {
anchors.fill: parent
onClicked: {
checked = !checked
_root.clicked()
}
}
}
/****************************************************************************
*
* (c) 2009-2019 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.
*
* @file
* @author Gus Grubba <gus@auterion.com>
*/
import QtQuick 2.11
import QtQuick.Controls 1.4
import QGroundControl 1.0
import QGroundControl.Controls 1.0
import QGroundControl.ScreenTools 1.0
import QGroundControl.Palette 1.0
Item {
width: size
height: size
property real size: 50
property real percent: 0
QGCPalette { id: qgcPal }
function getIcon() {
if (percent < 20)
return "/custom/img/menu_signal_0.svg"
if (percent < 40)
return "/custom/img/menu_signal_25.svg"
if (percent < 60)
return "/custom/img/menu_signal_50.svg"
if (percent < 90)
return "/custom/img/menu_signal_75.svg"
return "/custom/img/menu_signal_100.svg"
}
QGCColoredImage {
source: getIcon()
fillMode: Image.PreserveAspectFit
anchors.fill: parent
sourceSize.height: size
color: qgcPal.text
}
}
/****************************************************************************
*
* (c) 2009-2019 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.
*
* @file
* @author Gus Grubba <gus@auterion.com>
*/
import QtQuick 2.11
import QtQuick.Controls 2.4
import QGroundControl.Controls 1.0
import QGroundControl.Palette 1.0
import QGroundControl.ScreenTools 1.0
Button {
id: button
autoExclusive: true
background: Rectangle {
anchors.fill: parent
color: mouseArea.pressed ? qgcPal.buttonHighlight : Qt.rgba(0,0,0,0)
}
contentItem: Row {
spacing: ScreenTools.defaultFontPixelWidth
anchors.left: button.left
anchors.leftMargin: ScreenTools.defaultFontPixelWidth
anchors.verticalCenter: button.verticalCenter
Item {
height: ScreenTools.defaultFontPixelHeight * 3
width: 1
}
QGCColoredImage {
id: _icon
height: ScreenTools.defaultFontPixelHeight
width: height
sourceSize.height: parent.height
fillMode: Image.PreserveAspectFit
color: (mouseArea.pressed || button.checked) ? qgcPal.buttonHighlightText : qgcPal.buttonText
source: button.icon.source
anchors.verticalCenter: parent.verticalCenter
}
Label {
id: _label
visible: text !== ""
text: button.text
color: (mouseArea.pressed || button.checked) ? qgcPal.buttonHighlightText : qgcPal.buttonText
anchors.verticalCenter: parent.verticalCenter
}
}
// Process hover events
MouseArea {
id: mouseArea
anchors.fill: parent
onClicked: button.clicked()
}
}
/****************************************************************************
*
* (c) 2009-2019 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.
*
* @file
* @author Gus Grubba <gus@auterion.com>
*/
import QtQuick 2.11
import QtQuick.Controls 2.4
import QGroundControl.Controls 1.0
import QGroundControl.Palette 1.0
import QGroundControl.ScreenTools 1.0
Button {
id: button
height: _infoCol.height * 1.25
autoExclusive: true
property var vehicle: null
function getBatteryColor() {
if(vehicle) {
if(vehicle.battery.percentRemaining.value > 75) {
return qgcPal.colorGreen
}
if(vehicle.battery.percentRemaining.value > 50) {
return qgcPal.colorOrange
}
if(vehicle.battery.percentRemaining.value > 0.1) {
return qgcPal.colorRed
}
}
return qgcPal.colorGrey
}
function getBatteryPercentage() {
if(vehicle) {
return vehicle.battery.percentRemaining.value / 100.0
}
return 1
}
background: Rectangle {
anchors.fill: parent
color: button.checked ? qgcPal.buttonHighlight : qgcPal.button
radius: ScreenTools.defaultFontPixelWidth * 0.5
}
contentItem: Row {
spacing: ScreenTools.defaultFontPixelWidth
anchors.margins: ScreenTools.defaultFontPixelWidth
anchors.verticalCenter: button.verticalCenter
QGCColoredImage {
id: _icon
height: ScreenTools.defaultFontPixelHeight * 1.5
width: height
sourceSize.height: parent.height
fillMode: Image.PreserveAspectFit
color: qgcPal.buttonText
source: "/qmlimages/PaperPlane.svg"
anchors.verticalCenter: parent.verticalCenter
}
Column {
id: _infoCol
spacing: ScreenTools.defaultFontPixelHeight * 0.25
QGCLabel {
text: qsTr("Vehicle ") + (vehicle ? vehicle.id : qsTr("None"))
font.family: ScreenTools.demiboldFontFamily
color: qgcPal.buttonText
}
Row {
spacing: ScreenTools.defaultFontPixelWidth
QGCLabel {
text: vehicle ? vehicle.flightMode : qsTr("None")
color: qgcPal.buttonText
}
Rectangle {
height: ScreenTools.defaultFontPixelHeight * 0.5
width: ScreenTools.defaultFontPixelWidth * 3
color: Qt.rgba(0,0,0,0)
anchors.verticalCenter: parent.verticalCenter
Rectangle {
height: parent.height
width: parent.width * getBatteryPercentage()
color: getBatteryColor()
anchors.right: parent.right
}
}
}
}
}
}
Module Custom.Widgets
CustomArtificialHorizon 1.0 CustomArtificialHorizon.qml
CustomAttitudeWidget 1.0 CustomAttitudeWidget.qml
CustomComboBox 1.0 CustomComboBox.qml
CustomIconButton 1.0 CustomIconButton.qml
CustomOnOffSwitch 1.0 CustomOnOffSwitch.qml
CustomSignalStrength 1.0 CustomSignalStrength.qml
CustomToolBarButton 1.0 CustomToolBarButton.qml
CustomVehicleButton 1.0 CustomVehicleButton.qml
\ No newline at end of file
/****************************************************************************
*
* (c) 2009-2019 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.
*
* @file
* @author Gus Grubba <gus@auterion.com>
*/
import QtQuick 2.11
import QtQuick.Controls 2.4
import QtQuick.Layouts 1.11
import QtQuick.Dialogs 1.3
import QtMultimedia 5.9
import QtPositioning 5.2
import QGroundControl 1.0
import QGroundControl.Controls 1.0
import QGroundControl.FactControls 1.0
import QGroundControl.FactSystem 1.0
import QGroundControl.FlightMap 1.0
import QGroundControl.Palette 1.0
import QGroundControl.ScreenTools 1.0
import QGroundControl.Vehicle 1.0
import CustomQuickInterface 1.0
import Custom.Widgets 1.0
Item {
height: cameraRect.height
width: cameraRect.width + (ScreenTools.defaultFontPixelWidth * 2)
visible: !QGroundControl.videoManager.fullScreen
readonly property string _commLostStr: qsTr("NO CAMERA")
property real _spacers: ScreenTools.defaultFontPixelHeight
property real _labelFieldWidth: ScreenTools.defaultFontPixelWidth * 28
property real _editFieldWidth: ScreenTools.defaultFontPixelWidth * 30
property var _dynamicCameras: activeVehicle ? activeVehicle.dynamicCameras : null
property bool _isCamera: _dynamicCameras ? _dynamicCameras.cameras.count > 0 : false
property int _curCameraIndex: _dynamicCameras ? _dynamicCameras.currentCamera : 0
property var _camera: _isCamera ? _dynamicCameras.cameras.get(_curCameraIndex) : null
property bool _communicationLost: activeVehicle ? activeVehicle.connectionLost : false
property bool _noSdCard: _camera && _camera.storageTotal === 0
property bool _fullSD: _camera && _camera.storageTotal !== 0 && _camera.storageFree > 0 && _camera.storageFree < 250 // We get kiB from the camera
property bool _cameraVideoMode: !_communicationLost && (_noSdCard ? false : _camera && _camera.cameraMode === QGCCameraControl.CAM_MODE_VIDEO)
property bool _cameraPhotoMode: !_communicationLost && (_noSdCard ? false : _camera && (_camera.cameraMode === QGCCameraControl.CAM_MODE_PHOTO || _camera.cameraMode === QGCCameraControl.CAM_MODE_SURVEY))
property bool _cameraPhotoIdle: !_communicationLost && (_noSdCard ? false : _camera && _camera.photoStatus === QGCCameraControl.PHOTO_CAPTURE_IDLE)
property bool _cameraElapsedMode: !_communicationLost && (_noSdCard ? false : _camera && _camera.cameraMode === QGCCameraControl.CAM_MODE_PHOTO && _camera.photoMode === QGCCameraControl.PHOTO_CAPTURE_TIMELAPSE)
property bool _cameraModeUndefined: !_cameraPhotoMode && !_cameraVideoMode
property bool _recordingVideo: _cameraVideoMode && _camera.videoStatus === QGCCameraControl.VIDEO_CAPTURE_STATUS_RUNNING
property bool _settingsEnabled: !_communicationLost && _camera && _camera.cameraMode !== QGCCameraControl.CAM_MODE_UNDEFINED && _camera.photoStatus === QGCCameraControl.PHOTO_CAPTURE_IDLE && !_recordingVideo
property bool _hasZoom: _camera && _camera.hasZoom
property Fact _evFact: _camera ? _camera.ev : null
property Fact _irPaletteFact: _camera ? _camera.irPalette : null
Connections {
target: QGroundControl.multiVehicleManager.activeVehicle
onConnectionLostChanged: {
if(_communicationLost && cameraSettings.visible) {
cameraSettings.close()
}
}
}
DeadMouseArea {
anchors.fill: parent
}
Rectangle {
id: cameraRect
height: cameraCol.height
width: cameraCol.width + (ScreenTools.defaultFontPixelWidth * 4)
color: qgcPal.windowShade
radius: ScreenTools.defaultFontPixelWidth * 0.5
Column {
id: cameraCol
spacing: _spacers
anchors.centerIn: parent
Item {
height: 1
width: 1
}
//-----------------------------------------------------------------
//-- Camera Name
QGCLabel {
text: activeVehicle ? (_camera && _camera.modelName !== "" ? _camera.modelName : _commLostStr) : _commLostStr
font.pointSize: ScreenTools.smallFontPointSize
anchors.horizontalCenter: parent.horizontalCenter
}
//-----------------------------------------------------------------
//-- Camera Mode
Item {
width: modeCol.width
height: modeCol.height
anchors.horizontalCenter: parent.horizontalCenter
Column {
id: modeCol
spacing: _spacers * 0.5
QGCColoredImage {
height: ScreenTools.defaultFontPixelHeight * 1.25
width: height
source: (_cameraModeUndefined || _cameraPhotoMode) ? "/custom/img/camera_photo.svg" : "/custom/img/camera_video.svg"
color: qgcPal.text
fillMode: Image.PreserveAspectFit
sourceSize.height: height
anchors.horizontalCenter: parent.horizontalCenter
}
QGCLabel {
text: _cameraVideoMode ? qsTr("Video") : qsTr("Photo")
font.pointSize: ScreenTools.smallFontPointSize
anchors.horizontalCenter: parent.horizontalCenter
}
}
MouseArea {
anchors.fill: parent
enabled: !_cameraModeUndefined && _camera && _camera.videoStatus !== QGCCameraControl.VIDEO_CAPTURE_STATUS_RUNNING && _cameraPhotoIdle
onClicked: {
_camera.toggleMode()
}
}
}
//-----------------------------------------------------------------
//-- Shutter
Rectangle {
color: Qt.rgba(0,0,0,0)
width: height
height: ScreenTools.defaultFontPixelHeight * 4
radius: width * 0.5
border.color: qgcPal.buttonText
border.width: 2
anchors.horizontalCenter: parent.horizontalCenter
Rectangle {
width: parent.width * 0.75
height: width
radius: width * 0.5
color: _cameraModeUndefined ? qgcPal.colorGrey : ( _cameraVideoMode ? qgcPal.colorRed : qgcPal.text )
visible: !pauseVideo.visible
anchors.centerIn: parent
QGCColoredImage {
id: busyIndicator
height: parent.height * 0.75
width: height
source: "/qmlimages/MapSync.svg"
sourceSize.height: height
fillMode: Image.PreserveAspectFit
mipmap: true
smooth: true
color: qgcPal.windowShade
visible: {
if(_cameraPhotoMode && !_cameraPhotoIdle && !_cameraElapsedMode) {
return true
}
return false
}
anchors.centerIn: parent
RotationAnimation on rotation {
loops: Animation.Infinite
from: 360
to: 0
duration: 740
running: busyIndicator.visible
}
}
QGCLabel {
text: _camera ? _camera.photoLapse.toFixed(0) + 's' : qsTr('N/A')
font.family: ScreenTools.demiboldFontFamily
color: qgcPal.colorBlue
visible: _cameraElapsedMode
anchors.centerIn: parent
}
}
Rectangle {
id: pauseVideo
width: parent.width * 0.5
height: width
color: _cameraModeUndefined ? qgcPal.colorGrey : qgcPal.colorRed
visible: {
if(_cameraVideoMode && _camera.videoStatus === QGCCameraControl.VIDEO_CAPTURE_STATUS_RUNNING) {
return true
}
if(_cameraPhotoMode) {
if(_camera.photoStatus === QGCCameraControl.PHOTO_CAPTURE_INTERVAL_IDLE || _camera.photoStatus === QGCCameraControl.PHOTO_CAPTURE_INTERVAL_IN_PROGRESS) {
return true
}
}
return false
}
anchors.centerIn: parent
}
MouseArea {
anchors.fill: parent
enabled: !_noSdCard
onClicked: {
if(_cameraVideoMode) {
if(_camera.videoStatus === QGCCameraControl.VIDEO_CAPTURE_STATUS_RUNNING) {
_camera.stopVideo()
} else {
if(!_fullSD) {
_camera.startVideo()
}
}
} else {
if(_camera.photoStatus === QGCCameraControl.PHOTO_CAPTURE_INTERVAL_IDLE || _camera.photoStatus === QGCCameraControl.PHOTO_CAPTURE_INTERVAL_IN_PROGRESS) {
_camera.stopTakePhoto()
} else {
if(!_fullSD) {
_camera.takePhoto()
}
}
}
}
}
}
//-----------------------------------------------------------------
//-- Settings
Item {
width: settingsCol.width
height: settingsCol.height
anchors.horizontalCenter: parent.horizontalCenter
Column {
id: settingsCol
spacing: _spacers * 0.5
anchors.horizontalCenter: parent.horizontalCenter
QGCColoredImage {
width: ScreenTools.defaultFontPixelHeight * 1.25
height: width
sourceSize.width: width
source: "qrc:/custom/img/camera_settings.svg"
color: qgcPal.text
fillMode: Image.PreserveAspectFit
opacity: _settingsEnabled ? 1 : 0.5
anchors.horizontalCenter: parent.horizontalCenter
}
QGCLabel {
text: qsTr("Settings")
font.pointSize: ScreenTools.smallFontPointSize
anchors.horizontalCenter: parent.horizontalCenter
}
}
MouseArea {
anchors.fill: parent
enabled: _settingsEnabled
onClicked: {
cameraSettings.open()
}
}
}
//-----------------------------------------------------------------
//-- microSD Card
Column {
spacing: _spacers * 0.5
anchors.horizontalCenter: parent.horizontalCenter
QGCColoredImage {
width: ScreenTools.defaultFontPixelHeight * 1.25
height: width
sourceSize.width: width
source: "qrc:/custom/img/microSD.svg"
color: qgcPal.text
fillMode: Image.PreserveAspectFit
opacity: _settingsEnabled ? 1 : 0.5
anchors.horizontalCenter: parent.horizontalCenter
}
QGCLabel {
text: {
if(_noSdCard) return qsTr("NONE")
if(_fullSD) return qsTr("FULL")
return _camera ? _camera.storageFreeStr : ""
}
color: (_noSdCard || _fullSD) ? qgcPal.colorOrange : qgcPal.text
font.pointSize: ScreenTools.smallFontPointSize
anchors.horizontalCenter: parent.horizontalCenter
}
}
/*
//-----------------------------------------------------------------
//-- Recording Time / Images Captured
CustomLabel {
text: (_cameraVideoMode && _camera.videoStatus === QGCCameraControl.VIDEO_CAPTURE_STATUS_RUNNING) ? _camera.recordTimeStr : "00:00:00"
visible: _cameraVideoMode
pointSize: ScreenTools.smallFontPointSize
anchors.horizontalCenter: parent.horizontalCenter
}
CustomLabel {
text: activeVehicle && _cameraPhotoMode ? ('00000' + activeVehicle.cameraTriggerPoints.count).slice(-5) : "00000"
visible: _cameraPhotoMode
pointSize: ScreenTools.smallFontPointSize
anchors.horizontalCenter: parent.horizontalCenter
}
*/
Item {
height: 1
width: 1
}
}
}
//-------------------------------------------------------------------------
//-- Camera Settings
Popup {
id: cameraSettings
width: Math.min(mainWindow.width * 0.666, ScreenTools.defaultFontPixelWidth * 80)
height: mainWindow.height * 0.666
modal: true
focus: true
parent: Overlay.overlay
x: Math.round((mainWindow.width - width) * 0.5)
y: Math.round((mainWindow.height - height) * 0.5)
closePolicy: Popup.CloseOnEscape | Popup.CloseOnPressOutside
background: Rectangle {
anchors.fill: parent
color: qgcPal.globalTheme === QGCPalette.Light ? Qt.rgba(1,1,1,0.95) : Qt.rgba(0,0,0,0.75)
border.color: qgcPal.text
radius: ScreenTools.defaultFontPixelWidth
}
Item {
anchors.fill: parent
anchors.margins: ScreenTools.defaultFontPixelHeight
function showEditFact(fact) {
factEditor.text = fact.valueString
factEdit.fact = fact
factEdit.visible = true
}
function hideEditFact() {
factEdit.visible = false
factEdit.fact = null
}
QGCLabel {
id: cameraSettingsLabel
text: _noSdCard ? qsTr("Settings") : (_cameraVideoMode ? qsTr("Video Settings") : qsTr("Photo Settings"))
font.family: ScreenTools.demiboldFontFamily
font.pointSize: ScreenTools.mediumFontPointSize
anchors.margins: ScreenTools.defaultFontPixelWidth
anchors.top: parent.top
anchors.left: parent.left
}
QGCFlickable {
clip: true
anchors.top: cameraSettingsLabel.bottom
anchors.bottom: parent.bottom
anchors.margins: ScreenTools.defaultFontPixelWidth
width: cameraSettingsCol.width + (ScreenTools.defaultFontPixelWidth * 2)
contentHeight: cameraSettingsCol.height
contentWidth: cameraSettingsCol.width
anchors.horizontalCenter: parent.horizontalCenter
Column {
id: cameraSettingsCol
spacing: ScreenTools.defaultFontPixelHeight * 0.5
anchors.margins: ScreenTools.defaultFontPixelHeight
anchors.horizontalCenter: parent.horizontalCenter
//-------------------------------------------
//-- Camera Selector
Row {
spacing: ScreenTools.defaultFontPixelWidth
visible: _isCamera && _dynamicCameras.cameraLabels.length > 1
anchors.horizontalCenter: parent.horizontalCenter
QGCLabel {
text: qsTr("Camera Selector:")
width: _labelFieldWidth
anchors.verticalCenter: parent.verticalCenter
}
QGCComboBox {
model: _isCamera ? _dynamicCameras.cameraLabels : []
width: _editFieldWidth
onActivated: _dynamicCameras.currentCamera = index
currentIndex: _dynamicCameras ? _dynamicCameras.currentCamera : 0
}
}
Rectangle {
color: qgcPal.button
height: 1
width: cameraSettingsCol.width
visible: _isCamera && _dynamicCameras.cameraLabels.length > 1
}
//-------------------------------------------
//-- Stream Selector
Row {
spacing: ScreenTools.defaultFontPixelWidth
visible: _isCamera && _camera.streamLabels.length > 1
anchors.horizontalCenter: parent.horizontalCenter
QGCLabel {
text: qsTr("Stream Selector:")
width: _labelFieldWidth
anchors.verticalCenter: parent.verticalCenter
}
QGCComboBox {
model: _camera ? _camera.streamLabels : []
width: _editFieldWidth
onActivated: _camera.currentStream = index
currentIndex: _camera ? _camera.currentStream : 0
}
}
Rectangle {
color: qgcPal.button
height: 1
width: cameraSettingsCol.width
visible: _isCamera && _camera.streamLabels.length > 1
}
//-------------------------------------------
//-- Thermal Modes
Row {
spacing: ScreenTools.defaultFontPixelWidth
anchors.horizontalCenter: parent.horizontalCenter
visible: QGroundControl.videoManager.hasThermal
property var thermalModes: [qsTr("Off"), qsTr("Blend"), qsTr("Full"), qsTr("Picture In Picture")]
QGCLabel {
text: qsTr("Thermal View Mode")
width: _labelFieldWidth
anchors.verticalCenter: parent.verticalCenter
}
QGCComboBox {
width: _editFieldWidth
model: parent.thermalModes
currentIndex: _camera ? _camera.thermalMode : 0
onActivated: _camera.thermalMode = index
}
}
Rectangle {
color: qgcPal.button
height: 1
width: cameraSettingsCol.width
visible: QGroundControl.videoManager.hasThermal
}
//-------------------------------------------
//-- Thermal Video Opacity
Row {
spacing: ScreenTools.defaultFontPixelWidth
anchors.horizontalCenter: parent.horizontalCenter
visible: QGroundControl.videoManager.hasThermal && _camera.thermalMode === QGCCameraControl.THERMAL_BLEND
QGCLabel {
text: qsTr("Blend Opacity")
width: _labelFieldWidth
anchors.verticalCenter: parent.verticalCenter
}
Slider {
width: _editFieldWidth
to: 100
from: 0
value: _camera ? _camera.thermalOpacity : 0
live: true
onValueChanged: {
_camera.thermalOpacity = value
}
}
}
Rectangle {
color: qgcPal.button
height: 1
width: cameraSettingsCol.width
visible: QGroundControl.videoManager.hasThermal && _camera.thermalMode === QGCCameraControl.THERMAL_BLEND
}
//-------------------------------------------
//-- Settings from Camera Definition File
Repeater {
model: _camera ? _camera.activeSettings : []
Item {
width: repCol.width
height: repCol.height
Column {
id: repCol
spacing: ScreenTools.defaultFontPixelHeight * 0.5
property var _fact: _camera.getFact(modelData)
Row {
height: visible ? undefined : 0
spacing: ScreenTools.defaultFontPixelWidth
anchors.horizontalCenter: parent.horizontalCenter
property bool _isBool: parent._fact.typeIsBool
property bool _isCombo: !_isBool && parent._fact.enumStrings.length > 0
property bool _isSlider: parent._fact && !isNaN(parent._fact.increment)
property bool _isEdit: !_isBool && !_isSlider && parent._fact.enumStrings.length < 1
QGCLabel {
text: parent.parent._fact.shortDescription
width: _labelFieldWidth
anchors.verticalCenter: parent.verticalCenter
}
FactComboBox {
width: parent._isCombo ? _editFieldWidth : 0
fact: parent.parent._fact
indexModel: false
visible: parent._isCombo
anchors.verticalCenter: parent.verticalCenter
}
QGCButton {
visible: parent._isEdit
width: parent._isEdit ? _editFieldWidth : 0
text: parent.parent._fact.valueString
onClicked: {
showEditFact(parent.parent._fact)
}
}
QGCSlider {
width: parent._isSlider ? _editFieldWidth : 0
maximumValue: parent.parent._fact.max
minimumValue: parent.parent._fact.min
stepSize: parent.parent._fact.increment
visible: parent._isSlider
updateValueWhileDragging: false
anchors.verticalCenter: parent.verticalCenter
Component.onCompleted: {
value = parent.parent._fact.value
}
onValueChanged: {
parent.parent._fact.value = value
}
}
CustomOnOffSwitch {
width: parent._isBool ? _editFieldWidth : 0
checked: parent.parent._fact ? parent.parent._fact.value : false
onClicked: parent.parent._fact.value = checked ? 1 : 0
visible: parent._isBool
anchors.verticalCenter: parent.verticalCenter
}
}
Rectangle {
color: qgcPal.button
height: 1
width: cameraSettingsCol.width
}
}
}
}
//-------------------------------------------
//-- Time Lapse
Row {
spacing: ScreenTools.defaultFontPixelWidth
anchors.horizontalCenter: parent.horizontalCenter
visible: _cameraPhotoMode && !_noSdCard
property var photoModes: [qsTr("Single"), qsTr("Time Lapse")]
QGCLabel {
text: qsTr("Photo Mode")
width: _labelFieldWidth
anchors.verticalCenter: parent.verticalCenter
}
QGCComboBox {
width: _editFieldWidth
model: parent.photoModes
currentIndex: _camera ? _camera.photoMode : 0
onActivated: _camera.photoMode = index
}
}
Rectangle {
color: qgcPal.button
height: 1
width: cameraSettingsCol.width
visible: _cameraPhotoMode && !_noSdCard
}
//-------------------------------------------
//-- Time Lapse Interval
Row {
spacing: ScreenTools.defaultFontPixelWidth
anchors.horizontalCenter: parent.horizontalCenter
visible: _cameraPhotoMode && _camera.photoMode === QGCCameraControl.PHOTO_CAPTURE_TIMELAPSE && !_noSdCard
QGCLabel {
text: qsTr("Photo Interval (seconds)")
width: _labelFieldWidth
anchors.verticalCenter: parent.verticalCenter
}
QGCSlider {
width: _editFieldWidth
maximumValue: 60
minimumValue: _camera ? (_camera.isE90 ? 3 : 5) : 5
stepSize: 1
value: _camera ? _camera.photoLapse : 5
updateValueWhileDragging: true
anchors.verticalCenter: parent.verticalCenter
onValueChanged: {
if(_camera) {
_camera.photoLapse = value
}
}
}
}
Rectangle {
color: qgcPal.button
height: 1
width: cameraSettingsCol.width
visible: _cameraPhotoMode && _camera.photoMode === QGCCameraControl.PHOTO_CAPTURE_TIMELAPSE && !_noSdCard
}
//-------------------------------------------
//-- Screen Grid
Row {
spacing: ScreenTools.defaultFontPixelWidth
visible: _camera && !_camera.isThermal
anchors.horizontalCenter: parent.horizontalCenter
QGCLabel {
text: qsTr("Screen Grid")
width: _labelFieldWidth
anchors.verticalCenter: parent.verticalCenter
}
CustomOnOffSwitch {
checked: QGroundControl.settingsManager.videoSettings.gridLines.rawValue
width: _editFieldWidth
anchors.verticalCenter: parent.verticalCenter
onClicked: QGroundControl.settingsManager.videoSettings.gridLines.rawValue = checked
}
}
Rectangle {
color: qgcPal.button
height: 1
width: cameraSettingsCol.width
visible: _camera && !_camera.isThermal
}
//-------------------------------------------
//-- Video Fit
Row {
spacing: ScreenTools.defaultFontPixelWidth
visible: _camera
anchors.horizontalCenter: parent.horizontalCenter
QGCLabel {
text: qsTr("Video Screen Fit")
width: _labelFieldWidth
anchors.verticalCenter: parent.verticalCenter
}
FactComboBox {
width: _editFieldWidth
fact: QGroundControl.settingsManager.videoSettings.videoFit
indexModel: false
anchors.verticalCenter: parent.verticalCenter
}
}
Rectangle {
color: qgcPal.button
height: 1
width: cameraSettingsCol.width
visible: _camera && !_camera.isThermal
}
//-------------------------------------------
//-- Reset Camera
Row {
spacing: ScreenTools.defaultFontPixelWidth
anchors.horizontalCenter: parent.horizontalCenter
QGCLabel {
text: qsTr("Reset Camera Defaults")
width: _labelFieldWidth
anchors.verticalCenter: parent.verticalCenter
}
QGCButton {
text: qsTr("Reset")
onClicked: resetPrompt.open()
width: _editFieldWidth
enabled: !_recordingVideo
anchors.verticalCenter: parent.verticalCenter
MessageDialog {
id: resetPrompt
title: qsTr("Reset Camera to Factory Settings")
text: qsTr("Confirm resetting all settings?")
standardButtons: StandardButton.Yes | StandardButton.No
onNo: resetPrompt.close()
onYes: {
_camera.resetSettings()
QGroundControl.settingsManager.videoSettings.gridLines.rawValue = false
_camera.photoMode = QGCCameraControl.PHOTO_CAPTURE_SINGLE
_camera.photoLapse = 5.0
_camera.photoLapseCount = 0
resetPrompt.close()
}
}
}
}
Rectangle {
color: qgcPal.button
height: 1
width: cameraSettingsCol.width
}
}
}
Rectangle {
id: factEdit
visible: false
color: qgcPal.globalTheme === QGCPalette.Light ? Qt.rgba(1,1,1,0.5) : Qt.rgba(0,0,0,0.5)
anchors.fill: parent
property var fact: null
DeadMouseArea {
anchors.fill: parent
}
Rectangle {
width: factEditCol.width * 1.25
height: factEditCol.height * 1.25
color: qgcPal.globalTheme === QGCPalette.Light ? Qt.rgba(1,1,1,0.95) : Qt.rgba(0,0,0,0.75)
border.width: 1
border.color: qgcPal.globalTheme === QGCPalette.Light ? Qt.rgba(0,0,0,0.35) : Qt.rgba(1,1,1,0.35)
anchors.top: parent.top
anchors.topMargin: ScreenTools.defaultFontPixelHeight * 8
anchors.horizontalCenter: parent.horizontalCenter
Column {
id: factEditCol
spacing: ScreenTools.defaultFontPixelHeight
anchors.centerIn: parent
QGCLabel {
text: factEdit.fact ? factEdit.fact.shortDescription : ""
anchors.horizontalCenter: parent.horizontalCenter
}
FactTextField {
id: factEditor
width: _editFieldWidth
fact: factEdit.fact
anchors.horizontalCenter: parent.horizontalCenter
}
QGCButton {
text: qsTr("Close")
anchors.horizontalCenter: parent.horizontalCenter
onClicked: {
factEditor.completeEditing()
hideEditFact()
}
}
}
}
}
}
}
}
/****************************************************************************
*
* (c) 2009-2019 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.
*
* @file
* @author Gus Grubba <gus@auterion.com>
*/
import QtQuick 2.11
import QtQuick.Controls 2.4
import QtQuick.Layouts 1.11
import QtQuick.Dialogs 1.3
import QtPositioning 5.2
import QGroundControl 1.0
import QGroundControl.Controllers 1.0
import QGroundControl.Controls 1.0
import QGroundControl.FlightMap 1.0
import QGroundControl.MultiVehicleManager 1.0
import QGroundControl.Palette 1.0
import QGroundControl.ScreenTools 1.0
import QGroundControl.Vehicle 1.0
import QGroundControl.QGCPositionManager 1.0
import QGroundControl.Airspace 1.0
import CustomQuickInterface 1.0
import Custom.Widgets 1.0
Item {
anchors.fill: parent
visible: !QGroundControl.videoManager.fullScreen
readonly property string scaleState: "topMode"
readonly property string noGPS: qsTr("NO GPS")
readonly property real indicatorValueWidth: ScreenTools.defaultFontPixelWidth * 7
property real _indicatorDiameter: ScreenTools.defaultFontPixelWidth * 18
property real _indicatorsHeight: ScreenTools.defaultFontPixelHeight
property var _sepColor: qgcPal.globalTheme === QGCPalette.Light ? Qt.rgba(0,0,0,0.5) : Qt.rgba(1,1,1,0.5)
property color _indicatorsColor: qgcPal.text
property bool _communicationLost: activeVehicle ? activeVehicle.connectionLost : false
property bool _isVehicleGps: activeVehicle && activeVehicle.gps && activeVehicle.gps.count.rawValue > 1 && activeVehicle.gps.hdop.rawValue < 1.4
property var _dynamicCameras: activeVehicle ? activeVehicle.dynamicCameras : null
property bool _isCamera: _dynamicCameras ? _dynamicCameras.cameras.count > 0 : false
property int _curCameraIndex: _dynamicCameras ? _dynamicCameras.currentCamera : 0
property var _camera: _isCamera ? _dynamicCameras.cameras.get(_curCameraIndex) : null
property bool _cameraPresent: _camera && _camera.cameraMode !== QGCCameraControl.CAM_MODE_UNDEFINED
property var _flightPermit: QGroundControl.airmapSupported ? QGroundControl.airspaceManager.flightPlan.flightPermitStatus : null
property bool _airspaceIndicatorVisible: QGroundControl.airmapSupported && mainIsMap && _flightPermit && _flightPermit !== AirspaceFlightPlanProvider.PermitNone
property string _altitude: activeVehicle ? (isNaN(activeVehicle.altitudeRelative.value) ? "0.0" : activeVehicle.altitudeRelative.value.toFixed(1)) + ' ' + activeVehicle.altitudeRelative.units : "0.0"
property string _distanceStr: isNaN(_distance) ? "0" : _distance.toFixed(0) + ' ' + (activeVehicle ? activeVehicle.altitudeRelative.units : "")
property real _heading: activeVehicle ? activeVehicle.heading.rawValue : 0
property real _distance: 0.0
property string _messageTitle: ""
property string _messageText: ""
property bool _showAttitude: false
function secondsToHHMMSS(timeS) {
var sec_num = parseInt(timeS, 10);
var hours = Math.floor(sec_num / 3600);
var minutes = Math.floor((sec_num - (hours * 3600)) / 60);
var seconds = sec_num - (hours * 3600) - (minutes * 60);
if (hours < 10) {hours = "0"+hours;}
if (minutes < 10) {minutes = "0"+minutes;}
if (seconds < 10) {seconds = "0"+seconds;}
return hours+':'+minutes+':'+seconds;
}
Timer {
id: connectionTimer
interval: 5000
running: false;
repeat: false;
onTriggered: {
//-- Vehicle is gone
if(activeVehicle) {
//-- Let video stream close
QGroundControl.settingsManager.videoSettings.rtspTimeout.rawValue = 1
if(!activeVehicle.armed) {
//-- If it wasn't already set to auto-disconnect
if(!activeVehicle.autoDisconnect) {
//-- Vehicle is not armed. Close connection and tell user.
activeVehicle.disconnectInactiveVehicle()
connectionLostDisarmedDialog.open()
}
} else {
//-- Vehicle is armed. Show doom dialog.
connectionLostArmed.open()
}
}
}
}
Connections {
target: QGroundControl.qgcPositionManger
onGcsPositionChanged: {
if (activeVehicle && gcsPosition.latitude && Math.abs(gcsPosition.latitude) > 0.001 && gcsPosition.longitude && Math.abs(gcsPosition.longitude) > 0.001) {
var gcs = QtPositioning.coordinate(gcsPosition.latitude, gcsPosition.longitude)
var veh = activeVehicle.coordinate;
_distance = QGroundControl.metersToAppSettingsDistanceUnits(gcs.distanceTo(veh));
//-- Ignore absurd values
if(_distance > 99999)
_distance = 0;
if(_distance < 0)
_distance = 0;
} else {
_distance = 0;
}
}
}
Connections {
target: QGroundControl.multiVehicleManager.activeVehicle
onConnectionLostChanged: {
if(!_communicationLost) {
//-- Communication regained
connectionTimer.stop();
if(connectionLostArmed.visible) {
connectionLostArmed.close()
}
//-- Reset stream timeout
QGroundControl.settingsManager.videoSettings.rtspTimeout.rawValue = 60
} else {
if(activeVehicle && !activeVehicle.autoDisconnect) {
//-- Communication lost
connectionTimer.start();
}
}
}
}
Connections {
target: QGroundControl.multiVehicleManager
onVehicleAdded: {
//-- Dismiss comm lost dialog if open
connectionLostDisarmedDialog.close()
}
}
MessageDialog {
id: connectionLostDisarmedDialog
title: qsTr("Communication Lost")
text: qsTr("Connection to vehicle has been lost and closed.")
standardButtons: StandardButton.Ok
onAccepted: {
connectionLostDisarmedDialog.close()
}
}
//-- Heading Indicator
Rectangle {
id: compassBar
height: ScreenTools.defaultFontPixelHeight * 1.5
width: ScreenTools.defaultFontPixelWidth * 50
color: "#DEDEDE"
radius: 2
clip: true
anchors.top: parent.top
anchors.topMargin: ScreenTools.defaultFontPixelHeight * (_airspaceIndicatorVisible ? 3 : 2)
anchors.horizontalCenter: parent.horizontalCenter
visible: !mainIsMap
Repeater {
model: 720
visible: !mainIsMap
QGCLabel {
function _normalize(degrees) {
var a = degrees % 360
if (a < 0) a += 360
return a
}
property int _startAngle: modelData + 180 + _heading
property int _angle: _normalize(_startAngle)
anchors.verticalCenter: parent.verticalCenter
x: visible ? ((modelData * (compassBar.width / 360)) - (width * 0.5)) : 0
visible: _angle % 45 == 0
color: "#75505565"
font.pointSize: ScreenTools.smallFontPointSize
text: {
switch(_angle) {
case 0: return "N"
case 45: return "NE"
case 90: return "E"
case 135: return "SE"
case 180: return "S"
case 225: return "SW"
case 270: return "W"
case 315: return "NW"
}
return ""
}
}
}
}
Rectangle {
id: headingIndicator
height: ScreenTools.defaultFontPixelHeight
width: ScreenTools.defaultFontPixelWidth * 4
color: qgcPal.windowShadeDark
visible: !mainIsMap
anchors.bottom: compassBar.top
anchors.bottomMargin: ScreenTools.defaultFontPixelHeight * -0.1
anchors.horizontalCenter: parent.horizontalCenter
QGCLabel {
text: _heading
color: qgcPal.text
font.pointSize: ScreenTools.smallFontPointSize
anchors.centerIn: parent
}
}
Image {
height: _indicatorsHeight
width: height
source: "/custom/img/compass_pointer.svg"
visible: !mainIsMap
fillMode: Image.PreserveAspectFit
sourceSize.height: height
anchors.top: compassBar.bottom
anchors.topMargin: ScreenTools.defaultFontPixelHeight * -0.5
anchors.horizontalCenter: parent.horizontalCenter
}
//-- Camera Control
Loader {
id: camControlLoader
visible: !mainIsMap && _cameraPresent && _camera.paramComplete
source: visible ? "/custom/CustomCameraControl.qml" : ""
anchors.right: parent.right
anchors.rightMargin: ScreenTools.defaultFontPixelWidth
anchors.top: parent.top
anchors.topMargin: ScreenTools.defaultFontPixelHeight * 4
}
//-- Map Scale
MapScale {
id: mapScale
anchors.left: parent.left
anchors.top: parent.top
anchors.topMargin: ScreenTools.defaultFontPixelHeight * 0.5
anchors.leftMargin: ScreenTools.defaultFontPixelWidth * 16
mapControl: mainWindow.flightDisplayMap
visible: rootBackground.visible && mainIsMap
}
//-- Vehicle Indicator
Rectangle {
id: vehicleIndicator
color: qgcPal.windowShade
width: vehicleStatusGrid.width + (ScreenTools.defaultFontPixelWidth * 3)
height: vehicleStatusGrid.height + (ScreenTools.defaultFontPixelHeight * 1.5)
radius: 2
anchors.bottom: multiVehicleSelector.visible ? multiVehicleSelector.top : parent.bottom
anchors.bottomMargin: ScreenTools.defaultFontPixelWidth
anchors.right: attitudeIndicator.visible ? attitudeIndicator.left : parent.right
anchors.rightMargin: attitudeIndicator.visible ? -ScreenTools.defaultFontPixelWidth : ScreenTools.defaultFontPixelWidth
GridLayout {
id: vehicleStatusGrid
columnSpacing: ScreenTools.defaultFontPixelWidth * 1.5
rowSpacing: ScreenTools.defaultFontPixelHeight * 0.5
columns: 7
anchors.centerIn: parent
//-- Chronometer
QGCColoredImage {
height: _indicatorsHeight
width: height
source: "/custom/img/chronometer.svg"
fillMode: Image.PreserveAspectFit
sourceSize.height: height
Layout.alignment: Qt.AlignVCenter | Qt.AlignHCenter
color: qgcPal.text
}
QGCLabel {
text: {
if(activeVehicle)
return secondsToHHMMSS(activeVehicle.getFact("flightTime").value)
return "00:00:00"
}
color: _indicatorsColor
font.pointSize: ScreenTools.smallFontPointSize
Layout.fillWidth: true
Layout.minimumWidth: indicatorValueWidth
horizontalAlignment: Text.AlignRight
}
//-- Ground Speed
QGCColoredImage {
height: _indicatorsHeight
width: height
source: "/custom/img/horizontal_speed.svg"
fillMode: Image.PreserveAspectFit
sourceSize.height: height
Layout.alignment: Qt.AlignVCenter | Qt.AlignHCenter
color: qgcPal.text
}
QGCLabel {
text: activeVehicle ? activeVehicle.groundSpeed.value.toFixed(1) + ' ' + activeVehicle.groundSpeed.units : "0.0"
color: _indicatorsColor
font.pointSize: ScreenTools.smallFontPointSize
Layout.fillWidth: true
Layout.minimumWidth: indicatorValueWidth
horizontalAlignment: Text.AlignRight
}
//-- Vertical Speed
QGCColoredImage {
height: _indicatorsHeight
width: height
source: "/custom/img/vertical_speed.svg"
fillMode: Image.PreserveAspectFit
sourceSize.height: height
Layout.alignment: Qt.AlignVCenter | Qt.AlignHCenter
color: qgcPal.text
}
QGCLabel {
text: activeVehicle ? activeVehicle.climbRate.value.toFixed(1) + ' ' + activeVehicle.climbRate.units : "0.0"
color: _indicatorsColor
font.pointSize: ScreenTools.smallFontPointSize
Layout.fillWidth: true
Layout.minimumWidth: indicatorValueWidth
horizontalAlignment: Text.AlignRight
}
//-- Compass
Item {
Layout.rowSpan: 2
Layout.minimumWidth: mainIsMap ? parent.height * 1.25 : 0
Layout.fillHeight: true
Layout.fillWidth: true
//-- Large circle
Rectangle {
height: mainIsMap ? parent.height : 0
width: mainIsMap ? height : 0
radius: height * 0.5
border.color: qgcPal.text
border.width: 1
color: Qt.rgba(0,0,0,0)
anchors.centerIn: parent
visible: mainIsMap
}
//-- North Label
Rectangle {
height: mainIsMap ? ScreenTools.defaultFontPixelHeight * 0.75 : 0
width: mainIsMap ? ScreenTools.defaultFontPixelWidth * 2 : 0
radius: ScreenTools.defaultFontPixelWidth * 0.25
color: qgcPal.windowShade
visible: mainIsMap
anchors.top: parent.top
anchors.topMargin: ScreenTools.defaultFontPixelHeight * -0.25
anchors.horizontalCenter: parent.horizontalCenter
QGCLabel {
text: "N"
color: qgcPal.text
font.pointSize: ScreenTools.smallFontPointSize
anchors.centerIn: parent
}
}
//-- Needle
Image {
id: compassNeedle
anchors.centerIn: parent
height: mainIsMap ? parent.height * 0.75 : 0
width: height
source: "/custom/img/compass_needle.svg"
fillMode: Image.PreserveAspectFit
visible: mainIsMap
sourceSize.height: height
transform: [
Rotation {
origin.x: compassNeedle.width / 2
origin.y: compassNeedle.height / 2
angle: _heading
}]
}
//-- Heading
Rectangle {
height: mainIsMap ? ScreenTools.defaultFontPixelHeight * 0.75 : 0
width: mainIsMap ? ScreenTools.defaultFontPixelWidth * 3.5 : 0
radius: ScreenTools.defaultFontPixelWidth * 0.25
color: qgcPal.windowShade
visible: mainIsMap
anchors.bottom: parent.bottom
anchors.bottomMargin: ScreenTools.defaultFontPixelHeight * -0.25
anchors.horizontalCenter: parent.horizontalCenter
QGCLabel {
text: _heading
color: qgcPal.text
font.pointSize: ScreenTools.smallFontPointSize
anchors.centerIn: parent
}
}
}
//-- Second Row
//-- Odometer
QGCColoredImage {
height: _indicatorsHeight
width: height
source: "/custom/img/odometer.svg"
fillMode: Image.PreserveAspectFit
sourceSize.height: height
Layout.alignment: Qt.AlignVCenter | Qt.AlignHCenter
color: qgcPal.text
}
QGCLabel {
text: activeVehicle ? ('00000' + activeVehicle.flightDistance.value.toFixed(0)).slice(-5) + ' ' + activeVehicle.flightDistance.units : "00000"
color: _indicatorsColor
font.pointSize: ScreenTools.smallFontPointSize
Layout.fillWidth: true
Layout.minimumWidth: indicatorValueWidth
horizontalAlignment: Text.AlignRight
}
//-- Altitude
QGCColoredImage {
height: _indicatorsHeight
width: height
source: "/custom/img/altitude.svg"
fillMode: Image.PreserveAspectFit
sourceSize.height: height
Layout.alignment: Qt.AlignVCenter | Qt.AlignHCenter
color: qgcPal.text
}
QGCLabel {
text: _altitude
color: _indicatorsColor
font.pointSize: ScreenTools.smallFontPointSize
Layout.fillWidth: true
Layout.minimumWidth: indicatorValueWidth
horizontalAlignment: Text.AlignRight
}
//-- Distance
QGCColoredImage {
height: _indicatorsHeight
width: height
source: "/custom/img/distance.svg"
fillMode: Image.PreserveAspectFit
sourceSize.height: height
Layout.alignment: Qt.AlignVCenter | Qt.AlignHCenter
color: qgcPal.text
}
QGCLabel {
text: _distance ? _distanceStr : noGPS
color: _distance ? _indicatorsColor : qgcPal.colorOrange
font.pointSize: ScreenTools.smallFontPointSize
Layout.fillWidth: true
Layout.minimumWidth: indicatorValueWidth
horizontalAlignment: Text.AlignRight
}
}
MouseArea {
anchors.fill: parent
onDoubleClicked: _showAttitude = !_showAttitude
}
}
//-- Attitude Indicator
Rectangle {
color: qgcPal.windowShade
width: attitudeIndicator.width * 0.5
height: vehicleIndicator.height
visible: _showAttitude
anchors.top: vehicleIndicator.top
anchors.left: vehicleIndicator.right
}
Rectangle {
id: attitudeIndicator
anchors.bottom: vehicleIndicator.bottom
anchors.bottomMargin: ScreenTools.defaultFontPixelWidth * -0.5
anchors.right: parent.right
anchors.rightMargin: ScreenTools.defaultFontPixelWidth
height: ScreenTools.defaultFontPixelHeight * 6
width: height
radius: height * 0.5
color: qgcPal.windowShade
visible: _showAttitude
CustomAttitudeWidget {
size: parent.height * 0.95
vehicle: activeVehicle
showHeading: false
anchors.centerIn: parent
}
}
//-- Multi Vehicle Selector
Row {
id: multiVehicleSelector
spacing: ScreenTools.defaultFontPixelWidth
anchors.bottom: parent.bottom
anchors.bottomMargin: ScreenTools.defaultFontPixelWidth
anchors.right: parent.right
anchors.rightMargin: ScreenTools.defaultFontPixelWidth
visible: QGroundControl.multiVehicleManager.vehicles.count > 1
Repeater {
model: QGroundControl.multiVehicleManager.vehicles.count
CustomVehicleButton {
property var _vehicle: QGroundControl.multiVehicleManager.vehicles.get(modelData)
vehicle: _vehicle
checked: (_vehicle && activeVehicle) ? _vehicle.id === activeVehicle.id : false
}
}
}
//-- Connection Lost While Armed
Popup {
id: connectionLostArmed
width: mainWindow.width * 0.666
height: connectionLostArmedCol.height * 1.5
modal: true
focus: true
parent: Overlay.overlay
x: Math.round((mainWindow.width - width) * 0.5)
y: Math.round((mainWindow.height - height) * 0.5)
closePolicy: Popup.CloseOnEscape | Popup.CloseOnPressOutside
background: Rectangle {
anchors.fill: parent
color: qgcPal.alertBackground
border.color: qgcPal.alertBorder
radius: ScreenTools.defaultFontPixelWidth
}
Column {
id: connectionLostArmedCol
spacing: ScreenTools.defaultFontPixelHeight * 3
anchors.margins: ScreenTools.defaultFontPixelHeight
anchors.centerIn: parent
QGCLabel {
text: qsTr("Communication Lost")
font.family: ScreenTools.demiboldFontFamily
font.pointSize: ScreenTools.largeFontPointSize
color: qgcPal.alertText
anchors.horizontalCenter: parent.horizontalCenter
}
QGCLabel {
text: qsTr("Warning: Connection to vehicle lost.")
color: qgcPal.alertText
font.family: ScreenTools.demiboldFontFamily
font.pointSize: ScreenTools.mediumFontPointSize
anchors.horizontalCenter: parent.horizontalCenter
}
QGCLabel {
text: qsTr("The vehicle will automatically cancel the flight and return to land. Ensure a clear line of sight between transmitter and vehicle. Ensure the takeoff location is clear.")
width: connectionLostArmed.width * 0.75
wrapMode: Text.WordWrap
color: qgcPal.alertText
font.family: ScreenTools.demiboldFontFamily
font.pointSize: ScreenTools.mediumFontPointSize
anchors.horizontalCenter: parent.horizontalCenter
}
}
}
}
<svg width="72" height="72" viewBox="0 0 72 72" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M58 63H46.9V39.8H25.1V63H14V9H25.1V30.9H46.8V9H57.9L58 63Z" fill="white"/>
</svg>
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 23.0.4, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 288 36" style="enable-background:new 0 0 288 36;" xml:space="preserve">
<style type="text/css">
.st0{fill:none;}
.st1{fill:none;stroke:#0A94FF;stroke-width:4;stroke-miterlimit:10;}
.st2{fill:none;stroke:#0A94FF;stroke-width:4;stroke-linecap:round;stroke-miterlimit:10;}
</style>
<rect class="st0" width="288" height="36"/>
<line class="st1" x1="0" y1="18" x2="72" y2="18"/>
<line class="st1" x1="288" y1="18" x2="216" y2="18"/>
<polyline class="st2" points="194.5,31.1 144,18 93.5,31.1 "/>
</svg>
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 23.0.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 288 288" style="enable-background:new 0 0 288 288;" xml:space="preserve">
<style type="text/css">
.st0{fill:none;stroke:#FFFFFF;stroke-width:4;}
.st1{fill:none;}
</style>
<g>
<line class="st0" x1="144" y1="45.8" x2="144" y2="18.8"/>
<line class="st0" x1="171.7" y1="40.5" x2="176.4" y2="23.1"/>
<line class="st0" x1="197.6" y1="51.2" x2="206.6" y2="35.6"/>
<line class="st0" x1="219.8" y1="68.2" x2="232.5" y2="55.5"/>
<line class="st0" x1="236.8" y1="90.4" x2="252.4" y2="81.4"/>
<line class="st0" x1="116.3" y1="40.4" x2="111.6" y2="23"/>
<line class="st0" x1="90.4" y1="51.1" x2="81.4" y2="35.5"/>
<line class="st0" x1="68.2" y1="68.2" x2="55.5" y2="55.4"/>
<line class="st0" x1="51.1" y1="90.3" x2="35.6" y2="81.3"/>
<rect x="135" y="270" class="st1" width="18" height="18"/>
<g id="Layer_3">
</g>
</g>
</svg>
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 23.0.3, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.1" id="Layer_3" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 288 288" style="enable-background:new 0 0 288 288;" xml:space="preserve">
<style type="text/css">
.st0{fill-rule:evenodd;clip-rule:evenodd;fill:#231F20;}
</style>
<path id="pointer_2_" class="st0" d="M276.5,0L144,288L11.5,0"/>
</svg>
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 23.0.4, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.1"
id="Layer_1" xmlns:cc="http://creativecommons.org/ns#" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="0 0 288 288"
style="enable-background:new 0 0 288 288;" xml:space="preserve">
<g transform="translate(0,-952.36218)">
<path d="M102.3,978.9c-3.2,0.1-5.5,2.1-6.7,4.1l-13.1,26.2H30.3c-16.7,0-30.3,13.7-30.3,30.3v144c0,16.7,13.7,30.3,30.3,30.3h227.4
c16.7,0,30.3-13.7,30.3-30.3v-144c0-16.7-13.7-30.3-30.3-30.3h-52.1L192.4,983c-1.3-2.5-4-4.1-6.7-4.1H102.3z M106.9,994h74.1
l13,26.1c1.2,2.5,3.9,4.2,6.7,4.3h56.8c8.5,0,15.2,6.6,15.2,15.2v144c0,8.5-6.6,15.2-15.2,15.2H30.3c-8.5,0-15.2-6.6-15.2-15.2
v-144c0-8.5,6.6-15.2,15.2-15.2h56.8c2.8,0,5.5-1.7,6.7-4.3L106.9,994z M144,1047.1c-35.5,0-64.4,28.9-64.4,64.4
c0,35.5,28.9,64.4,64.4,64.4c35.5,0,64.4-28.9,64.4-64.4C208.4,1076,179.5,1047.1,144,1047.1z M144,1062.3
c27.3,0,49.3,22,49.3,49.3c0,27.3-22,49.3-49.3,49.3c-27.3,0-49.3-22-49.3-49.3C94.7,1084.2,116.7,1062.3,144,1062.3z"/>
</g>
</svg>
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 23.0.4, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 72 72" style="enable-background:new 0 0 72 72;" xml:space="preserve">
<style type="text/css">
.st0{fill-rule:evenodd;clip-rule:evenodd;}
</style>
<path class="st0" d="M63.6,65.5h-5.5V40h5.5V65.5z M18.6,31.2H3.4c-4.5,0-4.5-9.1,0-9.1h15.2C23.2,22.1,23.2,31.2,18.6,31.2z
M8.2,65.5h5.7V35H8.2V65.5z M8.2,18.3V6.5h5.7v11.8H8.2z M28.4,51h15.2c4.5,0,4.5-9.3,0-9.3H28.4C23.9,41.7,23.9,51,28.4,51z
M38.6,65.5h-5.5V54.6h5.5V65.5z M33.2,6.5V38h5.5V6.4L33.2,6.5L33.2,6.5z M68.4,36.2h-15c-4.8,0-4.8-9.1,0-9.1h15
C73.2,27.1,73.2,36.2,68.4,36.2z M58.2,6.5v16.8h5.4V6.5H58.2z"/>
</svg>
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 23.0.4, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 288 288" style="enable-background:new 0 0 288 288;" xml:space="preserve">
<g>
<path d="M21.2,215.3h168.7c11.7,0,21.2-9.5,21.2-21.2V93.9c0-11.7-9.5-21.2-21.2-21.2H21.2C9.5,72.7,0,82.2,0,93.9v100.2
C0,205.8,9.5,215.3,21.2,215.3z"/>
<polygon points="225.2,165.5 288,206.1 288,81.9 225.2,122.5 "/>
</g>
</svg>
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 23.0.3, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 72 72" style="enable-background:new 0 0 72 72;" xml:space="preserve">
<style type="text/css">
.st0{fill:#FFFFFF;}
</style>
<path class="st0" d="M36,5.3c4.2,0,8.2,0.8,12,2.4c3.7,1.5,6.9,3.8,9.8,6.6c2.8,2.8,5,6.1,6.6,9.8c1.6,3.8,2.4,7.8,2.4,12
c0,4.1-0.8,8.2-2.4,12c-1.5,3.7-3.8,6.9-6.6,9.8c-2.8,2.8-6.1,5-9.8,6.6c-3.8,1.6-7.8,2.4-12,2.4c-4.2,0-8.2-0.8-12-2.4
c-3.7-1.5-6.9-3.8-9.8-6.6c-2.8-2.8-5-6.1-6.6-9.8c-1.6-3.8-2.4-7.8-2.4-12c0-4.1,0.8-8.2,2.4-12c1.5-3.7,3.8-6.9,6.6-9.8
c2.8-2.8,6.1-5,9.8-6.6C27.8,6.1,31.9,5.3,36,5.3z M36,0C16.1,0,0,16.1,0,36s16.1,36,36,36s36-16.1,36-36S55.9,0,36,0z"/>
<path class="st0" d="M45.2,47.9c-0.7,0-1.4-0.3-1.9-0.8l-10-10V13.5c0-1.5,1.2-2.6,2.6-2.6c1.5,0,2.6,1.2,2.6,2.6v21.3l8.4,8.4
c1,1,1,2.7,0,3.7C46.6,47.6,45.9,47.9,45.2,47.9L45.2,47.9z"/>
</svg>
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 23.0.4, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 288 288" style="enable-background:new 0 0 288 288;" xml:space="preserve">
<style type="text/css">
.st0{fill:#FFFFFF;}
.st1{fill:#236A00;}
.st2{fill:#00B423;}
</style>
<g>
<path class="st0" d="M205.2,206.7L144,173.4V81.3"/>
<path class="st0" d="M144,81.3v92.2l-61.2,33.3"/>
</g>
<path class="st1" d="M198,199.3L144,170V88.7"/>
<path class="st2" d="M144,88.7V170l-54,29.4"/>
</svg>
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 23.0.3, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 72 72" style="enable-background:new 0 0 72 72;" xml:space="preserve">
<style type="text/css">
.st0{fill-rule:evenodd;clip-rule:evenodd;fill:#0B1629;}
</style>
<path class="st0" d="M5.3,58c-5.6,0-7-3.6-3-8.2l30.1-34.1c2-2.3,5.3-2.2,7.3,0l30.1,34.1c4,4.5,2.6,8.2-3,8.2H5.3z"/>
</svg>
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 23.0.4, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 72 72" style="enable-background:new 0 0 72 72;" xml:space="preserve">
<style type="text/css">
.st0{fill:#FFFFFF;}
.st1{fill-rule:evenodd;clip-rule:evenodd;fill:#FFFFFF;}
</style>
<path class="st0" d="M7.7,9v53.9V63h17.2c4.9,0,9.2-1.1,13.1-3.3c3.9-2.1,7-5.2,9-9.1c0.8-1.4,1.5-3,2-4.6H37.2
c-0.6,1.4-1.3,2.6-2.2,3.7c-2.4,2.9-5.9,4.3-10.4,4.3h-5.5V18h5.6c4.6,0,8,1.5,10.4,4.3c1.3,1.6,2.3,3.6,2.9,6.1h11.6
c-0.5-2.5-1.4-4.9-2.7-7.1c-2.1-3.9-5.1-7-9-9.1C34.2,10,29.8,9,24.9,9H7.7z"/>
<path class="st1" d="M47.8,35l-5.7,1.2c-1.2,0.3-1.2,2,0,2.3l5.7,1.2l4.7,2.1l0,3.5l6.4-4l4.8-3c0.7-0.4,0.7-1.5,0-1.9l-4.9-3
l-6.4-4l0,3.5L47.8,35z"/>
</svg>
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 23.0.4, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 72 72" style="enable-background:new 0 0 72 72;" xml:space="preserve">
<style type="text/css">
.st0{fill-rule:evenodd;clip-rule:evenodd;fill:#FFFFFF;}
.st1{fill:#FFFFFF;}
</style>
<path class="st0" d="M18.6,31.7l-7.3,1.9c-2.7,0.7-2.6,4.5,0,5.1l7.4,1.8l16,3.9l0,6.6l10.2-7.5l7.9-5.9c1.1-0.8,1.1-2.5,0-3.3
l-7.9-5.8L34.6,21l0,6.6L18.6,31.7z"/>
<rect x="64.5" y="14" class="st1" width="5.5" height="44.3"/>
</svg>
<svg width="16" height="13" viewBox="0 0 16 13" fill="none" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd" d="M15.9992 1.15794C15.9992 0.795041 15.718 0.500817 15.3711 0.500817L0.628867 0.5C0.281225 0.5 0 0.794224 0 1.15793V10.0903C0 10.4532 0.281225 10.7474 0.628867 10.7474H5.14583C5.27473 10.7474 5.39816 10.8006 5.48957 10.8946L6.41842 11.8525C6.52311 11.9603 6.66295 12.02 6.8098 12.02H8.37926V11.5607C8.37926 11.4806 8.44176 11.4144 8.5191 11.4144H9.74715C9.7784 11.4144 9.80809 11.4258 9.83387 11.4454L10.4917 11.9881C10.5167 12.0094 10.5471 12.0192 10.5784 12.0192H15.3719C15.7188 12.0192 16 11.7258 16 11.3621L15.9992 1.15794ZM4.32879 9.68253C4.32879 9.75118 4.27489 9.80758 4.20927 9.80758H1.31722C1.25082 9.80758 1.19769 9.75118 1.19769 9.68253V9.0352C1.19769 8.96655 1.2516 8.91015 1.31722 8.91015H4.21007C4.27569 8.91015 4.32959 8.96655 4.32959 9.0352L4.32879 9.68253ZM4.20927 8.70339C4.27489 8.70339 4.32879 8.64618 4.32879 8.57752L4.32959 7.92938C4.32959 7.85991 4.27569 7.80351 4.21007 7.80351H1.31722C1.2516 7.80351 1.19769 7.85991 1.19769 7.92938V8.57671C1.19769 8.64618 1.25082 8.70257 1.31722 8.70257L4.20927 8.70339ZM4.32879 7.47087C4.32879 7.53952 4.27489 7.59592 4.20927 7.59592H1.31722C1.25082 7.59592 1.19769 7.53952 1.19769 7.47087V6.82354C1.19769 6.75489 1.2516 6.69767 1.31722 6.69767H4.21007C4.27569 6.69767 4.32959 6.75407 4.32959 6.82354L4.32879 7.47087ZM4.20927 6.49089C4.27489 6.49089 4.32879 6.4345 4.32879 6.36503V5.7177C4.32879 5.64904 4.27489 5.59265 4.20927 5.59265H0.957038C0.891415 5.59265 0.837512 5.64823 0.837512 5.7177V6.36503C0.837512 6.4345 0.891417 6.49089 0.957038 6.49089H4.20927ZM4.32879 5.25837C4.32879 5.32784 4.27489 5.38342 4.20927 5.38342L1.31722 5.38424C1.25082 5.38424 1.19769 5.32784 1.19769 5.25919V4.61186C1.19769 4.54239 1.2516 4.48681 1.31722 4.48681H4.21007C4.27569 4.48681 4.32959 4.5432 4.32959 4.61186L4.32879 5.25837ZM4.20927 4.27758C4.27489 4.27758 4.32879 4.22118 4.32879 4.15253V3.5052C4.32879 3.43655 4.27489 3.38015 4.20927 3.38015H0.957038C0.891415 3.38015 0.837512 3.43573 0.837512 3.5052V4.15253C0.837512 4.22118 0.891417 4.27758 0.957038 4.27758H4.20927ZM4.32879 3.04587C4.32879 3.11534 4.27489 3.17092 4.20927 3.17092L1.31722 3.17174C1.25082 3.17174 1.19769 3.11534 1.19769 3.04669V2.39936C1.19769 2.33071 1.2516 2.27431 1.31722 2.27431H4.21007C4.27569 2.27431 4.32959 2.33071 4.32959 2.39936L4.32879 3.04587ZM4.20927 2.06508C4.27489 2.06508 4.32879 2.00868 4.32879 1.94003L4.32959 1.2927C4.32959 1.22323 4.27569 1.16684 4.21007 1.16684H1.31722C1.2516 1.16684 1.19769 1.22323 1.19769 1.2927V1.94003C1.19769 2.00869 1.25082 2.06508 1.31722 2.06508H4.20927Z" fill="white"/>
</svg>
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 23.0.4, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 72 72" style="enable-background:new 0 0 72 72;" xml:space="preserve">
<style type="text/css">
.st0{fill:#FFFFFF;}
.st1{fill-rule:evenodd;clip-rule:evenodd;fill:#FFFFFF;}
.st2{font-family:'Menlo-Regular';}
.st3{font-size:46px;}
</style>
<path class="st0" d="M47,15.9c-0.6,0-1.2,0.3-1.6,0.7c-0.4,0.4-0.7,1-0.6,1.6c0,4.6,1.3,8.8,4.1,11.5c1.4,1.4,3.1,2.2,5,2.2
c1.8,0,3.6-0.8,5-2.1c2.8-2.7,4.1-6.9,4.1-11.5l0,0c0-1.3-1-2.3-2.3-2.3s-2.3,1-2.3,2.3c0,3.6-1.3,6.8-2.7,8.2
c-0.7,0.7-1.3,0.9-1.8,0.9s-1.1-0.2-1.8-0.9c-1.4-1.4-2.7-4.7-2.7-8.3l0,0c0-0.6-0.2-1.2-0.7-1.7C48.2,16.1,47.6,15.9,47,15.9
L47,15.9z"/>
<path class="st0" d="M2,14.8c-1.2,0.1-2.1,1.1-2,2.3v37.8c0,1.3,1,2.3,2.3,2.3h67.4c1.3,0,2.3-1,2.3-2.3V17.1c0-1.3-1-2.3-2.3-2.3H2
z M2.1,16.9l67.6,0.2v37.8H2.3L2.1,16.9z"/>
<path class="st0" d="M53.9,36.3c-2.3,0-4.5,1.3-6.1,3.3c-3.1,4.1-3.9,10.2-2.4,15.7l0,0c0.3,1.2,1.6,1.9,2.8,1.6
c1.2-0.3,1.9-1.6,1.6-2.8c-1.1-4.1-0.2-9.3,1.6-11.7c0.9-1.2,1.8-1.6,2.4-1.5c0.7,0,1.5,0.3,2.4,1.6c1.8,2.5,2.7,7.7,1.5,11.7l0,0
c-0.2,0.6-0.2,1.3,0.1,1.8c0.3,0.6,0.8,1,1.4,1.2c0.6,0.2,1.3,0.1,1.8-0.3c0.5-0.3,0.9-0.9,1-1.5c1.5-5.4,0.8-11.6-2.3-15.7
C58.3,37.6,56.2,36.3,53.9,36.3L53.9,36.3z"/>
<path class="st1" d="M35.6,16.6v38.3h4.6V16.6H35.6z"/>
<text transform="matrix(1 0 0 1 5.3209 52.9379)" class="st0 st2 st3">1</text>
</svg>
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 23.0.4, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 72 72" style="enable-background:new 0 0 72 72;" xml:space="preserve">
<style type="text/css">
.st0{fill-rule:evenodd;clip-rule:evenodd;fill:#FFFFFF;}
.st1{fill:#FFFFFF;}
</style>
<path class="st0" d="M31.7,53.4l3.4,13.3c0.3,1.1,1.9,1.1,2.1,0l3.2-13.4l3.9-16l6.6,0l-7.5-10.2l-5.1-6.9c-1.2-1.6-3.6-1.6-4.8,0
l-5.1,6.9L21,37.4l6.6,0L31.7,53.4z"/>
<rect x="13.9" y="2.2" class="st1" width="44.3" height="5.5"/>
</svg>
/****************************************************************************
*
* (c) 2009-2019 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.
*
* @file
* @author Gus Grubba <gus@auterion.com>
*/
import QtQuick 2.11
import QtQuick.Controls 1.2
import QGroundControl 1.0
import QGroundControl.MultiVehicleManager 1.0
import QGroundControl.Controls 1.0
import QGroundControl.Palette 1.0
import QGroundControl.ScreenTools 1.0
//-------------------------------------------------------------------------
//-- Armed Indicator
Rectangle {
anchors.top: parent.top
anchors.bottom: parent.bottom
width: labelRow.width + (ScreenTools.defaultFontPixelWidth * 6)
color: qgcPal.windowShade
property bool _armed: activeVehicle ? activeVehicle.armed : false
Row {
id: labelRow
spacing: ScreenTools.defaultFontPixelWidth
anchors.centerIn: parent
QGCLabel {
id: labelText
text: _armed ? qsTr("Armed") : qsTr("Disarmed")
color: qgcPal.text
font.pointSize: ScreenTools.defaultFontPointSize
anchors.verticalCenter: parent.verticalCenter
}
Rectangle {
height: ScreenTools.defaultFontPixelHeight * 0.5
width: height
radius: height * 0.5
color: _armed ? qgcPal.colorGreen : qgcPal.colorRed
border.color: qgcPal.window
border.width: 1
anchors.verticalCenter: parent.verticalCenter
}
}
QGCMouseArea {
fillItem: parent
onClicked: _armed ? mainWindow.disarmVehicle() : mainWindow.armVehicle()
}
}
/****************************************************************************
*
* (c) 2009-2019 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.
*
* @file
* @author Gus Grubba <gus@auterion.com>
*/
import QtQuick 2.11
import QtQuick.Controls 1.4
import QtQuick.Layouts 1.11
import QGroundControl 1.0
import QGroundControl.Controls 1.0
import QGroundControl.MultiVehicleManager 1.0
import QGroundControl.ScreenTools 1.0
import QGroundControl.Palette 1.0
//-------------------------------------------------------------------------
//-- Battery Indicator
Item {
id: _root
width: batteryIndicatorRow.width
anchors.top: parent.top
anchors.bottom: parent.bottom
property var battery1: activeVehicle ? activeVehicle.battery : null
property var battery2: activeVehicle ? activeVehicle.battery2 : null
property bool hasSecondBattery: battery2 && battery2.voltage.value !== -1
function lowestBattery() {
if(activeVehicle) {
if(hasSecondBattery) {
if(activeVehicle.battery2.percentRemaining.value < activeVehicle.battery.percentRemaining.value) {
return activeVehicle.battery2
}
}
return activeVehicle.battery
}
return null
}
function getBatteryColor(battery) {
if(battery) {
if(battery.percentRemaining.value > 75) {
return qgcPal.text
}
if(battery.percentRemaining.value > 50) {
return qgcPal.colorOrange
}
if(battery.percentRemaining.value > 0.1) {
return qgcPal.colorRed
}
}
return qgcPal.colorGrey
}
function getBatteryPercentageText(battery) {
if(battery) {
if(battery.percentRemaining.value > 98.9) {
return "100%"
}
if(battery.percentRemaining.value > 0.1) {
return battery.percentRemaining.valueString + battery.percentRemaining.units
}
if(battery.voltage.value >= 0) {
return battery.voltage.valueString + battery.voltage.units
}
}
return "N/A"
}
Component {
id: batteryInfo
Rectangle {
width: battCol.width + ScreenTools.defaultFontPixelWidth * 3
height: battCol.height + ScreenTools.defaultFontPixelHeight * 2
radius: ScreenTools.defaultFontPixelHeight * 0.5
color: qgcPal.window
Column {
id: battCol
spacing: ScreenTools.defaultFontPixelHeight * 0.5
width: Math.max(battGrid.width, battLabel.width)
anchors.margins: ScreenTools.defaultFontPixelHeight
anchors.centerIn: parent
QGCLabel {
id: battLabel
text: qsTr("Battery Status")
font.family: ScreenTools.demiboldFontFamily
anchors.horizontalCenter: parent.horizontalCenter
}
GridLayout {
id: battGrid
anchors.margins: ScreenTools.defaultFontPixelHeight
columnSpacing: ScreenTools.defaultFontPixelWidth
columns: 2
anchors.horizontalCenter: parent.horizontalCenter
QGCLabel {
id: batteryLabel
text: qsTr("Battery 1")
Layout.alignment: Qt.AlignVCenter
}
QGCColoredImage {
height: batteryLabel.height
width: height
sourceSize.width: width
source: "/qmlimages/Battery.svg"
color: qgcPal.text
fillMode: Image.PreserveAspectFit
Rectangle {
color: getBatteryColor(activeVehicle ? activeVehicle.battery : null)
anchors.left: parent.left
anchors.leftMargin: ScreenTools.defaultFontPixelWidth * 0.125
height: parent.height * 0.35
width: activeVehicle ? (activeVehicle.battery.percentRemaining.value / 100) * parent.width * 0.875 : 0
anchors.verticalCenter: parent.verticalCenter
}
}
QGCLabel { text: qsTr("Voltage:") }
QGCLabel { text: (battery1 && battery1.voltage.value !== -1) ? (battery1.voltage.valueString + " " + battery1.voltage.units) : "N/A" }
QGCLabel { text: qsTr("Accumulated Consumption:") }
QGCLabel { text: (battery1 && battery1.mahConsumed.value !== -1) ? (battery1.mahConsumed.valueString + " " + battery1.mahConsumed.units) : "N/A" }
Item {
width: 1
height: 1
visible: hasSecondBattery;
Layout.columnSpan: 2
}
QGCLabel {
text: qsTr("Battery 2")
visible: hasSecondBattery
Layout.alignment: Qt.AlignVCenter
}
QGCColoredImage {
height: batteryLabel.height
width: height
sourceSize.width: width
source: "/qmlimages/Battery.svg"
color: qgcPal.text
visible: hasSecondBattery
fillMode: Image.PreserveAspectFit
Rectangle {
color: getBatteryColor(activeVehicle ? activeVehicle.battery2 : null)
anchors.left: parent.left
anchors.leftMargin: ScreenTools.defaultFontPixelWidth * 0.125
height: parent.height * 0.35
width: activeVehicle ? (activeVehicle.battery2.percentRemaining.value / 100) * parent.width * 0.875 : 0
anchors.verticalCenter: parent.verticalCenter
}
}
QGCLabel { text: qsTr("Voltage:"); visible: hasSecondBattery; }
QGCLabel { text: (battery2 && battery2.voltage.value !== -1) ? (battery2.voltage.valueString + " " + battery2.voltage.units) : "N/A"; visible: hasSecondBattery; }
QGCLabel { text: qsTr("Accumulated Consumption:"); visible: hasSecondBattery; }
QGCLabel { text: (battery2 && battery2.mahConsumed.value !== -1) ? (battery2.mahConsumed.valueString + " " + battery2.mahConsumed.units) : "N/A"; visible: hasSecondBattery; }
}
}
}
}
Row {
id: batteryIndicatorRow
anchors.top: parent.top
anchors.bottom: parent.bottom
opacity: (activeVehicle && activeVehicle.battery.voltage.value >= 0) ? 1 : 0.5
spacing: ScreenTools.defaultFontPixelWidth
QGCColoredImage {
anchors.top: parent.top
anchors.bottom: parent.bottom
width: height
sourceSize.width: width
source: "/qmlimages/Battery.svg"
color: qgcPal.text
fillMode: Image.PreserveAspectFit
Rectangle {
color: getBatteryColor(lowestBattery())
anchors.left: parent.left
anchors.leftMargin: ScreenTools.defaultFontPixelWidth * 0.25
height: parent.height * 0.35
width: activeVehicle ? (activeVehicle.battery.percentRemaining.value / 100) * parent.width * 0.75 : 0
anchors.verticalCenter: parent.verticalCenter
}
}
QGCLabel {
text: getBatteryPercentageText(lowestBattery())
font.pointSize: ScreenTools.smallFontPointSize
color: getBatteryColor(lowestBattery())
anchors.verticalCenter: parent.verticalCenter
}
}
MouseArea {
anchors.fill: parent
onClicked: {
mainWindow.showPopUp(_root, batteryInfo)
}
}
}
/****************************************************************************
*
* (c) 2009-2019 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.
*
* @file
* @author Gus Grubba <gus@auterion.com>
*/
import QtQuick 2.11
import QtQuick.Controls 1.4
import QtQuick.Layouts 1.11
import QGroundControl 1.0
import QGroundControl.Controls 1.0
import QGroundControl.MultiVehicleManager 1.0
import QGroundControl.ScreenTools 1.0
import QGroundControl.Palette 1.0
import Custom.Widgets 1.0
//-------------------------------------------------------------------------
//-- GPS Indicator
Item {
id: _root
width: gpsRow.width
anchors.top: parent.top
anchors.bottom: parent.bottom
function getGPSSignal() {
if(!activeVehicle || activeVehicle.gps.count.rawValue < 1 || activeVehicle.gps.hdop.rawValue > 1.4) {
return 0;
} else if(activeVehicle.gps.hdop.rawValue < 1.0) {
return 100;
} else if(activeVehicle.gps.hdop.rawValue < 1.1) {
return 75;
} else if(activeVehicle.gps.hdop.rawValue < 1.2) {
return 50;
} else {
return 25;
}
}
Component {
id: gpsInfo
Rectangle {
width: gpsCol.width + ScreenTools.defaultFontPixelWidth * 3
height: gpsCol.height + ScreenTools.defaultFontPixelHeight * 2
radius: ScreenTools.defaultFontPixelHeight * 0.5
color: qgcPal.window
Column {
id: gpsCol
spacing: ScreenTools.defaultFontPixelHeight * 0.5
width: Math.max(gpsGrid.width, gpsLabel.width)
anchors.margins: ScreenTools.defaultFontPixelHeight
anchors.centerIn: parent
QGCLabel {
id: gpsLabel
text: (activeVehicle && activeVehicle.gps.count.value >= 0) ? qsTr("GPS Status") : qsTr("GPS Data Unavailable")
font.family: ScreenTools.demiboldFontFamily
anchors.horizontalCenter: parent.horizontalCenter
}
GridLayout {
id: gpsGrid
visible: (activeVehicle && activeVehicle.gps.count.value >= 0)
anchors.margins: ScreenTools.defaultFontPixelHeight
columnSpacing: ScreenTools.defaultFontPixelWidth
anchors.horizontalCenter: parent.horizontalCenter
columns: 2
QGCLabel { text: qsTr("GPS Count:") }
QGCLabel { text: activeVehicle ? activeVehicle.gps.count.valueString : qsTr("N/A", "No data to display") }
QGCLabel { text: qsTr("GPS Lock:") }
QGCLabel { text: activeVehicle ? activeVehicle.gps.lock.enumStringValue : qsTr("N/A", "No data to display") }
QGCLabel { text: qsTr("HDOP:") }
QGCLabel { text: activeVehicle ? activeVehicle.gps.hdop.valueString : qsTr("--.--", "No data to display") }
QGCLabel { text: qsTr("VDOP:") }
QGCLabel { text: activeVehicle ? activeVehicle.gps.vdop.valueString : qsTr("--.--", "No data to display") }
QGCLabel { text: qsTr("Course Over Ground:") }
QGCLabel { text: activeVehicle ? activeVehicle.gps.courseOverGround.valueString : qsTr("--.--", "No data to display") }
}
}
}
}
Row {
id: gpsRow
anchors.top: parent.top
anchors.bottom: parent.bottom
spacing: ScreenTools.defaultFontPixelWidth * 0.25
QGCColoredImage {
width: height
anchors.top: parent.top
anchors.bottom: parent.bottom
sourceSize.height: height
source: "/qmlimages/Gps.svg"
color: qgcPal.text
fillMode: Image.PreserveAspectFit
opacity: getGPSSignal() > 0 ? 1 : 0.5
}
CustomSignalStrength {
anchors.verticalCenter: parent.verticalCenter
size: parent.height * 0.75
percent: getGPSSignal()
}
}
MouseArea {
anchors.fill: parent
onClicked: {
mainWindow.showPopUp(_root, gpsInfo)
}
}
}
/****************************************************************************
*
* (c) 2009-2019 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.
*
* @file
* @author Gus Grubba <gus@auterion.com>
*/
import QtQuick 2.11
import QtQuick.Controls 2.4
import QtQuick.Layouts 1.11
import QGroundControl 1.0
import QGroundControl.Controls 1.0
import QGroundControl.Palette 1.0
import QGroundControl.MultiVehicleManager 1.0
import QGroundControl.ScreenTools 1.0
import QGroundControl.Controllers 1.0
import Custom.Widgets 1.0
Item {
id: toolBar
anchors.fill: parent
property string sectionTitle: qsTr("Fly")
property bool inPlanView: planViewLoader.visible
property bool inFlyView: rootBackground.visible
//-------------------------------------------------------------------------
//-- Setup can be invoked from c++ side
Connections {
target: setupWindow
onVisibleChanged: {
if(setupWindow.visible) {
vehicleSetup.checked = true
sectionTitle = vehicleSetup.text
}
}
}
//-------------------------------------------------------------------------
//-- Initial State
Component.onCompleted: {
flyButton.checked = true
sectionTitle = flyButton.text
}
//-------------------------------------------------------------------------
//-- Fly/Plan state toggle
onInPlanViewChanged: {
if(inPlanView) {
planButton.checked = true
sectionTitle = planButton.text
}
}
onInFlyViewChanged: {
if(inFlyView) {
flyButton.checked = true
sectionTitle = flyButton.text
}
}
Row {
id: iconRow
height: parent.height
anchors.left: parent.left
spacing: ScreenTools.defaultFontPixelWidth * 2
CustomIconButton {
height: parent.height
onPressed: {
if(drawer.visible) {
drawer.close()
} else {
drawer.open()
}
// Easter egg mechanism
_pressCount++
eggTimer.restart()
if (_pressCount == 5) {
QGroundControl.corePlugin.showAdvancedUI = !QGroundControl.corePlugin.showAdvancedUI
}
}
property int _pressCount: 0
Timer {
id: eggTimer
interval: 1000
onTriggered: parent._pressCount = 0
}
}
Rectangle {
width: 1
height: parent.height
color: qgcPal.globalTheme === QGCPalette.Light ? Qt.rgba(0,0,0,0.15) : Qt.rgba(1,1,1,0.15)
}
//-------------------------------------------------------------------------
//-- Multi Vehicle Selector
Loader {
anchors.top: parent.top
anchors.bottom: parent.bottom
source: "/custom/CustomMultiVehicleSelector.qml"
visible: activeVehicle && !inPlanView
}
Rectangle {
width: 1
height: parent.height
color: qgcPal.globalTheme === QGCPalette.Light ? Qt.rgba(0,0,0,0.15) : Qt.rgba(1,1,1,0.15)
visible: activeVehicle && !inPlanView
}
//-------------------------------------------------------------------------
//-- Flight Mode
Loader {
anchors.top: parent.top
anchors.bottom: parent.bottom
source: "/custom/CustomModeIndicator.qml"
visible: activeVehicle && !inPlanView
}
}
//-------------------------------------------------------------------------
//-- Arm/Disarm
Loader {
anchors.top: parent.top
anchors.bottom: parent.bottom
anchors.horizontalCenter: parent.horizontalCenter
source: "/custom/CustomArmedIndicator.qml"
visible: activeVehicle && !inPlanView
}
//-------------------------------------------------------------------------
// Indicators
Loader {
source: inPlanView ? "/qml/PlanToolBarIndicators.qml" : "/custom/CustomMainToolBarIndicators.qml"
anchors.left: iconRow.right
anchors.leftMargin: ScreenTools.defaultFontPixelWidth * 2
anchors.right: parent.right
anchors.top: parent.top
anchors.bottom: parent.bottom
}
//-------------------------------------------------------------------------
// Parameter download progress bar
Rectangle {
anchors.bottom: parent.bottom
height: ScreenTools.defaultFontPixelheight * 0.25
width: activeVehicle ? activeVehicle.parameterManager.loadProgress * parent.width : 0
color: qgcPal.colorGreen
}
//-------------------------------------------------------------------------
// Bottom single pixel divider
Rectangle {
anchors.left: parent.left
anchors.right: parent.right
anchors.bottom: parent.bottom
height: 1
color: qgcPal.globalTheme === QGCPalette.Light ? Qt.rgba(0,0,0,0.15) : Qt.rgba(1,1,1,0.15)
}
//-------------------------------------------------------------------------
//-- Navigation Drawer (Left to Right, on command or using touch gestures)
Drawer {
id: drawer
y: header.height
width: navButtonWidth
height: mainWindow.height - header.height
closePolicy: Popup.CloseOnEscape | Popup.CloseOnPressOutside
background: Rectangle {
color: qgcPal.window
}
ButtonGroup {
id: buttonGroup
buttons: buttons.children
}
ColumnLayout {
id: buttons
anchors.top: parent.top
anchors.left: parent.left
anchors.right: parent.right
spacing: ScreenTools.defaultFontPixelHeight * 0.125
Rectangle {
Layout.alignment: Qt.AlignVCenter
width: parent.width
height: 1
color: Qt.rgba(1,1,1,0.15)
}
CustomToolBarButton {
id: flyButton
text: qsTr("Fly")
icon.source: "/qmlimages/PaperPlane.svg"
Layout.fillWidth: true
onClicked: {
checked = true
drawer.close()
sectionTitle = text
mainWindow.showFlyView()
}
}
Rectangle {
Layout.alignment: Qt.AlignVCenter
width: parent.width
height: 1
color: Qt.rgba(1,1,1,0.15)
}
CustomToolBarButton {
id: planButton
text: qsTr("Plan")
icon.source: "/qmlimages/Plan.svg"
Layout.fillWidth: true
onClicked: {
checked = true
drawer.close()
sectionTitle = text
mainWindow.showPlanView()
}
}
Rectangle {
Layout.alignment: Qt.AlignVCenter
width: parent.width
height: 1
color: Qt.rgba(1,1,1,0.15)
}
CustomToolBarButton {
text: qsTr("Analyze")
icon.source: "/qmlimages/Analyze.svg"
Layout.fillWidth: true
onClicked: {
checked = true
drawer.close()
sectionTitle = text
mainWindow.showAnalyzeView()
}
}
Rectangle {
Layout.alignment: Qt.AlignVCenter
width: parent.width
height: 1
color: Qt.rgba(1,1,1,0.15)
}
CustomToolBarButton {
id: vehicleSetup
text: qsTr("Vehicle Setup")
icon.source: "/qmlimages/Gears.svg"
Layout.fillWidth: true
onClicked: {
checked = true
drawer.close()
sectionTitle = text
mainWindow.showSetupView()
}
}
Rectangle {
Layout.alignment: Qt.AlignVCenter
width: parent.width
height: 1
color: Qt.rgba(1,1,1,0.15)
}
}
ColumnLayout {
id: lowerButtons
anchors.bottom: parent.bottom
anchors.bottomMargin: ScreenTools.defaultFontPixelHeight * 0.125
anchors.left: parent.left
anchors.right: parent.right
spacing: ScreenTools.defaultFontPixelHeight * 0.125
Rectangle {
Layout.alignment: Qt.AlignVCenter
width: parent.width
height: 1
color: Qt.rgba(1,1,1,0.15)
}
CustomToolBarButton {
id: settingsButton
text: qsTr("Settings")
icon.source: "/qmlimages/Gears.svg"
Layout.fillWidth: true
onClicked: {
checked = true
buttonGroup.checkState = Qt.Unchecked
drawer.close()
sectionTitle = text
mainWindow.showSettingsView()
}
}
Connections {
target: buttonGroup
onClicked: settingsButton.checked = false
}
}
}
}
/****************************************************************************
*
* (c) 2009-2019 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.
*
* @file
* @author Gus Grubba <gus@auterion.com>
*/
import QtQuick 2.11
import QtQuick.Controls 2.4
import QtQuick.Dialogs 1.3
import QtQuick.Layouts 1.11
import QGroundControl 1.0
import QGroundControl.Controls 1.0
import QGroundControl.MultiVehicleManager 1.0
import QGroundControl.ScreenTools 1.0
import QGroundControl.Palette 1.0
Item {
anchors.fill: parent
readonly property real _indicatorMargins: ScreenTools.defaultFontPixelHeight * 0.75
//-------------------------------------------------------------------------
//-- Waiting for a vehicle
Row {
id: waitForVehicle
spacing: ScreenTools.defaultFontPixelWidth
visible: !activeVehicle
anchors.top: parent.top
anchors.bottom: parent.bottom
anchors.left: parent.left
QGCColoredImage {
id: menuEdge
anchors.verticalCenter: parent.verticalCenter
height: ScreenTools.defaultFontPixelHeight
width: height
sourceSize.height: parent.height
fillMode: Image.PreserveAspectFit
source: "/qmlimages/PaperPlane.svg"
color: qgcPal.buttonText
}
QGCLabel {
anchors.verticalCenter: parent.verticalCenter
text: qsTr("Waiting for a vehicle")
font.pointSize: ScreenTools.mediumFontPointSize
font.family: ScreenTools.demiboldFontFamily
}
}
//-------------------------------------------------------------------------
//-- Toolbar Indicators
Row {
id: indicatorRow
anchors.top: parent.top
anchors.bottom: parent.bottom
anchors.right: parent.right
anchors.rightMargin: ScreenTools.defaultFontPixelWidth * 2
spacing: ScreenTools.defaultFontPixelWidth * 2
visible: activeVehicle && !communicationLost
Repeater {
model: activeVehicle ? activeVehicle.toolBarIndicators : []
Loader {
anchors.top: parent.top
anchors.bottom: parent.bottom
anchors.margins: _indicatorMargins
source: modelData;
}
}
Item {
width: 1
height: 1
}
Loader {
anchors.top: parent.top
anchors.bottom: parent.bottom
anchors.margins: _indicatorMargins
source: "/toolbar/MessageIndicator.qml"
}
}
}
/****************************************************************************
*
* (c) 2009-2019 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.
*
* @file
* @author Gus Grubba <gus@auterion.com>
*/
import QtQuick 2.11
import QtQuick.Controls 1.4
import QGroundControl 1.0
import QGroundControl.Controls 1.0
import QGroundControl.MultiVehicleManager 1.0
import QGroundControl.ScreenTools 1.0
import QGroundControl.Palette 1.0
//-------------------------------------------------------------------------
//-- Mode Indicator
Item {
anchors.top: parent.top
anchors.bottom: parent.bottom
width: selectorRow.width
property var _flightModes: activeVehicle ? activeVehicle.flightModes : [ ]
on_FlightModesChanged: flightModeSelector.updateFlightModesMenu()
Row {
id: selectorRow
spacing: ScreenTools.defaultFontPixelWidth
anchors.verticalCenter: parent.verticalCenter
QGCLabel {
id: flightModeSelector
text: activeVehicle ? activeVehicle.flightMode : qsTr("N/A")
color: qgcPal.text
font.pointSize: ScreenTools.defaultFontPointSize
anchors.verticalCenter: parent.verticalCenter
Menu {
id: flightModesMenu
}
Component {
id: flightModeMenuItemComponent
MenuItem {
onTriggered: activeVehicle.flightMode = text
}
}
property var flightModesMenuItems: []
function updateFlightModesMenu() {
if (activeVehicle && activeVehicle.flightModeSetAvailable) {
// Remove old menu items
var i = 0
for (i = 0; i < flightModesMenuItems.length; i++) {
flightModesMenu.removeItem(flightModesMenuItems[i])
}
flightModesMenuItems.length = 0
// Add new items
for (i = 0; i < _flightModes.length; i++) {
var menuItem = flightModeMenuItemComponent.createObject(null, { "text": _flightModes[i] })
flightModesMenuItems.push(menuItem)
flightModesMenu.insertItem(i, menuItem)
}
}
}
}
QGCColoredImage {
anchors.verticalCenter: parent.verticalCenter
height: ScreenTools.defaultFontPixelHeight * 0.5
width: height
sourceSize.height: parent.height
fillMode: Image.PreserveAspectFit
source: "/res/DropArrow.svg"
color: qgcPal.text
}
}
Component.onCompleted: flightModeSelector.updateFlightModesMenu()
MouseArea {
visible: activeVehicle && activeVehicle.flightModeSetAvailable
anchors.fill: parent
onClicked: flightModesMenu.popup()
}
}
/****************************************************************************
*
* (c) 2009-2019 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.
*
* @file
* @author Gus Grubba <gus@auterion.com>
*/
import QtQuick 2.11
import QtQuick.Controls 1.4
import QGroundControl 1.0
import QGroundControl.Controls 1.0
import QGroundControl.MultiVehicleManager 1.0
import QGroundControl.ScreenTools 1.0
import QGroundControl.Palette 1.0
//-------------------------------------------------------------------------
//-- Multi Vehicle Selector
Item {
anchors.top: parent.top
anchors.bottom: parent.bottom
width: selectorRow.width
property bool _multiVehicles: QGroundControl.multiVehicleManager.vehicles.count > 1
Component.onCompleted: {
updatemultiVehiclesMenu()
}
Connections {
target: QGroundControl.multiVehicleManager.vehicles
onCountChanged: updatemultiVehiclesMenu()
}
Row {
id: selectorRow
spacing: ScreenTools.defaultFontPixelWidth
anchors.verticalCenter: parent.verticalCenter
QGCColoredImage {
anchors.verticalCenter: parent.verticalCenter
height: ScreenTools.defaultFontPixelHeight
width: height
sourceSize.height: parent.height
fillMode: Image.PreserveAspectFit
source: "/qmlimages/PaperPlane.svg"
color: qgcPal.text
}
QGCLabel {
id: multiVehicleSelector
text: "Vehicle " + (activeVehicle ? activeVehicle.id : "None")
color: qgcPal.buttonText
anchors.verticalCenter: parent.verticalCenter
}
QGCColoredImage {
visible: _multiVehicles
anchors.verticalCenter: parent.verticalCenter
height: ScreenTools.defaultFontPixelHeight * 0.5
width: height
sourceSize.height: parent.height
fillMode: Image.PreserveAspectFit
source: "/res/DropArrow.svg"
color: qgcPal.text
}
}
Menu {
id: multiVehiclesMenu
}
Component {
id: multiVehicleMenuItemComponent
MenuItem {
onTriggered: QGroundControl.multiVehicleManager.activeVehicle = vehicle
property int vehicleId: Number(text.split(" ")[1])
property var vehicle: QGroundControl.multiVehicleManager.getVehicleById(vehicleId)
}
}
property var multiVehiclesMenuItems: []
function updatemultiVehiclesMenu() {
if (_multiVehicles) {
// Remove old menu items
for (var i = 0; i < multiVehiclesMenuItems.length; i++) {
multiVehiclesMenu.removeItem(multiVehiclesMenuItems[i])
}
multiVehiclesMenuItems.length = 0
// Add new items
for (i = 0; i < QGroundControl.multiVehicleManager.vehicles.count; i++) {
var vehicle = QGroundControl.multiVehicleManager.vehicles.get(i)
var menuItem = multiVehicleMenuItemComponent.createObject(null, { "text": "Vehicle " + vehicle.id })
multiVehiclesMenuItems.push(menuItem)
multiVehiclesMenu.insertItem(i, menuItem)
console.log("Vehicle " + vehicle.id)
}
} else {
console.log('No multiple vehicles: ' + QGroundControl.multiVehicleManager.vehicles.count)
}
}
MouseArea {
visible: _multiVehicles
anchors.fill: parent
onClicked: {
console.log('Clicked')
multiVehiclesMenu.popup()
}
}
}
/****************************************************************************
*
* (c) 2009-2019 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.
*
* @file
* @author Gus Grubba <gus@auterion.com>
*/
import QtQuick 2.11
import QtQuick.Controls 1.4
import QtQuick.Layouts 1.11
import QGroundControl 1.0
import QGroundControl.Controls 1.0
import QGroundControl.MultiVehicleManager 1.0
import QGroundControl.ScreenTools 1.0
import QGroundControl.Palette 1.0
import Custom.Widgets 1.0
//-------------------------------------------------------------------------
//-- RC RSSI Indicator
Item {
id: _root
width: visible ? rssiRow.width : 0
anchors.top: parent.top
anchors.bottom: parent.bottom
visible: activeVehicle ? activeVehicle.supportsRadio : true
property bool _rcRSSIAvailable: activeVehicle ? activeVehicle.rcRSSI > 0 && activeVehicle.rcRSSI <= 100 : false
Component {
id: rcRSSIInfo
Rectangle {
width: rcrssiCol.width + ScreenTools.defaultFontPixelWidth * 3
height: rcrssiCol.height + ScreenTools.defaultFontPixelHeight * 2
radius: ScreenTools.defaultFontPixelHeight * 0.5
color: qgcPal.window
Column {
id: rcrssiCol
spacing: ScreenTools.defaultFontPixelHeight * 0.5
width: Math.max(rcrssiGrid.width, rssiLabel.width)
anchors.margins: ScreenTools.defaultFontPixelHeight
anchors.centerIn: parent
QGCLabel {
id: rssiLabel
text: activeVehicle ? (activeVehicle.rcRSSI !== 255 ? qsTr("RC RSSI Status") : qsTr("RC RSSI Data Unavailable")) : qsTr("N/A", "No data available")
font.family: ScreenTools.demiboldFontFamily
anchors.horizontalCenter: parent.horizontalCenter
}
GridLayout {
id: rcrssiGrid
visible: _rcRSSIAvailable
anchors.margins: ScreenTools.defaultFontPixelHeight
columnSpacing: ScreenTools.defaultFontPixelWidth
columns: 2
anchors.horizontalCenter: parent.horizontalCenter
QGCLabel { text: qsTr("RSSI:") }
QGCLabel { text: activeVehicle ? (activeVehicle.rcRSSI + "%") : 0 }
}
}
}
}
Row {
id: rssiRow
anchors.top: parent.top
anchors.bottom: parent.bottom
spacing: ScreenTools.defaultFontPixelWidth * 0.25
QGCColoredImage {
width: height
anchors.top: parent.top
anchors.bottom: parent.bottom
sourceSize.height: height
source: "/custom/img/menu_rc.svg"
color: qgcPal.text
fillMode: Image.PreserveAspectFit
opacity: _rcRSSIAvailable ? 1 : 0.5
}
CustomSignalStrength {
anchors.verticalCenter: parent.verticalCenter
size: parent.height * 0.75
percent: _rcRSSIAvailable ? activeVehicle.rcRSSI : 0
}
}
MouseArea {
anchors.fill: parent
onClicked: {
mainWindow.showPopUp(_root, rcRSSIInfo)
}
}
}
/****************************************************************************
*
* (c) 2009-2019 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.
*
* @file
* @brief Custom Autopilot Plugin
* @author Gus Grubba <gus@auterion.com>
*/
#include "CustomAutoPilotPlugin.h"
#include "QGCApplication.h"
#include "QGCCorePlugin.h"
//-----------------------------------------------------------------------------
CustomAutoPilotPlugin::CustomAutoPilotPlugin(Vehicle* vehicle, QObject* parent)
: PX4AutoPilotPlugin(vehicle, parent)
{
connect(qgcApp()->toolbox()->corePlugin(), &QGCCorePlugin::showAdvancedUIChanged, this, &CustomAutoPilotPlugin::_advancedChanged);
}
//-----------------------------------------------------------------------------
void
CustomAutoPilotPlugin::_advancedChanged(bool)
{
_components.clear();
emit vehicleComponentsChanged();
}
//-----------------------------------------------------------------------------
const QVariantList&
CustomAutoPilotPlugin::vehicleComponents()
{
if (_components.count() == 0 && !_incorrectParameterVersion) {
if (_vehicle) {
bool showAdvanced = qgcApp()->toolbox()->corePlugin()->showAdvancedUI();
qDebug() << "Loading components:" << showAdvanced;
if (_vehicle->parameterManager()->parametersReady()) {
if(showAdvanced) {
_airframeComponent = new AirframeComponent(_vehicle, this);
_airframeComponent->setupTriggerSignals();
_components.append(QVariant::fromValue(reinterpret_cast<VehicleComponent*>(_airframeComponent)));
}
if (!_vehicle->hilMode()) {
_sensorsComponent = new SensorsComponent(_vehicle, this);
_sensorsComponent->setupTriggerSignals();
_components.append(QVariant::fromValue(reinterpret_cast<VehicleComponent*>(_sensorsComponent)));
}
if(showAdvanced) {
_radioComponent = new PX4RadioComponent(_vehicle, this);
_radioComponent->setupTriggerSignals();
_components.append(QVariant::fromValue(reinterpret_cast<VehicleComponent*>(_radioComponent)));
_flightModesComponent = new FlightModesComponent(_vehicle, this);
_flightModesComponent->setupTriggerSignals();
_components.append(QVariant::fromValue(reinterpret_cast<VehicleComponent*>(_flightModesComponent)));
_powerComponent = new PowerComponent(_vehicle, this);
_powerComponent->setupTriggerSignals();
_components.append(QVariant::fromValue(reinterpret_cast<VehicleComponent*>(_powerComponent)));
_motorComponent = new MotorComponent(_vehicle, this);
_motorComponent->setupTriggerSignals();
_components.append(QVariant::fromValue(reinterpret_cast<VehicleComponent*>(_motorComponent)));
}
_safetyComponent = new SafetyComponent(_vehicle, this);
_safetyComponent->setupTriggerSignals();
_components.append(QVariant::fromValue(reinterpret_cast<VehicleComponent*>(_safetyComponent)));
if(showAdvanced) {
_tuningComponent = new PX4TuningComponent(_vehicle, this);
_tuningComponent->setupTriggerSignals();
_components.append(QVariant::fromValue(reinterpret_cast<VehicleComponent*>(_tuningComponent)));
//-- Is there support for cameras?
if(_vehicle->parameterManager()->parameterExists(_vehicle->id(), "TRIG_MODE")) {
_cameraComponent = new CameraComponent(_vehicle, this);
_cameraComponent->setupTriggerSignals();
_components.append(QVariant::fromValue(reinterpret_cast<VehicleComponent*>(_cameraComponent)));
}
}
//-- Is there an ESP8266 Connected?
if(_vehicle->parameterManager()->parameterExists(MAV_COMP_ID_UDP_BRIDGE, "SW_VER")) {
_esp8266Component = new ESP8266Component(_vehicle, this);
_esp8266Component->setupTriggerSignals();
_components.append(QVariant::fromValue(reinterpret_cast<VehicleComponent*>(_esp8266Component)));
}
} else {
qWarning() << "Call to vehicleCompenents prior to parametersReady";
}
if(_vehicle->parameterManager()->parameterExists(_vehicle->id(), "SLNK_RADIO_CHAN")) {
_syslinkComponent = new SyslinkComponent(_vehicle, this);
_syslinkComponent->setupTriggerSignals();
_components.append(QVariant::fromValue(reinterpret_cast<VehicleComponent*>(_syslinkComponent)));
}
} else {
qWarning() << "Internal error";
}
}
return _components;
}
/****************************************************************************
*
* (c) 2009-2019 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.
*
* @file
* @brief Custom Autopilot Plugin
* @author Gus Grubba <gus@auterion.com>
*/
#pragma once
#include "PX4AutoPilotPlugin.h"
#include "Vehicle.h"
/// Custom overrides from standard PX4AutoPilotPlugin implementation
class CustomAutoPilotPlugin : public PX4AutoPilotPlugin
{
Q_OBJECT
public:
CustomAutoPilotPlugin(Vehicle* vehicle, QObject* parent);
const QVariantList& vehicleComponents() override;
private slots:
void _advancedChanged (bool advanced);
private:
QVariantList _components;
};
/****************************************************************************
*
* (c) 2009-2019 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.
*
* @brief Custom QGCCorePlugin Implementation
* @author Gus Grubba <gus@custom.com>
*/
#include <QtQml>
#include <QQmlEngine>
#include <QDateTime>
#include "QGCSettings.h"
#include "MAVLinkLogManager.h"
#include "CustomPlugin.h"
#include "CustomQuickInterface.h"
#include "MultiVehicleManager.h"
#include "QGCApplication.h"
#include "SettingsManager.h"
#include "AppMessages.h"
#include "QmlComponentInfo.h"
#include "QGCPalette.h"
QGC_LOGGING_CATEGORY(CustomLog, "CustomLog")
CustomVideoReceiver::CustomVideoReceiver(QObject* parent)
: VideoReceiver(parent)
{
#if defined(QGC_GST_STREAMING)
//-- Shorter RTSP test interval
_restart_time_ms = 1000;
#endif
}
CustomVideoReceiver::~CustomVideoReceiver()
{
}
//-----------------------------------------------------------------------------
static QObject*
customQuickInterfaceSingletonFactory(QQmlEngine*, QJSEngine*)
{
qCDebug(CustomLog) << "Creating CustomQuickInterface instance";
CustomQuickInterface* pIFace = new CustomQuickInterface();
CustomPlugin* pPlug = dynamic_cast<CustomPlugin*>(qgcApp()->toolbox()->corePlugin());
if(pPlug) {
pIFace->init();
} else {
qCritical() << "Error obtaining instance of CustomPlugin";
}
return pIFace;
}
//-----------------------------------------------------------------------------
CustomOptions::CustomOptions(CustomPlugin*, QObject* parent)
: QGCOptions(parent)
{
}
//-----------------------------------------------------------------------------
bool
CustomOptions::showFirmwareUpgrade() const
{
return qgcApp()->toolbox()->corePlugin()->showAdvancedUI();
}
QColor
CustomOptions::toolbarBackgroundLight() const
{
return CustomPlugin::_windowShadeEnabledLightColor;
}
QColor
CustomOptions::toolbarBackgroundDark() const
{
return CustomPlugin::_windowShadeEnabledDarkColor;
}
//-----------------------------------------------------------------------------
CustomPlugin::CustomPlugin(QGCApplication *app, QGCToolbox* toolbox)
: QGCCorePlugin(app, toolbox)
{
_pOptions = new CustomOptions(this, this);
_showAdvancedUI = false;
}
//-----------------------------------------------------------------------------
CustomPlugin::~CustomPlugin()
{
}
//-----------------------------------------------------------------------------
void
CustomPlugin::setToolbox(QGCToolbox* toolbox)
{
QGCCorePlugin::setToolbox(toolbox);
qmlRegisterSingletonType<CustomQuickInterface>("CustomQuickInterface", 1, 0, "CustomQuickInterface", customQuickInterfaceSingletonFactory);
//-- Disable automatic logging
toolbox->mavlinkLogManager()->setEnableAutoStart(false);
toolbox->mavlinkLogManager()->setEnableAutoUpload(false);
connect(qgcApp()->toolbox()->corePlugin(), &QGCCorePlugin::showAdvancedUIChanged, this, &CustomPlugin::_advancedChanged);
}
//-----------------------------------------------------------------------------
void
CustomPlugin::_advancedChanged(bool changed)
{
//-- We are now in "Advanced Mode" (or not)
emit _pOptions->showFirmwareUpgradeChanged(changed);
}
//-----------------------------------------------------------------------------
void
CustomPlugin::addSettingsEntry(const QString& title,
const char* qmlFile,
const char* iconFile/*= nullptr*/)
{
Q_CHECK_PTR(qmlFile);
// 'this' instance will take ownership on the QmlComponentInfo instance
_customSettingsList.append(QVariant::fromValue(
new QmlComponentInfo(title,
QUrl::fromUserInput(qmlFile),
iconFile == nullptr ? QUrl() : QUrl::fromUserInput(iconFile),
this)));
}
//-----------------------------------------------------------------------------
QVariantList&
CustomPlugin::settingsPages()
{
if(_customSettingsList.isEmpty()) {
addSettingsEntry(tr("General"), "qrc:/qml/GeneralSettings.qml", "qrc:/res/gear-white.svg");
addSettingsEntry(tr("Comm Links"), "qrc:/qml/LinkSettings.qml", "qrc:/res/waves.svg");
addSettingsEntry(tr("Offline Maps"),"qrc:/qml/OfflineMap.qml", "qrc:/res/waves.svg");
#if defined(QGC_GST_MICROHARD_ENABLED)
addSettingsEntry(tr("Microhard"), "qrc:/qml/MicrohardSettings.qml");
#endif
#if defined(QGC_GST_TAISYNC_ENABLED)
addSettingsEntry(tr("Taisync"), "qrc:/qml/TaisyncSettings.qml");
#endif
#if defined(QGC_AIRMAP_ENABLED)
addSettingsEntry(tr("AirMap"), "qrc:/qml/AirmapSettings.qml");
#endif
addSettingsEntry(tr("MAVLink"), "qrc:/qml/MavlinkSettings.qml", " qrc:/res/waves.svg");
addSettingsEntry(tr("Console"), "qrc:/qml/QGroundControl/Controls/AppMessages.qml");
#if defined(QGC_ENABLE_QZXING)
addSettingsEntry(tr("Barcode Test"),"qrc:/custom/BarcodeReader.qml");
#endif
#if defined(QT_DEBUG)
//-- These are always present on Debug builds
addSettingsEntry(tr("Mock Link"), "qrc:/qml/MockLink.qml");
addSettingsEntry(tr("Debug"), "qrc:/qml/DebugWindow.qml");
addSettingsEntry(tr("Palette Test"),"qrc:/qml/QmlTest.qml");
#endif
}
return _customSettingsList;
}
//-----------------------------------------------------------------------------
QGCOptions*
CustomPlugin::options()
{
return _pOptions;
}
//-----------------------------------------------------------------------------
QString
CustomPlugin::brandImageIndoor(void) const
{
return QStringLiteral("/custom/img/void.png");
}
//-----------------------------------------------------------------------------
QString
CustomPlugin::brandImageOutdoor(void) const
{
return QStringLiteral("/custom/img/void.png");
}
//-----------------------------------------------------------------------------
bool
CustomPlugin::overrideSettingsGroupVisibility(QString name)
{
if (name == BrandImageSettings::name) {
return false;
}
return true;
}
//-----------------------------------------------------------------------------
VideoReceiver*
CustomPlugin::createVideoReceiver(QObject* parent)
{
return new CustomVideoReceiver(parent);
}
//-----------------------------------------------------------------------------
QQmlApplicationEngine*
CustomPlugin::createRootWindow(QObject *parent)
{
QQmlApplicationEngine* pEngine = new QQmlApplicationEngine(parent);
pEngine->addImportPath("qrc:/qml");
pEngine->addImportPath("qrc:/Custom/Widgets");
pEngine->rootContext()->setContextProperty("joystickManager", qgcApp()->toolbox()->joystickManager());
pEngine->rootContext()->setContextProperty("debugMessageModel", AppMessages::getModel());
pEngine->load(QUrl(QStringLiteral("qrc:/qml/MainRootWindow.qml")));
return pEngine;
}
//-----------------------------------------------------------------------------
bool
CustomPlugin::adjustSettingMetaData(const QString& settingsGroup, FactMetaData& metaData)
{
if (settingsGroup == AppSettings::settingsGroup) {
if (metaData.name() == AppSettings::appFontPointSizeName) {
#if defined(WIN32)
int defaultFontPointSize = 11;
metaData.setRawDefaultValue(defaultFontPointSize);
#endif
} else if (metaData.name() == AppSettings::indoorPaletteName) {
QVariant indoorPalette = 1;
metaData.setRawDefaultValue(indoorPalette);
return true;
}
}
return true;
}
const QColor CustomPlugin::_windowShadeEnabledLightColor("#FFFFFF");
const QColor CustomPlugin::_windowShadeEnabledDarkColor("#0B1420");
//-----------------------------------------------------------------------------
void
CustomPlugin::paletteOverride(QString colorName, QGCPalette::PaletteColorInfo_t& colorInfo)
{
if (colorName == QStringLiteral("window")) {
colorInfo[QGCPalette::Dark][QGCPalette::ColorGroupEnabled] = QColor("#0b1420");
colorInfo[QGCPalette::Dark][QGCPalette::ColorGroupDisabled] = QColor("#0b1420");
colorInfo[QGCPalette::Light][QGCPalette::ColorGroupEnabled] = QColor("#ffffff");
colorInfo[QGCPalette::Light][QGCPalette::ColorGroupDisabled] = QColor("#ffffff");
}
else if (colorName == QStringLiteral("windowShade")) {
colorInfo[QGCPalette::Dark][QGCPalette::ColorGroupEnabled] = QColor("#342926");
colorInfo[QGCPalette::Dark][QGCPalette::ColorGroupDisabled] = QColor("#342926");
colorInfo[QGCPalette::Light][QGCPalette::ColorGroupEnabled] = QColor("#d9d9d9");
colorInfo[QGCPalette::Light][QGCPalette::ColorGroupDisabled] = QColor("#d9d9d9");
}
else if (colorName == QStringLiteral("windowShadeDark")) {
colorInfo[QGCPalette::Dark][QGCPalette::ColorGroupEnabled] = QColor("#40332e");
colorInfo[QGCPalette::Dark][QGCPalette::ColorGroupDisabled] = QColor("#080f18");
colorInfo[QGCPalette::Light][QGCPalette::ColorGroupEnabled] = QColor("#bdbdbd");
colorInfo[QGCPalette::Light][QGCPalette::ColorGroupDisabled] = QColor("#bdbdbd");
}
else if (colorName == QStringLiteral("text")) {
colorInfo[QGCPalette::Dark][QGCPalette::ColorGroupEnabled] = QColor("#ffffff");
colorInfo[QGCPalette::Dark][QGCPalette::ColorGroupDisabled] = QColor("#777c89");
colorInfo[QGCPalette::Light][QGCPalette::ColorGroupEnabled] = QColor("#0b1420");
colorInfo[QGCPalette::Light][QGCPalette::ColorGroupDisabled] = QColor("#9d9d9d");
}
else if (colorName == QStringLiteral("warningText")) {
colorInfo[QGCPalette::Dark][QGCPalette::ColorGroupEnabled] = QColor("#e03131");
colorInfo[QGCPalette::Dark][QGCPalette::ColorGroupDisabled] = QColor("#e03131");
colorInfo[QGCPalette::Light][QGCPalette::ColorGroupEnabled] = QColor("#cc0808");
colorInfo[QGCPalette::Light][QGCPalette::ColorGroupDisabled] = QColor("#cc0808");
}
else if (colorName == QStringLiteral("button")) {
colorInfo[QGCPalette::Dark][QGCPalette::ColorGroupEnabled] = QColor("#594e4c");
colorInfo[QGCPalette::Dark][QGCPalette::ColorGroupDisabled] = QColor("#313d4d");
colorInfo[QGCPalette::Light][QGCPalette::ColorGroupEnabled] = QColor("#ffffff");
colorInfo[QGCPalette::Light][QGCPalette::ColorGroupDisabled] = QColor("#ffffff");
}
else if (colorName == QStringLiteral("buttonText")) {
colorInfo[QGCPalette::Dark][QGCPalette::ColorGroupEnabled] = QColor("#ffffff");
colorInfo[QGCPalette::Dark][QGCPalette::ColorGroupDisabled] = QColor("#777c89");
colorInfo[QGCPalette::Light][QGCPalette::ColorGroupEnabled] = QColor("#0b1420");
colorInfo[QGCPalette::Light][QGCPalette::ColorGroupDisabled] = QColor("#9d9d9d");
}
else if (colorName == QStringLiteral("buttonHighlight")) {
colorInfo[QGCPalette::Dark][QGCPalette::ColorGroupEnabled] = QColor("#6EF880");
colorInfo[QGCPalette::Dark][QGCPalette::ColorGroupDisabled] = QColor("#222a35");
colorInfo[QGCPalette::Light][QGCPalette::ColorGroupEnabled] = QColor("#edcfb4");
colorInfo[QGCPalette::Light][QGCPalette::ColorGroupDisabled] = QColor("#e4e4e4");
}
else if (colorName == QStringLiteral("buttonHighlightText")) {
colorInfo[QGCPalette::Dark][QGCPalette::ColorGroupEnabled] = QColor("#1d3c20");
colorInfo[QGCPalette::Dark][QGCPalette::ColorGroupDisabled] = QColor("#777c89");
colorInfo[QGCPalette::Light][QGCPalette::ColorGroupEnabled] = QColor("#211b1b");
colorInfo[QGCPalette::Light][QGCPalette::ColorGroupDisabled] = QColor("#2c2c2c");
}
else if (colorName == QStringLiteral("primaryButton")) {
colorInfo[QGCPalette::Dark][QGCPalette::ColorGroupEnabled] = QColor("#24dc09");
colorInfo[QGCPalette::Dark][QGCPalette::ColorGroupDisabled] = QColor("#29313a");
colorInfo[QGCPalette::Light][QGCPalette::ColorGroupEnabled] = QColor("#8e5e54");
colorInfo[QGCPalette::Light][QGCPalette::ColorGroupDisabled] = QColor("#585858");
}
else if (colorName == QStringLiteral("primaryButtonText")) {
colorInfo[QGCPalette::Dark][QGCPalette::ColorGroupEnabled] = QColor("#ffffff");
colorInfo[QGCPalette::Dark][QGCPalette::ColorGroupDisabled] = QColor("#777c89");
colorInfo[QGCPalette::Light][QGCPalette::ColorGroupEnabled] = QColor("#ffffff");
colorInfo[QGCPalette::Light][QGCPalette::ColorGroupDisabled] = QColor("#cad0d0");
}
else if (colorName == QStringLiteral("textField")) {
colorInfo[QGCPalette::Dark][QGCPalette::ColorGroupEnabled] = QColor("#0a111f");
colorInfo[QGCPalette::Dark][QGCPalette::ColorGroupDisabled] = QColor("#29313a");
colorInfo[QGCPalette::Light][QGCPalette::ColorGroupEnabled] = QColor("#ffffff");
colorInfo[QGCPalette::Light][QGCPalette::ColorGroupDisabled] = QColor("#ffffff");
}
else if (colorName == QStringLiteral("textFieldText")) {
colorInfo[QGCPalette::Dark][QGCPalette::ColorGroupEnabled] = QColor("#ffffff");
colorInfo[QGCPalette::Dark][QGCPalette::ColorGroupDisabled] = QColor("#777c89");
colorInfo[QGCPalette::Light][QGCPalette::ColorGroupEnabled] = QColor("#0b1420");
colorInfo[QGCPalette::Light][QGCPalette::ColorGroupDisabled] = QColor("#808080");
}
else if (colorName == QStringLiteral("mapButton")) {
colorInfo[QGCPalette::Dark][QGCPalette::ColorGroupEnabled] = QColor("#000000");
colorInfo[QGCPalette::Dark][QGCPalette::ColorGroupDisabled] = QColor("#585858");
colorInfo[QGCPalette::Light][QGCPalette::ColorGroupEnabled] = QColor("#0b1420");
colorInfo[QGCPalette::Light][QGCPalette::ColorGroupDisabled] = QColor("#585858");
}
else if (colorName == QStringLiteral("mapButtonHighlight")) {
colorInfo[QGCPalette::Dark][QGCPalette::ColorGroupEnabled] = QColor("#84c448");
colorInfo[QGCPalette::Dark][QGCPalette::ColorGroupDisabled] = QColor("#585858");
colorInfo[QGCPalette::Light][QGCPalette::ColorGroupEnabled] = QColor("#be781c");
colorInfo[QGCPalette::Light][QGCPalette::ColorGroupDisabled] = QColor("#585858");
}
else if (colorName == QStringLiteral("mapIndicator")) {
colorInfo[QGCPalette::Dark][QGCPalette::ColorGroupEnabled] = QColor("#9dda4f");
colorInfo[QGCPalette::Dark][QGCPalette::ColorGroupDisabled] = QColor("#585858");
colorInfo[QGCPalette::Light][QGCPalette::ColorGroupEnabled] = QColor("#be781c");
colorInfo[QGCPalette::Light][QGCPalette::ColorGroupDisabled] = QColor("#585858");
}
else if (colorName == QStringLiteral("mapIndicatorChild")) {
colorInfo[QGCPalette::Dark][QGCPalette::ColorGroupEnabled] = QColor("#527942");
colorInfo[QGCPalette::Dark][QGCPalette::ColorGroupDisabled] = QColor("#585858");
colorInfo[QGCPalette::Light][QGCPalette::ColorGroupEnabled] = QColor("#766043");
colorInfo[QGCPalette::Light][QGCPalette::ColorGroupDisabled] = QColor("#585858");
}
else if (colorName == QStringLiteral("colorGreen")) {
colorInfo[QGCPalette::Dark][QGCPalette::ColorGroupEnabled] = QColor("#27bf89");
colorInfo[QGCPalette::Dark][QGCPalette::ColorGroupDisabled] = QColor("#0ca678");
colorInfo[QGCPalette::Light][QGCPalette::ColorGroupEnabled] = QColor("#009431");
colorInfo[QGCPalette::Light][QGCPalette::ColorGroupDisabled] = QColor("#009431");
}
else if (colorName == QStringLiteral("colorOrange")) {
colorInfo[QGCPalette::Dark][QGCPalette::ColorGroupEnabled] = QColor("#f7b24a");
colorInfo[QGCPalette::Dark][QGCPalette::ColorGroupDisabled] = QColor("#f6921e");
colorInfo[QGCPalette::Light][QGCPalette::ColorGroupEnabled] = QColor("#b95604");
colorInfo[QGCPalette::Light][QGCPalette::ColorGroupDisabled] = QColor("#b95604");
}
else if (colorName == QStringLiteral("colorRed")) {
colorInfo[QGCPalette::Dark][QGCPalette::ColorGroupEnabled] = QColor("#e1544c");
colorInfo[QGCPalette::Dark][QGCPalette::ColorGroupDisabled] = QColor("#e03131");
colorInfo[QGCPalette::Light][QGCPalette::ColorGroupEnabled] = QColor("#ed3939");
colorInfo[QGCPalette::Light][QGCPalette::ColorGroupDisabled] = QColor("#ed3939");
}
else if (colorName == QStringLiteral("colorGrey")) {
colorInfo[QGCPalette::Dark][QGCPalette::ColorGroupEnabled] = QColor("#8b90a0");
colorInfo[QGCPalette::Dark][QGCPalette::ColorGroupDisabled] = QColor("#8b90a0");
colorInfo[QGCPalette::Light][QGCPalette::ColorGroupEnabled] = QColor("#808080");
colorInfo[QGCPalette::Light][QGCPalette::ColorGroupDisabled] = QColor("#808080");
}
else if (colorName == QStringLiteral("colorBlue")) {
colorInfo[QGCPalette::Dark][QGCPalette::ColorGroupEnabled] = QColor("#228be6");
colorInfo[QGCPalette::Dark][QGCPalette::ColorGroupDisabled] = QColor("#228be6");
colorInfo[QGCPalette::Light][QGCPalette::ColorGroupEnabled] = QColor("#1a72ff");
colorInfo[QGCPalette::Light][QGCPalette::ColorGroupDisabled] = QColor("#1a72ff");
}
else if (colorName == QStringLiteral("alertBackground")) {
colorInfo[QGCPalette::Dark][QGCPalette::ColorGroupEnabled] = QColor("#a04a18");
colorInfo[QGCPalette::Dark][QGCPalette::ColorGroupDisabled] = QColor("#a04a18");
colorInfo[QGCPalette::Light][QGCPalette::ColorGroupEnabled] = QColor("#b45d48");
colorInfo[QGCPalette::Light][QGCPalette::ColorGroupDisabled] = QColor("#b45d48");
}
else if (colorName == QStringLiteral("alertBorder")) {
colorInfo[QGCPalette::Dark][QGCPalette::ColorGroupEnabled] = QColor("#c79218");
colorInfo[QGCPalette::Dark][QGCPalette::ColorGroupDisabled] = QColor("#c79218");
colorInfo[QGCPalette::Light][QGCPalette::ColorGroupEnabled] = QColor("#808080");
colorInfo[QGCPalette::Light][QGCPalette::ColorGroupDisabled] = QColor("#808080");
}
else if (colorName == QStringLiteral("alertText")) {
colorInfo[QGCPalette::Dark][QGCPalette::ColorGroupEnabled] = QColor("#fff9ed");
colorInfo[QGCPalette::Dark][QGCPalette::ColorGroupDisabled] = QColor("#fff9ed");
colorInfo[QGCPalette::Light][QGCPalette::ColorGroupEnabled] = QColor("#fff9ed");
colorInfo[QGCPalette::Light][QGCPalette::ColorGroupDisabled] = QColor("#fff9ed");
}
else if (colorName == QStringLiteral("missionItemEditor")) {
colorInfo[QGCPalette::Dark][QGCPalette::ColorGroupEnabled] = QColor("#0b1420");
colorInfo[QGCPalette::Dark][QGCPalette::ColorGroupDisabled] = QColor("#0b1420");
colorInfo[QGCPalette::Light][QGCPalette::ColorGroupEnabled] = QColor("#ffffff");
colorInfo[QGCPalette::Light][QGCPalette::ColorGroupDisabled] = QColor("#585858");
}
else if (colorName == QStringLiteral("hoverColor")) {
colorInfo[QGCPalette::Dark][QGCPalette::ColorGroupEnabled] = QColor("#E7D8AE");
colorInfo[QGCPalette::Dark][QGCPalette::ColorGroupDisabled] = QColor("#E7D8AE");
colorInfo[QGCPalette::Light][QGCPalette::ColorGroupEnabled] = QColor("#464f5a");
colorInfo[QGCPalette::Light][QGCPalette::ColorGroupDisabled] = QColor("#464f5a");
}
else if (colorName == QStringLiteral("mapWidgetBorderLight")) {
colorInfo[QGCPalette::Dark][QGCPalette::ColorGroupEnabled] = QColor("#ffffff");
colorInfo[QGCPalette::Dark][QGCPalette::ColorGroupDisabled] = QColor("#ffffff");
colorInfo[QGCPalette::Light][QGCPalette::ColorGroupEnabled] = QColor("#0b1420");
colorInfo[QGCPalette::Light][QGCPalette::ColorGroupDisabled] = QColor("#ffffff");
}
else if (colorName == QStringLiteral("mapWidgetBorderDark")) {
colorInfo[QGCPalette::Dark][QGCPalette::ColorGroupEnabled] = QColor("#000000");
colorInfo[QGCPalette::Dark][QGCPalette::ColorGroupDisabled] = QColor("#000000");
colorInfo[QGCPalette::Light][QGCPalette::ColorGroupEnabled] = QColor("#0b1420");
colorInfo[QGCPalette::Light][QGCPalette::ColorGroupDisabled] = QColor("#000000");
}
else if (colorName == QStringLiteral("brandingPurple")) {
colorInfo[QGCPalette::Dark][QGCPalette::ColorGroupEnabled] = QColor("#4a2c6d");
colorInfo[QGCPalette::Dark][QGCPalette::ColorGroupDisabled] = QColor("#4a2c6d");
colorInfo[QGCPalette::Light][QGCPalette::ColorGroupEnabled] = QColor("#4a2c6d");
colorInfo[QGCPalette::Light][QGCPalette::ColorGroupDisabled] = QColor("#4a2c6d");
}
else if (colorName == QStringLiteral("brandingBlue")) {
colorInfo[QGCPalette::Dark][QGCPalette::ColorGroupEnabled] = QColor("#6045c5");
colorInfo[QGCPalette::Dark][QGCPalette::ColorGroupDisabled] = QColor("#48d6ff");
colorInfo[QGCPalette::Light][QGCPalette::ColorGroupEnabled] = QColor("#6045c5");
colorInfo[QGCPalette::Light][QGCPalette::ColorGroupDisabled] = QColor("#48d6ff");
}
}
/****************************************************************************
*
* (c) 2009-2019 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.
*
* @brief Custom QGCCorePlugin Declaration
* @author Gus Grubba <gus@auterion.com>
*/
#pragma once
#include "QGCCorePlugin.h"
#include "QGCOptions.h"
#include "QGCLoggingCategory.h"
#include "VideoReceiver.h"
#include "SettingsManager.h"
#include <QTranslator>
class CustomPlugin;
class CustomSettings;
Q_DECLARE_LOGGING_CATEGORY(CustomLog)
//-- Our own, custom video receiver
class CustomVideoReceiver : public VideoReceiver
{
Q_OBJECT
public:
explicit CustomVideoReceiver(QObject* parent = nullptr);
~CustomVideoReceiver();
};
//-----------------------------------------------------------------------------
//-- Our own, custom options
class CustomOptions : public QGCOptions
{
public:
CustomOptions(CustomPlugin*, QObject* parent = nullptr);
bool wifiReliableForCalibration () const final { return true; }
QUrl flyViewOverlay () const final { return QUrl::fromUserInput("qrc:/custom/CustomFlyView.qml"); }
//-- We have our own toolbar
QUrl mainToolbarUrl () const final { return QUrl::fromUserInput("qrc:/custom/CustomMainToolBar.qml"); }
QUrl planToolbarUrl () const final { return QUrl::fromUserInput("qrc:/custom/CustomMainToolBar.qml"); }
//-- Don't show instrument widget
CustomInstrumentWidget* instrumentWidget () final { return nullptr; }
bool showMavlinkLogOptions () const final { return false; }
bool showFirmwareUpgrade () const final;
//-- We handle multiple vehicles in a custom way
bool enableMultiVehicleList () const final { return false; }
//-- We handle our own map scale
bool enableMapScale () const final { return false; }
// TODO: Can't access QGCPalette without some workarounds, change this upstream
QColor toolbarBackgroundLight () const final;
QColor toolbarBackgroundDark () const final;
};
//-----------------------------------------------------------------------------
class CustomPlugin : public QGCCorePlugin
{
Q_OBJECT
public:
CustomPlugin(QGCApplication* app, QGCToolbox *toolbox);
~CustomPlugin();
// Overrides from QGCCorePlugin
QVariantList& settingsPages () final;
QGCOptions* options () final;
QString brandImageIndoor () const final;
QString brandImageOutdoor () const final;
bool overrideSettingsGroupVisibility (QString name) final;
VideoReceiver* createVideoReceiver (QObject* parent) final;
QQmlApplicationEngine* createRootWindow (QObject* parent) final;
bool adjustSettingMetaData (const QString& settingsGroup, FactMetaData& metaData) final;
void paletteOverride (QString colorName, QGCPalette::PaletteColorInfo_t& colorInfo) final;
// Overrides from QGCTool
void setToolbox (QGCToolbox* toolbox);
const static QColor _windowShadeEnabledLightColor;
const static QColor _windowShadeEnabledDarkColor;
private slots:
void _advancedChanged (bool advanced);
private:
void
addSettingsEntry(
const QString& title,
const char* qmlFile,
const char* iconFile = nullptr);
private:
CustomOptions* _pOptions = nullptr;
QVariantList _customSettingsList; // Not to be mixed up with QGCCorePlugin implementation
};
/****************************************************************************
*
* (c) 2009-2019 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.
*
* @file
* @brief Custom QtQuick Interface
* @author Gus Grubba <gus@auterion.com>
*/
#include "QGCApplication.h"
#include "AppSettings.h"
#include "SettingsManager.h"
#include "MAVLinkLogManager.h"
#include "QGCMapEngine.h"
#include "QGCApplication.h"
#include "PositionManager.h"
#include "CustomPlugin.h"
#include "CustomQuickInterface.h"
#include <QDirIterator>
#include <QtAlgorithms>
//-----------------------------------------------------------------------------
CustomQuickInterface::CustomQuickInterface(QObject* parent)
: QObject(parent)
{
qCDebug(CustomLog) << "CustomQuickInterface Created";
}
//-----------------------------------------------------------------------------
CustomQuickInterface::~CustomQuickInterface()
{
qCDebug(CustomLog) << "CustomQuickInterface Destroyed";
}
//-----------------------------------------------------------------------------
void
CustomQuickInterface::init()
{
}
/****************************************************************************
*
* (c) 2009-2019 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.
*
* @file
* @brief Custom QtQuick Interface
* @author Gus Grubba <gus@auterion.com>
*/
#pragma once
#include "Vehicle.h"
#include <QObject>
#include <QTimer>
#include <QColor>
#include <QGeoPositionInfo>
#include <QGeoPositionInfoSource>
//-----------------------------------------------------------------------------
// QtQuick Interface (UI)
class CustomQuickInterface : public QObject
{
Q_OBJECT
public:
CustomQuickInterface(QObject* parent = nullptr);
~CustomQuickInterface();
void init ();
};
/****************************************************************************
*
* (c) 2009-2019 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.
*
* @file
* @brief Camera Controller
* @author Gus Grubba <gus@auterion.com>
*
*/
#include "CustomCameraControl.h"
#include "QGCCameraIO.h"
QGC_LOGGING_CATEGORY(CustomCameraLog, "CustomCameraLog")
QGC_LOGGING_CATEGORY(CustomCameraVerboseLog, "CustomCameraVerboseLog")
//-----------------------------------------------------------------------------
CustomCameraControl::CustomCameraControl(const mavlink_camera_information_t *info, Vehicle* vehicle, int compID, QObject* parent)
: QGCCameraControl(info, vehicle, compID, parent)
{
connect(_vehicle, &Vehicle::mavlinkMessageReceived, this, &CustomCameraControl::_mavlinkMessageReceived);
}
//-----------------------------------------------------------------------------
bool
CustomCameraControl::takePhoto()
{
bool res = false;
res = QGCCameraControl::takePhoto();
return res;
}
//-----------------------------------------------------------------------------
bool
CustomCameraControl::stopTakePhoto()
{
bool res = QGCCameraControl::stopTakePhoto();
return res;
}
//-----------------------------------------------------------------------------
bool
CustomCameraControl::startVideo()
{
bool res = QGCCameraControl::startVideo();
return res;
}
//-----------------------------------------------------------------------------
bool
CustomCameraControl::stopVideo()
{
bool res = QGCCameraControl::stopVideo();
return res;
}
//-----------------------------------------------------------------------------
void
CustomCameraControl::setVideoMode()
{
if(cameraMode() != CAM_MODE_VIDEO) {
qCDebug(CustomCameraLog) << "setVideoMode()";
Fact* pFact = getFact(kCAM_MODE);
if(pFact) {
pFact->setRawValue(CAM_MODE_VIDEO);
_setCameraMode(CAM_MODE_VIDEO);
}
}
}
//-----------------------------------------------------------------------------
void
CustomCameraControl::setPhotoMode()
{
if(cameraMode() != CAM_MODE_PHOTO) {
qCDebug(CustomCameraLog) << "setPhotoMode()";
Fact* pFact = getFact(kCAM_MODE);
if(pFact) {
pFact->setRawValue(CAM_MODE_PHOTO);
_setCameraMode(CAM_MODE_PHOTO);
}
}
}
//-----------------------------------------------------------------------------
void
CustomCameraControl::_setVideoStatus(VideoStatus status)
{
QGCCameraControl::_setVideoStatus(status);
}
//-----------------------------------------------------------------------------
void
CustomCameraControl::_mavlinkMessageReceived(const mavlink_message_t& message)
{
switch (message.msgid) {
case MAVLINK_MSG_ID_MOUNT_ORIENTATION:
_handleGimbalOrientation(message);
break;
}
}
//-----------------------------------------------------------------------------
void
CustomCameraControl::_handleGimbalOrientation(const mavlink_message_t& message)
{
mavlink_mount_orientation_t o;
mavlink_msg_mount_orientation_decode(&message, &o);
if(fabsf(_gimbalRoll - o.roll) > 0.5f) {
_gimbalRoll = o.roll;
emit gimbalRollChanged();
}
if(fabsf(_gimbalPitch - o.pitch) > 0.5f) {
_gimbalPitch = o.pitch;
emit gimbalPitchChanged();
}
if(fabsf(_gimbalYaw - o.yaw) > 0.5f) {
_gimbalYaw = o.yaw;
emit gimbalYawChanged();
}
if(!_gimbalData) {
_gimbalData = true;
emit gimbalDataChanged();
}
}
//-----------------------------------------------------------------------------
void
CustomCameraControl::handleCaptureStatus(const mavlink_camera_capture_status_t& cap)
{
QGCCameraControl::handleCaptureStatus(cap);
}
/****************************************************************************
*
* (c) 2009-2019 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.
*
* @file
* @brief Camera Controller
* @author Gus Grubba <gus@auterion.com>
*
*/
#pragma once
#include "QGCCameraControl.h"
#include <QSize>
#include <QPoint>
Q_DECLARE_LOGGING_CATEGORY(CustomCameraLog)
Q_DECLARE_LOGGING_CATEGORY(CustomCameraVerboseLog)
//-----------------------------------------------------------------------------
class CustomCameraControl : public QGCCameraControl
{
Q_OBJECT
public:
CustomCameraControl(const mavlink_camera_information_t* info, Vehicle* vehicle, int compID, QObject* parent = nullptr);
Q_PROPERTY(qreal gimbalRoll READ gimbalRoll NOTIFY gimbalRollChanged)
Q_PROPERTY(qreal gimbalPitch READ gimbalPitch NOTIFY gimbalPitchChanged)
Q_PROPERTY(qreal gimbalYaw READ gimbalYaw NOTIFY gimbalYawChanged)
Q_PROPERTY(bool gimbalData READ gimbalData NOTIFY gimbalDataChanged)
bool takePhoto () override;
bool stopTakePhoto () override;
bool startVideo () override;
bool stopVideo () override;
void setVideoMode () override;
void setPhotoMode () override;
void handleCaptureStatus (const mavlink_camera_capture_status_t& capStatus) override;
qreal gimbalRoll () { return static_cast<qreal>(_gimbalRoll);}
qreal gimbalPitch () { return static_cast<qreal>(_gimbalPitch); }
qreal gimbalYaw () { return static_cast<qreal>(_gimbalYaw); }
bool gimbalData () { return _gimbalData; }
private slots:
void _mavlinkMessageReceived (const mavlink_message_t& message);
signals:
void gimbalRollChanged ();
void gimbalPitchChanged ();
void gimbalYawChanged ();
void gimbalDataChanged ();
protected:
void _setVideoStatus (VideoStatus status) override;
private:
void _handleGimbalOrientation(const mavlink_message_t& message);
private:
float _gimbalRoll = 0.0;
float _gimbalPitch = 0.0;
float _gimbalYaw = 0.0;
bool _gimbalData = false;
};
/****************************************************************************
*
* (c) 2009-2019 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.
*
* @file
* @brief Camera Controller
* @author Gus Grubba <gus@auterion.com>
*
*/
#include "QGCApplication.h"
#include "CustomCameraManager.h"
//-----------------------------------------------------------------------------
CustomCameraManager::CustomCameraManager(Vehicle *vehicle)
: QGCCameraManager(vehicle)
{
}
/****************************************************************************
*
* (c) 2009-2019 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.
*
* @file
* @brief Camera Controller
* @author Gus Grubba <gus@auterion.com>
*
*/
#pragma once
#include "QGCCameraManager.h"
//-----------------------------------------------------------------------------
class CustomCameraManager : public QGCCameraManager
{
Q_OBJECT
public:
CustomCameraManager(Vehicle* vehicle);
};
/****************************************************************************
*
* (c) 2009-2019 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.
*
* @file
* @brief Custom Firmware Plugin (PX4)
* @author Gus Grubba <gus@auterion.com>
*
*/
#include "CustomFirmwarePlugin.h"
#include "CustomAutoPilotPlugin.h"
#include "CustomCameraManager.h"
#include "CustomCameraControl.h"
//-----------------------------------------------------------------------------
CustomFirmwarePlugin::CustomFirmwarePlugin()
{
}
//-----------------------------------------------------------------------------
AutoPilotPlugin* CustomFirmwarePlugin::autopilotPlugin(Vehicle* vehicle)
{
return new CustomAutoPilotPlugin(vehicle, vehicle);
}
//-----------------------------------------------------------------------------
QGCCameraManager*
CustomFirmwarePlugin::createCameraManager(Vehicle *vehicle)
{
return new CustomCameraManager(vehicle);
}
//-----------------------------------------------------------------------------
QGCCameraControl*
CustomFirmwarePlugin::createCameraControl(const mavlink_camera_information_t* info, Vehicle *vehicle, int compID, QObject* parent)
{
return new CustomCameraControl(info, vehicle, compID, parent);
}
//-----------------------------------------------------------------------------
const QVariantList&
CustomFirmwarePlugin::toolBarIndicators(const Vehicle* vehicle)
{
Q_UNUSED(vehicle);
if(_toolBarIndicatorList.size() == 0) {
_toolBarIndicatorList.append(QVariant::fromValue(QUrl::fromUserInput("qrc:/toolbar/GPSIndicator.qml")));
_toolBarIndicatorList.append(QVariant::fromValue(QUrl::fromUserInput("qrc:/toolbar/TelemetryRSSIIndicator.qml")));
_toolBarIndicatorList.append(QVariant::fromValue(QUrl::fromUserInput("qrc:/toolbar/RCRSSIIndicator.qml")));
_toolBarIndicatorList.append(QVariant::fromValue(QUrl::fromUserInput("qrc:/toolbar/BatteryIndicator.qml")));
}
return _toolBarIndicatorList;
}
/****************************************************************************
*
* (c) 2009-2019 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.
*
* @file
* @brief Custom Firmware Plugin (PX4)
* @author Gus Grubba <gus@auterion.com>
*
*/
#pragma once
#include "FirmwarePlugin.h"
#include "PX4FirmwarePlugin.h"
class CustomCameraManager;
class CustomFirmwarePlugin : public PX4FirmwarePlugin
{
Q_OBJECT
public:
CustomFirmwarePlugin();
// FirmwarePlugin overrides
AutoPilotPlugin* autopilotPlugin (Vehicle* vehicle) override;
QGCCameraManager* createCameraManager (Vehicle *vehicle) override;
QGCCameraControl* createCameraControl (const mavlink_camera_information_t* info, Vehicle* vehicle, int compID, QObject* parent = nullptr) override;
const QVariantList& toolBarIndicators (const Vehicle* vehicle) override;
private:
QVariantList _toolBarIndicatorList;
};
/****************************************************************************
*
* (c) 2009-2019 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.
*
* @file
* @brief Custom Firmware Plugin Factory (PX4)
* @author Gus Grubba <gus@auterion.com>
*
*/
#include "CustomFirmwarePluginFactory.h"
#include "CustomFirmwarePlugin.h"
CustomFirmwarePluginFactory CustomFirmwarePluginFactoryImp;
CustomFirmwarePluginFactory::CustomFirmwarePluginFactory()
: _pluginInstance(nullptr)
{
}
QList<MAV_AUTOPILOT> CustomFirmwarePluginFactory::supportedFirmwareTypes() const
{
QList<MAV_AUTOPILOT> list;
list.append(MAV_AUTOPILOT_PX4);
return list;
}
FirmwarePlugin* CustomFirmwarePluginFactory::firmwarePluginForAutopilot(MAV_AUTOPILOT autopilotType, MAV_TYPE vehicleType)
{
Q_UNUSED(vehicleType);
if (autopilotType == MAV_AUTOPILOT_PX4) {
if (!_pluginInstance) {
_pluginInstance = new CustomFirmwarePlugin;
}
return _pluginInstance;
}
return nullptr;
}
/****************************************************************************
*
* (c) 2009-2019 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.
*
* @file
* @brief Custom Firmware Plugin Factory (PX4)
* @author Gus Grubba <gus@auterion.com>
*
*/
#pragma once
#include "FirmwarePlugin.h"
class CustomFirmwarePlugin;
class CustomFirmwarePluginFactory : public FirmwarePluginFactory
{
Q_OBJECT
public:
CustomFirmwarePluginFactory();
QList<MAV_AUTOPILOT> supportedFirmwareTypes () const override;
FirmwarePlugin* firmwarePluginForAutopilot (MAV_AUTOPILOT autopilotType, MAV_TYPE vehicleType) override;
private:
CustomFirmwarePlugin* _pluginInstance;
};
extern CustomFirmwarePluginFactory CustomFirmwarePluginFactoryImp;
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment