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 {