Commit f1559638 authored by dogmaphobic's avatar dogmaphobic

Work on RTSP Video Stream, x86 Android, etc.

parent 5fc24cfa
......@@ -30,12 +30,18 @@ linux {
CONFIG += LinuxBuild
DEFINES += __STDC_LIMIT_MACROS __rasp_pi2__
} else : android-g++ {
message("Android build")
CONFIG += AndroidBuild MobileBuild
DEFINES += __android__
DEFINES += __STDC_LIMIT_MACROS
DEFINES += QGC_ENABLE_BLUETOOTH
target.path = $$DESTDIR
equals(ANDROID_TARGET_ARCH, x86) {
CONFIG += Androidx86Build
DEFINES += __androidx86__
message("Android x86 build")
} else {
message("Android Arm build")
}
} else {
error("Unsuported Linux toolchain, only GCC 32- or 64-bit is supported")
}
......@@ -54,11 +60,11 @@ linux {
DEFINES += __macos__
CONFIG += x86_64
CONFIG -= x86
equals(QT_MAJOR_VERSION, 5) | greaterThan(QT_MINOR_VERSION, 5) {
QMAKE_MACOSX_DEPLOYMENT_TARGET = 10.7
} else {
QMAKE_MACOSX_DEPLOYMENT_TARGET = 10.6
}
equals(QT_MAJOR_VERSION, 5) | greaterThan(QT_MINOR_VERSION, 5) {
QMAKE_MACOSX_DEPLOYMENT_TARGET = 10.7
} else {
QMAKE_MACOSX_DEPLOYMENT_TARGET = 10.6
}
QMAKE_MAC_SDK = macosx10.11
QMAKE_CXXFLAGS += -fvisibility=hidden
} else {
......
......@@ -46,6 +46,15 @@ contains (DEFINES, QGC_DISABLE_BLUETOOTH) {
DEFINES += QGC_ENABLE_BLUETOOTH
}
# USB Camera and UVC Video Sources
contains (DEFINES, QGC_DISABLE_UVC) {
message("Skipping support for UVC devices (manual override from command line)")
DEFINES -= QGC_DISABLE_UVC
} else:exists(user_config.pri):infile(user_config.pri, DEFINES, QGC_DISABLE_UVC) {
message("Skipping support for UVC devices (manual override from user_config.pri)")
DEFINES -= QGC_DISABLE_UVC
}
LinuxBuild {
CONFIG += link_pkgconfig
}
......
......@@ -15,6 +15,8 @@
<file alias="LogDownload.qml">src/ViewWidgets/LogDownload.qml</file>
<file alias="FirmwareUpgrade.qml">src/VehicleSetup/FirmwareUpgrade.qml</file>
<file alias="FlightDisplayView.qml">src/FlightDisplay/FlightDisplayView.qml</file>
<file alias="FlightDisplayViewUVC.qml">src/FlightDisplay/FlightDisplayViewUVC.qml</file>
<file alias="FlightDisplayViewDummy.qml">src/FlightDisplay/FlightDisplayViewDummy.qml</file>
<file alias="PX4FlightModes.qml">src/AutoPilotPlugins/PX4/PX4FlightModes.qml</file>
<file alias="PX4AdvancedFlightModes.qml">src/AutoPilotPlugins/PX4/PX4AdvancedFlightModes.qml</file>
<file alias="PX4SimpleFlightModes.qml">src/AutoPilotPlugins/PX4/PX4SimpleFlightModes.qml</file>
......
......@@ -184,34 +184,17 @@ QGCView {
}
}
]
//-- UDP Video Streaming
//-- Video Streaming
FlightDisplayViewVideo {
anchors.fill: parent
visible: QGroundControl.videoManager.isGStreamer
}
//-- UVC Video (USB Camera or Video Device)
Rectangle {
id: noVideo
Loader {
id: cameraLoader
anchors.fill: parent
color: Qt.rgba(0,0,0,0.75)
visible: !QGroundControl.videoManager.isGStreamer
Camera {
id: camera
deviceId: QGroundControl.videoManager.videoSourceID
captureMode: Camera.CaptureViewfinder
}
VideoOutput {
id: viewFinder
source: camera
anchors.fill: parent
visible: !QGroundControl.videoManager.isGStreamer
}
onVisibleChanged: {
if(visible)
camera.start()
else
camera.stop()
}
source: QGroundControl.videoManager.uvcEnabled ? "qrc:/qml/FlightDisplayViewUVC.qml" : "qrc:/qml/FlightDisplayViewDummy.qml"
}
}
......
/****************************************************************************
*
* (c) 2009-2016 QGROUNDCONTROL PROJECT <http://www.qgroundcontrol.org>
*
* QGroundControl is licensed according to the terms in the file
* COPYING.md in the root of the source code directory.
*
****************************************************************************/
import QtQuick 2.5
Rectangle {
anchors.fill: parent
color: Qt.rgba(0,0,0,0.75)
}
/****************************************************************************
*
* (c) 2009-2016 QGROUNDCONTROL PROJECT <http://www.qgroundcontrol.org>
*
* QGroundControl is licensed according to the terms in the file
* COPYING.md in the root of the source code directory.
*
****************************************************************************/
import QtQuick 2.5
import QtMultimedia 5.5
import QGroundControl 1.0
Rectangle {
anchors.fill: parent
color: Qt.rgba(0,0,0,0.75)
Camera {
id: camera
deviceId: QGroundControl.videoManager.videoSourceID
captureMode: Camera.CaptureViewfinder
}
VideoOutput {
source: camera
anchors.fill: parent
fillMode: VideoOutput.PreserveAspectCrop
visible: !QGroundControl.videoManager.isGStreamer
}
onVisibleChanged: {
if(visible)
camera.start()
else
camera.stop()
}
}
......@@ -41,7 +41,6 @@ Item {
display: QGroundControl.videoManager.videoSurface
receiver: QGroundControl.videoManager.videoReceiver
visible: QGroundControl.videoManager.videoRunning
runVideo: true
/* TODO: Come up with a way to make this an option
QGCAttitudeHUD {
id: attitudeHUD
......
......@@ -19,51 +19,33 @@
#include "VideoManager.h"
static const char* kVideoSourceKey = "VideoSource";
static const char* kGStreamerSource = "UDP Video Stream";
static const char* kVideoUDPPortKey = "VideoUDPPort";
static const char* kVideoRTSPUrlKey = "VideoRTSPUrl";
static const char* kUDPStream = "UDP Video Stream";
static const char* kRTSPStream = "RTSP Video Stream";
QGC_LOGGING_CATEGORY(VideoManagerLog, "VideoManagerLog")
//-----------------------------------------------------------------------------
VideoManager::VideoManager(QGCApplication* app)
: QGCTool(app)
, _videoSurface(NULL)
, _videoReceiver(NULL)
, _videoRunning(false)
, _udpPort(5600) //-- Defalut Port 5600 == Solo UDP Port
, _init(false)
{
/*
* This is the receiving end of an UDP RTP stream. The sender can be setup with this command:
*
* gst-launch-1.0 uvch264src initial-bitrate=1000000 average-bitrate=1000000 iframe-period=1000 name=src auto-start=true src.vidsrc ! \
* video/x-h264,width=1280,height=720,framerate=24/1 ! h264parse ! rtph264pay ! udpsink host=192.168.1.9 port=5600
*
* Where the main parameters are:
*
* uvch264src: Your h264 video source (the example above uses a Logitech C920 on an Raspberry PI 2+ or Odroid C1
* host=192.168.1.9 This is the IP address of QGC. You can use Avahi/Zeroconf to find QGC using the "_qgroundcontrol._udp" service.
*
* Advanced settings (you should probably read the gstreamer documentation before changing these):
*
* initial-bitrate=1000000 average-bitrate=1000000
* The bit rate to use. The greater, the better quality at the cost of higher bandwidth.
*
* width=1280,height=720,framerate=24/1
* The video resolution and frame rate. This depends on the camera used.
*
* iframe-period=1000
* Interval between iFrames. The greater the interval the lesser bandwidth at the cost of a longer time to recover from lost packets.
*
* Do not change anything else unless you know what you are doing. Any other change will require a matching change on the receiving end.
*
*/
_videoSurface = new VideoSurface;
_videoReceiver = new VideoReceiver(this);
_videoReceiver->setUri(QLatin1Literal("udp://0.0.0.0:5600")); // Port 5600=Solo UDP port, if you change it, you will break Solo video support
//-- Get saved settings
QSettings settings;
setVideoSource(settings.value(kVideoSourceKey, kUDPStream).toString());
setUdpPort(settings.value(kVideoUDPPortKey, 5600).toUInt());
setRtspURL(settings.value(kVideoRTSPUrlKey, "rtsp://192.168.42.1:554/live").toString()); //-- Example RTSP URL
_init = true;
#if defined(QGC_GST_STREAMING)
_videoReceiver->setVideoSink(_videoSurface->videoSink());
_updateVideo();
connect(&_frameTimer, &QTimer::timeout, this, &VideoManager::_updateTimer);
_frameTimer.start(1000);
#endif
//-- Get saved video source
QSettings settings;
setVideoSource(settings.value(kVideoSourceKey, kGStreamerSource).toString());
}
//-----------------------------------------------------------------------------
......@@ -96,12 +78,21 @@ bool
VideoManager::isGStreamer()
{
#if defined(QGC_GST_STREAMING)
return _videoSource == kGStreamerSource;
return _videoSource == kUDPStream || _videoSource == kRTSPStream;
#else
return false;
#endif
}
//-----------------------------------------------------------------------------
#ifndef QGC_DISABLE_UVC
bool
VideoManager::uvcEnabled()
{
return QCameraInfo::availableCameras().count() > 0;
}
#endif
//-----------------------------------------------------------------------------
void
VideoManager::setVideoSource(QString vSource)
......@@ -110,6 +101,7 @@ VideoManager::setVideoSource(QString vSource)
QSettings settings;
settings.setValue(kVideoSourceKey, vSource);
emit videoSourceChanged();
#ifndef QGC_DISABLE_UVC
QList<QCameraInfo> cameras = QCameraInfo::availableCameras();
foreach (const QCameraInfo &cameraInfo, cameras) {
if(cameraInfo.description() == vSource) {
......@@ -119,8 +111,51 @@ VideoManager::setVideoSource(QString vSource)
break;
}
}
#endif
emit isGStreamerChanged();
qCDebug(VideoManagerLog) << "New Video Source:" << vSource;
/*
* Not working. Requires restart for now
if(isGStreamer())
_updateVideo();
*/
if(_videoReceiver) {
if(isGStreamer()) {
_videoReceiver->start();
} else {
_videoReceiver->stop();
}
}
}
//-----------------------------------------------------------------------------
void
VideoManager::setUdpPort(quint16 port)
{
_udpPort = port;
QSettings settings;
settings.setValue(kVideoUDPPortKey, port);
emit udpPortChanged();
/*
* Not working. Requires restart for now
if(_videoSource == kUDPStream)
_updateVideo();
*/
}
//-----------------------------------------------------------------------------
void
VideoManager::setRtspURL(QString url)
{
_rtspURL = url;
QSettings settings;
settings.setValue(kVideoRTSPUrlKey, url);
emit rtspURLChanged();
/*
* Not working. Requires restart for now
if(_videoSource == kRTSPStream)
_updateVideo();
*/
}
//-----------------------------------------------------------------------------
......@@ -129,20 +164,23 @@ VideoManager::videoSourceList()
{
_videoSourceList.clear();
#if defined(QGC_GST_STREAMING)
_videoSourceList.append(kGStreamerSource);
_videoSourceList.append(kUDPStream);
_videoSourceList.append(kRTSPStream);
#endif
#ifndef QGC_DISABLE_UVC
QList<QCameraInfo> cameras = QCameraInfo::availableCameras();
foreach (const QCameraInfo &cameraInfo, cameras) {
qCDebug(VideoManagerLog) << "UVC Video source ID:" << cameraInfo.deviceName() << " Name:" << cameraInfo.description();
_videoSourceList.append(cameraInfo.description());
}
#endif
return _videoSourceList;
}
//-----------------------------------------------------------------------------
#if defined(QGC_GST_STREAMING)
void VideoManager::_updateTimer(void)
void VideoManager::_updateTimer()
{
#if defined(QGC_GST_STREAMING)
if(_videoRunning)
{
time_t elapsed = 0;
......@@ -150,7 +188,7 @@ void VideoManager::_updateTimer(void)
{
elapsed = time(0) - _videoSurface->lastFrame();
}
if(elapsed > 2)
if(elapsed > 2 && _videoSurface)
{
_videoRunning = false;
_videoSurface->setLastFrame(0);
......@@ -167,5 +205,26 @@ void VideoManager::_updateTimer(void)
}
}
}
}
#endif
}
//-----------------------------------------------------------------------------
void VideoManager::_updateVideo()
{
if(_init) {
if(_videoReceiver)
delete _videoReceiver;
if(_videoSurface)
delete _videoSurface;
_videoSurface = new VideoSurface;
_videoReceiver = new VideoReceiver(this);
_videoReceiver->setVideoSink(_videoSurface->videoSink());
#if defined(QGC_GST_STREAMING)
if(_videoSource == kUDPStream)
_videoReceiver->setUri(QStringLiteral("udp://0.0.0.0:%1").arg(_udpPort));
else
_videoReceiver->setUri(_rtspURL);
#endif
_videoReceiver->start();
}
}
......@@ -35,6 +35,9 @@ public:
Q_PROPERTY(QString videoSource READ videoSource WRITE setVideoSource NOTIFY videoSourceChanged)
Q_PROPERTY(QStringList videoSourceList READ videoSourceList NOTIFY videoSourceListChanged)
Q_PROPERTY(bool videoRunning READ videoRunning NOTIFY videoRunningChanged)
Q_PROPERTY(quint16 udpPort READ udpPort WRITE setUdpPort NOTIFY udpPortChanged)
Q_PROPERTY(QString rtspURL READ rtspURL WRITE setRtspURL NOTIFY rtspURLChanged)
Q_PROPERTY(bool uvcEnabled READ uvcEnabled CONSTANT)
Q_PROPERTY(VideoSurface* videoSurface MEMBER _videoSurface CONSTANT)
Q_PROPERTY(VideoReceiver* videoReceiver MEMBER _videoReceiver CONSTANT)
......@@ -44,7 +47,18 @@ public:
QString videoSourceID () { return _videoSourceID; }
QString videoSource () { return _videoSource; }
QStringList videoSourceList ();
quint16 udpPort () { return _udpPort; }
QString rtspURL () { return _rtspURL; }
#if defined(QGC_DISABLE_UVC)
bool uvcEnabled () { return false; }
#else
bool uvcEnabled ();
#endif
void setVideoSource (QString vSource);
void setUdpPort (quint16 port);
void setRtspURL (QString url);
// Override from QGCTool
void setToolbox (QGCToolbox *toolbox);
......@@ -56,9 +70,12 @@ signals:
void videoSourceListChanged ();
void isGStreamerChanged ();
void videoSourceIDChanged ();
void udpPortChanged ();
void rtspURLChanged ();
private:
void _updateTimer(void);
void _updateTimer ();
void _updateVideo ();
private:
VideoSurface* _videoSurface;
......@@ -70,6 +87,9 @@ private:
QString _videoSource;
QString _videoSourceID;
QStringList _videoSourceList;
quint16 _udpPort;
QString _rtspURL;
bool _init;
};
#endif
......@@ -22,20 +22,5 @@ VideoItem {
id: videoBackground
property var display
property var receiver
property var runVideo: false
surface: display
onRunVideoChanged: {
if(videoBackground.receiver && videoBackground.display) {
if(videoBackground.runVideo) {
videoBackground.receiver.start();
} else {
videoBackground.receiver.stop();
}
}
}
Component.onCompleted: {
if(videoBackground.runVideo && videoBackground.receiver) {
videoBackground.receiver.start();
}
}
}
......@@ -49,6 +49,21 @@ void VideoReceiver::setVideoSink(GstElement* sink)
}
#endif
static void newPadCB(GstElement * element, GstPad* pad, gpointer data)
{
gchar *name;
name = gst_pad_get_name(pad);
g_print("A new pad %s was created\n", name);
GstCaps * p_caps = gst_pad_get_pad_template_caps (pad);
gchar * description = gst_caps_to_string(p_caps);
qDebug() << p_caps << ", " << description;
g_free(description);
GstElement * p_rtph264depay = GST_ELEMENT(data);
if(gst_element_link_pads(element, name, p_rtph264depay, "sink") == false)
qCritical() << "newPadCB : failed to link elements\n";
g_free(name);
}
void VideoReceiver::start()
{
#if defined(QGC_GST_STREAMING)
......@@ -56,7 +71,6 @@ void VideoReceiver::start()
qCritical() << "VideoReceiver::start() failed because URI is not specified";
return;
}
if (_videoSink == NULL) {
qCritical() << "VideoReceiver::start() failed because video sink is not set";
return;
......@@ -72,29 +86,44 @@ void VideoReceiver::start()
GstElement* parser = NULL;
GstElement* decoder = NULL;
bool isUdp = _uri.contains("udp://");
do {
if ((_pipeline = gst_pipeline_new("receiver")) == NULL) {
qCritical() << "VideoReceiver::start() failed. Error with gst_pipeline_new()";
break;
}
if ((dataSource = gst_element_factory_make("udpsrc", "udp-source")) == NULL) {
qCritical() << "VideoReceiver::start() failed. Error with gst_element_factory_make('udpsrc')";
break;
if(isUdp) {
dataSource = gst_element_factory_make("udpsrc", "udp-source");
} else {
dataSource = gst_element_factory_make("rtspsrc", "rtsp-source");
}
if ((caps = gst_caps_from_string("application/x-rtp, media=(string)video, clock-rate=(int)90000, encoding-name=(string)H264")) == NULL) {
qCritical() << "VideoReceiver::start() failed. Error with gst_caps_from_string()";
if (!dataSource) {
qCritical() << "VideoReceiver::start() failed. Error with data source for gst_element_factory_make()";
break;
}
g_object_set(G_OBJECT(dataSource), "uri", qPrintable(_uri), "caps", caps, NULL);
if(isUdp) {
if ((caps = gst_caps_from_string("application/x-rtp, media=(string)video, clock-rate=(int)90000, encoding-name=(string)H264")) == NULL) {
qCritical() << "VideoReceiver::start() failed. Error with gst_caps_from_string()";
break;
}
g_object_set(G_OBJECT(dataSource), "uri", qPrintable(_uri), "caps", caps, NULL);
} else {
g_object_set(G_OBJECT(dataSource), "location", qPrintable(_uri), "latency", 0, NULL);
}
if ((demux = gst_element_factory_make("rtph264depay", "rtp-h264-depacketizer")) == NULL) {
qCritical() << "VideoReceiver::start() failed. Error with gst_element_factory_make('rtph264depay')";
break;
}
if(!isUdp) {
g_signal_connect(dataSource, "pad-added", G_CALLBACK(newPadCB), demux);
}
if ((parser = gst_element_factory_make("h264parse", "h264-parser")) == NULL) {
qCritical() << "VideoReceiver::start() failed. Error with gst_element_factory_make('h264parse')";
break;
......@@ -107,7 +136,15 @@ void VideoReceiver::start()
gst_bin_add_many(GST_BIN(_pipeline), dataSource, demux, parser, decoder, _videoSink, NULL);
if (gst_element_link_many(dataSource, demux, parser, decoder, _videoSink, NULL) != (gboolean)TRUE) {
gboolean res = FALSE;
if(isUdp) {
res = gst_element_link_many(dataSource, demux, parser, decoder, _videoSink, NULL);
} else {
res = gst_element_link_many(demux, parser, decoder, _videoSink, NULL);
}
if (!res) {
qCritical() << "VideoReceiver::start() failed. Error with gst_element_link_many()";
break;
}
......
......@@ -73,8 +73,12 @@ LinuxBuild {
QMAKE_POST_LINK += $$escape_expand(\\n) xcopy \"$$GST_ROOT_WIN\\lib\\gstreamer-1.0\\validate\\*.dll\" \"$$DESTDIR_WIN\\gstreamer-plugins\\validate\\\" /Y $$escape_expand(\\n)
}
} else:AndroidBuild {
#- gstreamer assumed to be installed in $$PWD/../../android/gstreamer-1.0-android-armv7-1.5.2
GST_ROOT = $$PWD/../../gstreamer-1.0-android-armv7-1.5.2
#- gstreamer assumed to be installed in $$PWD/../../android/gstreamer-1.0-android-armv7-1.5.2 (or x86)
Androidx86Build {
GST_ROOT = $$PWD/../../gstreamer-1.0-android-x86-1.5.2
} else {
GST_ROOT = $$PWD/../../gstreamer-1.0-android-armv7-1.5.2
}
exists($$GST_ROOT) {
QMAKE_CXXFLAGS += -pthread
CONFIG += VideoEnabled
......
......@@ -27,6 +27,7 @@ VideoSurface::VideoSurface(QObject *parent)
#if defined(QGC_GST_STREAMING)
, _data(new VideoSurfacePrivate)
, _lastFrame(0)
, _refed(false)
#endif
{
}
......@@ -34,7 +35,7 @@ VideoSurface::VideoSurface(QObject *parent)
VideoSurface::~VideoSurface()
{
#if defined(QGC_GST_STREAMING)
if (_data->videoSink != NULL) {
if (!_refed && _data->videoSink != NULL) {
gst_element_set_state(_data->videoSink, GST_STATE_NULL);
}
delete _data;
......@@ -42,7 +43,7 @@ VideoSurface::~VideoSurface()
}
#if defined(QGC_GST_STREAMING)
GstElement* VideoSurface::videoSink() const
GstElement* VideoSurface::videoSink()
{
if (_data->videoSink == NULL) {
if ((_data->videoSink = gst_element_factory_make("qtquick2videosink", NULL)) == NULL) {
......@@ -50,6 +51,7 @@ GstElement* VideoSurface::videoSink() const
return NULL;
}
g_signal_connect(_data->videoSink, "update", G_CALLBACK(onUpdateThunk), (void* )this);
_refed = true;
}
return _data->videoSink;
}
......
......@@ -40,7 +40,7 @@ public:
* is called. The surface will always keep a reference to this element.
*/
#if defined(QGC_GST_STREAMING)
GstElement* videoSink() const;
GstElement* videoSink();
time_t lastFrame() { return _lastFrame; }
void setLastFrame(time_t t) { _lastFrame = t; }
#endif
......@@ -55,7 +55,8 @@ private:
friend class VideoItem;
#if defined(QGC_GST_STREAMING)
VideoSurfacePrivate * const _data;
time_t _lastFrame;
time_t _lastFrame;
bool _refed;
#endif
};
......
......@@ -27,7 +27,7 @@
#include "gstqwidgetvideosink.h"
#define PACKAGE "mini-qt-gstreamer"
#define PACKAGE_NAME "QgcQtGStreamer"
#define PACKAGE_NAME "QgcQtGStreamer"
#define PACKAGE_ORIGIN "http://gstreamer.freedesktop.org/"
#define PACKAGE_VERSION "1.2.0"
......@@ -44,7 +44,7 @@ static gboolean plugin_init(GstPlugin *plugin)
G_STRINGIFY(QGC_VIDEOSINK_PLUGIN), 0,
"Debug category for GstQtVideoSink");
if(!gst_element_register(plugin, G_STRINGIFY(QGC_VIDEOSINK_PLUGIN),
if(!gst_element_register(plugin, G_STRINGIFY(QGC_VIDEOSINK_PLUGIN),
GST_RANK_NONE, GST_TYPE_QT_VIDEO_SINK)) {
GST_ERROR("Failed to register " G_STRINGIFY(QGC_VIDEOSINK_PLUGIN));
return FALSE;
......
......@@ -31,493 +31,546 @@ QGCView {
anchors.margins: ScreenTools.defaultFontPixelWidth
property Fact _percentRemainingAnnounce: QGroundControl.batteryPercentRemainingAnnounce
property real _editFieldWidth: ScreenTools.defaultFontPixelWidth * 20
property real _labelWidth: ScreenTools.defaultFontPixelWidth * 15
property real _editFieldWidth: ScreenTools.defaultFontPixelWidth * 30
QGCPalette { id: qgcPal }
QGCViewPanel {
id: panel
anchors.fill: parent
QGCFlickable {
clip: true
anchors.fill: parent
contentHeight: settingsColumn.height
contentWidth: settingsColumn.width
Column {
id: settingsColumn
width: qgcView.width
spacing: ScreenTools.defaultFontPixelHeight * 0.5
anchors.margins: ScreenTools.defaultFontPixelWidth
spacing: ScreenTools.defaultFontPixelHeight / 2
//-----------------------------------------------------------------
//-- Base UI Font Point Size
Row {
spacing: ScreenTools.defaultFontPixelWidth
//-- Units
Item {
width: qgcView.width * 0.8
height: unitLabel.height
anchors.margins: ScreenTools.defaultFontPixelWidth
anchors.horizontalCenter: parent.horizontalCenter
QGCLabel {
id: baseFontLabel
text: qsTr("Base UI font size:")
anchors.verticalCenter: parent.verticalCenter
id: unitLabel
text: qsTr("Units (Requires Restart)")
font.family: ScreenTools.demiboldFontFamily
}
Row {
id: baseFontRow
spacing: ScreenTools.defaultFontPixelWidth / 2
anchors.verticalCenter: parent.verticalCenter
QGCButton {
id: decrementButton
width: height
height: baseFontEdit.height
text: "-"
onClicked: {
if(ScreenTools.defaultFontPointSize > 6) {
QGroundControl.baseFontPointSize = QGroundControl.baseFontPointSize - 1
}
}
Rectangle {
height: unitsCol.height + (ScreenTools.defaultFontPixelHeight * 2)
width: qgcView.width * 0.8
color: qgcPal.windowShade
anchors.margins: ScreenTools.defaultFontPixelWidth
anchors.horizontalCenter: parent.horizontalCenter
Column {
id: unitsCol
spacing: ScreenTools.defaultFontPixelWidth
anchors.centerIn: parent
Row {
spacing: ScreenTools.defaultFontPixelWidth
QGCLabel {
width: _labelWidth
anchors.baseline: distanceUnitsCombo.baseline
text: qsTr("Distance:")
}
FactComboBox {
id: distanceUnitsCombo
width: _editFieldWidth
fact: QGroundControl.distanceUnits
indexModel: false
}
}
QGCTextField {
id: baseFontEdit
width: _editFieldWidth - (decrementButton.width * 2) - (baseFontRow.spacing * 2)
text: QGroundControl.baseFontPointSize
showUnits: true
unitsLabel: "pt"
maximumLength: 6
validator: DoubleValidator {bottom: 6.0; top: 48.0; decimals: 2;}
onEditingFinished: {
var point = parseFloat(text)
if(point >= 6.0 && point <= 48.0)
QGroundControl.baseFontPointSize = point;
Row {
spacing: ScreenTools.defaultFontPixelWidth
QGCLabel {
width: _labelWidth
anchors.baseline: areaUnitsCombo.baseline
text: qsTr("Area:")
}
FactComboBox {
id: areaUnitsCombo
width: _editFieldWidth
fact: QGroundControl.areaUnits
indexModel: false
}
}
QGCButton {
width: height
height: baseFontEdit.height
text: "+"
onClicked: {
if(ScreenTools.defaultFontPointSize < 49) {
QGroundControl.baseFontPointSize = QGroundControl.baseFontPointSize + 1
}
Row {
spacing: ScreenTools.defaultFontPixelWidth
QGCLabel {
width: _labelWidth
anchors.baseline: speedUnitsCombo.baseline
text: qsTr("Speed:")
}
FactComboBox {
id: speedUnitsCombo
width: _editFieldWidth
fact: QGroundControl.speedUnits
indexModel: false
}
}
}
QGCLabel {
anchors.verticalCenter: parent.verticalCenter
text: qsTr("(requires app restart)")
}
}
//-----------------------------------------------------------------
//-- Units
Row {
spacing: ScreenTools.defaultFontPixelWidth
QGCLabel {
width: baseFontLabel.width
anchors.baseline: distanceUnitsCombo.baseline
text: qsTr("Distance units:")
}
FactComboBox {
id: distanceUnitsCombo
width: _editFieldWidth
fact: QGroundControl.distanceUnits
indexModel: false
}
QGCLabel {
anchors.baseline: distanceUnitsCombo.baseline
text: qsTr("(requires app restart)")
}
}
Row {
spacing: ScreenTools.defaultFontPixelWidth
QGCLabel {
width: baseFontLabel.width
anchors.baseline: areaUnitsCombo.baseline
text: qsTr("Area units:")
}
FactComboBox {
id: areaUnitsCombo
width: _editFieldWidth
fact: QGroundControl.areaUnits
indexModel: false
}
QGCLabel {
anchors.baseline: areaUnitsCombo.baseline
text: qsTr("(requires app restart)")
}
}
Row {
spacing: ScreenTools.defaultFontPixelWidth
QGCLabel {
width: baseFontLabel.width
anchors.baseline: speedUnitsCombo.baseline
text: qsTr("Speed units:")
}
FactComboBox {
id: speedUnitsCombo
width: _editFieldWidth
fact: QGroundControl.speedUnits
indexModel: false
}
QGCLabel {
anchors.baseline: speedUnitsCombo.baseline
text: qsTr("(requires app restart)")
}
}
//-- Video Source
Item {
height: ScreenTools.defaultFontPixelHeight / 2
width: parent.width
}
//-----------------------------------------------------------------
//-- Audio preferences
QGCCheckBox {
text: qsTr("Mute all audio output")
checked: QGroundControl.isAudioMuted
onClicked: {
QGroundControl.isAudioMuted = checked
}
}
//-----------------------------------------------------------------
//-- Prompt Save Log
QGCCheckBox {
id: promptSaveLog
text: qsTr("Prompt to save Flight Data Log after each flight")
checked: QGroundControl.isSaveLogPrompt
visible: !ScreenTools.isMobile
onClicked: {
QGroundControl.isSaveLogPrompt = checked
}
}
//-----------------------------------------------------------------
//-- Prompt Save even if not armed
QGCCheckBox {
text: qsTr("Prompt to save Flight Data Log even if vehicle was not armed")
checked: QGroundControl.isSaveLogPromptNotArmed
visible: !ScreenTools.isMobile
enabled: promptSaveLog.checked
onClicked: {
QGroundControl.isSaveLogPromptNotArmed = checked
width: qgcView.width * 0.8
height: videoLabel.height
anchors.margins: ScreenTools.defaultFontPixelWidth
anchors.horizontalCenter: parent.horizontalCenter
QGCLabel {
id: videoLabel
text: qsTr("Video (Requires Restart)")
font.family: ScreenTools.demiboldFontFamily
}
}
//-----------------------------------------------------------------
//-- Clear settings
QGCCheckBox {
id: clearCheck
text: qsTr("Clear all settings on next start")
checked: false
onClicked: {
checked ? clearDialog.visible = true : QGroundControl.clearDeleteAllSettingsNextBoot()
}
MessageDialog {
id: clearDialog
visible: false
icon: StandardIcon.Warning
standardButtons: StandardButton.Yes | StandardButton.No
title: qsTr("Clear Settings")
text: qsTr("All saved settings will be reset the next time you start QGroundControl. Is this really what you want?")
onYes: {
QGroundControl.deleteAllSettingsNextBoot()
clearDialog.visible = false
Rectangle {
height: videoCol.height + (ScreenTools.defaultFontPixelHeight * 2)
width: qgcView.width * 0.8
color: qgcPal.windowShade
anchors.margins: ScreenTools.defaultFontPixelWidth
anchors.horizontalCenter: parent.horizontalCenter
Column {
id: videoCol
spacing: ScreenTools.defaultFontPixelWidth
anchors.centerIn: parent
Row {
spacing: ScreenTools.defaultFontPixelWidth
QGCLabel {
anchors.baseline: videoSource.baseline
text: qsTr("Video Source:")
width: _labelWidth
}
QGCComboBox {
id: videoSource
width: _editFieldWidth
model: QGroundControl.videoManager.videoSourceList
Component.onCompleted: {
var index = videoSource.find(QGroundControl.videoManager.videoSource)
if (index >= 0) {
videoSource.currentIndex = index
}
}
onActivated: {
if (index != -1) {
currentIndex = index
QGroundControl.videoManager.videoSource = model[index]
}
}
}
}
onNo: {
clearCheck.checked = false
clearDialog.visible = false
Row {
spacing: ScreenTools.defaultFontPixelWidth
visible: QGroundControl.videoManager.isGStreamer && videoSource.currentIndex === 0
QGCLabel {
anchors.baseline: udpField.baseline
text: qsTr("UDP Port:")
width: _labelWidth
}
QGCTextField {
id: udpField
width: _editFieldWidth
text: QGroundControl.videoManager.udpPort
validator: IntValidator {bottom: 1024; top: 65535;}
inputMethodHints: Qt.ImhDigitsOnly
onEditingFinished: {
QGroundControl.videoManager.udpPort = parseInt(text)
}
}
}
}
}
//-----------------------------------------------------------------
//-- Battery talker
Row {
spacing: ScreenTools.defaultFontPixelWidth
QGCCheckBox {
id: announcePercentCheckbox
anchors.baseline: announcePercent.baseline
text: qsTr("Announce battery lower than:")
checked: _percentRemainingAnnounce.value != 0
onClicked: {
if (checked) {
_percentRemainingAnnounce.value = _percentRemainingAnnounce.defaultValueString
} else {
_percentRemainingAnnounce.value = 0
Row {
spacing: ScreenTools.defaultFontPixelWidth
visible: QGroundControl.videoManager.isGStreamer && videoSource.currentIndex === 1
QGCLabel {
anchors.baseline: rtspField.baseline
text: qsTr("RTSP URL:")
width: _labelWidth
}
QGCTextField {
id: rtspField
width: _editFieldWidth
text: QGroundControl.videoManager.rtspURL
onEditingFinished: {
QGroundControl.videoManager.rtspURL = text
}
}
}
}
FactTextField {
id: announcePercent
fact: _percentRemainingAnnounce
enabled: announcePercentCheckbox.checked
}
}
Item {
height: ScreenTools.defaultFontPixelHeight / 2
width: parent.width
}
//-----------------------------------------------------------------
//-- Video Source
Row {
spacing: ScreenTools.defaultFontPixelWidth
//-- Offline mission editing
Item {
width: qgcView.width * 0.8
height: offlineLabel.height
anchors.margins: ScreenTools.defaultFontPixelWidth
anchors.horizontalCenter: parent.horizontalCenter
QGCLabel {
anchors.baseline: videoSource.baseline
text: qsTr("Video Source:")
id: offlineLabel
text: qsTr("Offline Mission Editing")
font.family: ScreenTools.demiboldFontFamily
}
QGCComboBox {
id: videoSource
width: _editFieldWidth
model: QGroundControl.videoManager.videoSourceList
Component.onCompleted: {
var index = videoSource.find(QGroundControl.videoManager.videoSource)
if (index >= 0) {
videoSource.currentIndex = index
}
Rectangle {
height: offlineCol.height + (ScreenTools.defaultFontPixelHeight * 2)
width: qgcView.width * 0.8
color: qgcPal.windowShade
anchors.margins: ScreenTools.defaultFontPixelWidth
anchors.horizontalCenter: parent.horizontalCenter
Column {
id: offlineCol
spacing: ScreenTools.defaultFontPixelWidth
anchors.centerIn: parent
Row {
spacing: ScreenTools.defaultFontPixelWidth
QGCLabel {
text: qsTr("Firmware:")
width: _labelWidth
anchors.baseline: offlineTypeCombo.baseline
}
FactComboBox {
id: offlineTypeCombo
width: _editFieldWidth
fact: QGroundControl.offlineEditingFirmwareType
indexModel: false
}
}
onActivated: {
if (index != -1) {
currentIndex = index
QGroundControl.videoManager.videoSource = model[index]
Row {
spacing: ScreenTools.defaultFontPixelWidth
QGCLabel {
text: qsTr("Vehicle:")
width: _labelWidth
anchors.baseline: offlineVehicleCombo.baseline
}
FactComboBox {
id: offlineVehicleCombo
width: _editFieldWidth
fact: QGroundControl.offlineEditingVehicleType
indexModel: false
}
}
}
}
//-----------------------------------------------------------------
//-- Map Providers
Row {
/*
TODO: Map settings should come from QGroundControl.mapEngineManager. What is currently in
QGroundControl.flightMapSettings should be moved there so all map related funtions are in
one place.
*/
spacing: ScreenTools.defaultFontPixelWidth
visible: QGroundControl.flightMapSettings.googleMapEnabled
QGCLabel {
id: mapProvidersLabel
anchors.baseline: mapProviders.baseline
text: qsTr("Map Provider:")
}
QGCComboBox {
id: mapProviders
width: _editFieldWidth
model: QGroundControl.flightMapSettings.mapProviders
Component.onCompleted: {
var index = mapProviders.find(QGroundControl.flightMapSettings.mapProvider)
if (index < 0) {
console.warn(qsTr("Active map provider not in combobox"), QGroundControl.flightMapSettings.mapProvider)
} else {
mapProviders.currentIndex = index
Row {
spacing: ScreenTools.defaultFontPixelWidth
visible: offlineVehicleCombo.currentText != "Multicopter"
QGCLabel {
text: qsTr("Cruise speed:")
width: _labelWidth
anchors.baseline: cruiseSpeedField.baseline
}
FactTextField {
id: cruiseSpeedField
width: _editFieldWidth
fact: QGroundControl.offlineEditingCruiseSpeed
enabled: true
}
}
onActivated: {
if (index != -1) {
currentIndex = index
console.log(qsTr("New map provider: ") + model[index])
QGroundControl.flightMapSettings.mapProvider = model[index]
Row {
spacing: ScreenTools.defaultFontPixelWidth
visible: offlineVehicleCombo.currentText != "Fixedwing"
QGCLabel {
id: hoverSpeedLabel
text: qsTr("Hover speed:")
width: _labelWidth
anchors.baseline: hoverSpeedField.baseline
}
FactTextField {
id: hoverSpeedField
width: _editFieldWidth
fact: QGroundControl.offlineEditingHoverSpeed
enabled: true
}
}
}
}
//-----------------------------------------------------------------
//-- Palette Styles
Row {
spacing: ScreenTools.defaultFontPixelWidth
//-- Miscelanous
Item {
width: qgcView.width * 0.8
height: miscLabel.height
anchors.margins: ScreenTools.defaultFontPixelWidth
anchors.horizontalCenter: parent.horizontalCenter
QGCLabel {
width: mapProvidersLabel.width
anchors.baseline: paletteCombo.baseline
text: qsTr("Style:")
id: miscLabel
text: qsTr("Miscelaneous")
font.family: ScreenTools.demiboldFontFamily
}
QGCComboBox {
id: paletteCombo
width: _editFieldWidth
model: [ qsTr("Indoor"), qsTr("Outdoor") ]
currentIndex: QGroundControl.isDarkStyle ? 0 : 1
onActivated: {
if (index != -1) {
currentIndex = index
QGroundControl.isDarkStyle = index === 0 ? true : false
}
Rectangle {
height: miscCol.height + (ScreenTools.defaultFontPixelHeight * 2)
width: qgcView.width * 0.8
color: qgcPal.windowShade
anchors.margins: ScreenTools.defaultFontPixelWidth
anchors.horizontalCenter: parent.horizontalCenter
Column {
id: miscCol
spacing: ScreenTools.defaultFontPixelWidth
anchors.centerIn: parent
//-----------------------------------------------------------------
//-- Base UI Font Point Size
Row {
spacing: ScreenTools.defaultFontPixelWidth
QGCLabel {
id: baseFontLabel
text: qsTr("Base UI font size:")
anchors.verticalCenter: parent.verticalCenter
}
Row {
id: baseFontRow
spacing: ScreenTools.defaultFontPixelWidth / 2
anchors.verticalCenter: parent.verticalCenter
QGCButton {
id: decrementButton
width: height
height: baseFontEdit.height
text: "-"
onClicked: {
if(ScreenTools.defaultFontPointSize > 6) {
QGroundControl.baseFontPointSize = QGroundControl.baseFontPointSize - 1
}
}
}
QGCTextField {
id: baseFontEdit
width: _editFieldWidth - (decrementButton.width * 2) - (baseFontRow.spacing * 2)
text: QGroundControl.baseFontPointSize
showUnits: true
unitsLabel: "pt"
maximumLength: 6
validator: DoubleValidator {bottom: 6.0; top: 48.0; decimals: 2;}
onEditingFinished: {
var point = parseFloat(text)
if(point >= 6.0 && point <= 48.0)
QGroundControl.baseFontPointSize = point;
}
}
QGCButton {
width: height
height: baseFontEdit.height
text: "+"
onClicked: {
if(ScreenTools.defaultFontPointSize < 49) {
QGroundControl.baseFontPointSize = QGroundControl.baseFontPointSize + 1
}
}
}
}
QGCLabel {
anchors.verticalCenter: parent.verticalCenter
text: qsTr("(Requires Restart)")
}
}
//-----------------------------------------------------------------
//-- Audio preferences
QGCCheckBox {
text: qsTr("Mute all audio output")
checked: QGroundControl.isAudioMuted
onClicked: {
QGroundControl.isAudioMuted = checked
}
}
//-----------------------------------------------------------------
//-- Prompt Save Log
QGCCheckBox {
id: promptSaveLog
text: qsTr("Prompt to save Flight Data Log after each flight")
checked: QGroundControl.isSaveLogPrompt
visible: !ScreenTools.isMobile
onClicked: {
QGroundControl.isSaveLogPrompt = checked
}
}
//-----------------------------------------------------------------
//-- Prompt Save even if not armed
QGCCheckBox {
text: qsTr("Prompt to save Flight Data Log even if vehicle was not armed")
checked: QGroundControl.isSaveLogPromptNotArmed
visible: !ScreenTools.isMobile
enabled: promptSaveLog.checked
onClicked: {
QGroundControl.isSaveLogPromptNotArmed = checked
}
}
//-----------------------------------------------------------------
//-- Clear settings
QGCCheckBox {
id: clearCheck
text: qsTr("Clear all settings on next start")
checked: false
onClicked: {
checked ? clearDialog.visible = true : QGroundControl.clearDeleteAllSettingsNextBoot()
}
MessageDialog {
id: clearDialog
visible: false
icon: StandardIcon.Warning
standardButtons: StandardButton.Yes | StandardButton.No
title: qsTr("Clear Settings")
text: qsTr("All saved settings will be reset the next time you start QGroundControl. Is this really what you want?")
onYes: {
QGroundControl.deleteAllSettingsNextBoot()
clearDialog.visible = false
}
onNo: {
clearCheck.checked = false
clearDialog.visible = false
}
}
}
//-----------------------------------------------------------------
//-- Battery talker
Row {
spacing: ScreenTools.defaultFontPixelWidth
QGCCheckBox {
id: announcePercentCheckbox
anchors.verticalCenter: parent.verticalCenter
text: qsTr("Announce battery lower than:")
checked: _percentRemainingAnnounce.value != 0
onClicked: {
if (checked) {
_percentRemainingAnnounce.value = _percentRemainingAnnounce.defaultValueString
} else {
_percentRemainingAnnounce.value = 0
}
}
}
FactTextField {
id: announcePercent
fact: _percentRemainingAnnounce
enabled: announcePercentCheckbox.checked
anchors.verticalCenter: parent.verticalCenter
}
}
//-----------------------------------------------------------------
//-- Virtual joystick settings
QGCCheckBox {
text: qsTr("Virtual Joystick")
checked: QGroundControl.virtualTabletJoystick
onClicked: QGroundControl.virtualTabletJoystick = checked
}
//-----------------------------------------------------------------
//-- Map Providers
Row {
/*
TODO: Map settings should come from QGroundControl.mapEngineManager. What is currently in
QGroundControl.flightMapSettings should be moved there so all map related funtions are in
one place.
*/
spacing: ScreenTools.defaultFontPixelWidth
visible: QGroundControl.flightMapSettings.googleMapEnabled
QGCLabel {
id: mapProvidersLabel
anchors.baseline: mapProviders.baseline
text: qsTr("Map Provider:")
width: _labelWidth
}
QGCComboBox {
id: mapProviders
width: _editFieldWidth
model: QGroundControl.flightMapSettings.mapProviders
Component.onCompleted: {
var index = mapProviders.find(QGroundControl.flightMapSettings.mapProvider)
if (index < 0) {
console.warn(qsTr("Active map provider not in combobox"), QGroundControl.flightMapSettings.mapProvider)
} else {
mapProviders.currentIndex = index
}
}
onActivated: {
if (index != -1) {
currentIndex = index
console.log(qsTr("New map provider: ") + model[index])
QGroundControl.flightMapSettings.mapProvider = model[index]
}
}
}
}
//-----------------------------------------------------------------
//-- Palette Styles
Row {
spacing: ScreenTools.defaultFontPixelWidth
QGCLabel {
anchors.baseline: paletteCombo.baseline
text: qsTr("Style:")
width: _labelWidth
}
QGCComboBox {
id: paletteCombo
width: _editFieldWidth
model: [ qsTr("Indoor"), qsTr("Outdoor") ]
currentIndex: QGroundControl.isDarkStyle ? 0 : 1
onActivated: {
if (index != -1) {
currentIndex = index
QGroundControl.isDarkStyle = index === 0 ? true : false
}
}
}
}
}
}
Item {
height: ScreenTools.defaultFontPixelHeight / 2
width: parent.width
}
//-----------------------------------------------------------------
//-- Autoconnect settings
QGCLabel { text: "Autoconnect to the following devices:" }
Row {
spacing: ScreenTools.defaultFontPixelWidth * 2
QGCCheckBox {
text: qsTr("Pixhawk")
visible: !ScreenTools.isiOS
checked: QGroundControl.linkManager.autoconnectPixhawk
onClicked: QGroundControl.linkManager.autoconnectPixhawk = checked
}
QGCCheckBox {
text: qsTr("SiK Radio")
visible: !ScreenTools.isiOS
checked: QGroundControl.linkManager.autoconnect3DRRadio
onClicked: QGroundControl.linkManager.autoconnect3DRRadio = checked
}
QGCCheckBox {
text: qsTr("PX4 Flow")
visible: !ScreenTools.isiOS
checked: QGroundControl.linkManager.autoconnectPX4Flow
onClicked: QGroundControl.linkManager.autoconnectPX4Flow = checked
}
QGCCheckBox {
text: qsTr("UDP")
checked: QGroundControl.linkManager.autoconnectUDP
onClicked: QGroundControl.linkManager.autoconnectUDP = checked
}
QGCCheckBox {
text: qsTr("RTK GPS")
checked: QGroundControl.linkManager.autoconnectRTKGPS
onClicked: QGroundControl.linkManager.autoconnectRTKGPS = checked
}
}
Item {
height: ScreenTools.defaultFontPixelHeight / 2
width: parent.width
}
//-----------------------------------------------------------------
//-- Virtual joystick settings
QGCCheckBox {
text: qsTr("Virtual Joystick")
checked: QGroundControl.virtualTabletJoystick
onClicked: QGroundControl.virtualTabletJoystick = checked
}
Item {
height: ScreenTools.defaultFontPixelHeight / 2
width: parent.width
}
//-----------------------------------------------------------------
//-- Offline mission editing settings
QGCLabel { text: "Offline mission editing" }
Row {
spacing: ScreenTools.defaultFontPixelWidth
QGCLabel {
text: qsTr("Firmware:")
width: hoverSpeedLabel.width
anchors.baseline: offlineTypeCombo.baseline
}
FactComboBox {
id: offlineTypeCombo
width: ScreenTools.defaultFontPixelWidth * 18
fact: QGroundControl.offlineEditingFirmwareType
indexModel: false
}
}
Row {
spacing: ScreenTools.defaultFontPixelWidth
width: qgcView.width * 0.8
height: autoConnectLabel.height
anchors.margins: ScreenTools.defaultFontPixelWidth
anchors.horizontalCenter: parent.horizontalCenter
QGCLabel {
text: qsTr("Vehicle:")
width: hoverSpeedLabel.width
anchors.baseline: offlineVehicleCombo.baseline
}
FactComboBox {
id: offlineVehicleCombo
width: offlineTypeCombo.width
fact: QGroundControl.offlineEditingVehicleType
indexModel: false
id: autoConnectLabel
text: qsTr("Autoconnect to the following devices:")
font.family: ScreenTools.demiboldFontFamily
}
}
Row {
spacing: ScreenTools.defaultFontPixelWidth
visible: offlineVehicleCombo.currentText != "Multicopter"
QGCLabel {
text: qsTr("Cruise speed:")
width: hoverSpeedLabel.width
anchors.baseline: cruiseSpeedField.baseline
}
FactTextField {
id: cruiseSpeedField
width: offlineTypeCombo.width
fact: QGroundControl.offlineEditingCruiseSpeed
enabled: true
}
}
Row {
spacing: ScreenTools.defaultFontPixelWidth
visible: offlineVehicleCombo.currentText != "Fixedwing"
QGCLabel {
id: hoverSpeedLabel
text: qsTr("Hover speed:")
width: baseFontLabel.width
anchors.baseline: hoverSpeedField.baseline
}
FactTextField {
id: hoverSpeedField
width: offlineTypeCombo.width
fact: QGroundControl.offlineEditingHoverSpeed
enabled: true
Rectangle {
height: autoConnectCol.height + (ScreenTools.defaultFontPixelHeight * 2)
width: qgcView.width * 0.8
color: qgcPal.windowShade
anchors.margins: ScreenTools.defaultFontPixelWidth
anchors.horizontalCenter: parent.horizontalCenter
Column {
id: autoConnectCol
spacing: ScreenTools.defaultFontPixelWidth
anchors.centerIn: parent
//-----------------------------------------------------------------
//-- Autoconnect settings
Row {
spacing: ScreenTools.defaultFontPixelWidth * 2
QGCCheckBox {
text: qsTr("Pixhawk")
visible: !ScreenTools.isiOS
checked: QGroundControl.linkManager.autoconnectPixhawk
onClicked: QGroundControl.linkManager.autoconnectPixhawk = checked
}
QGCCheckBox {
text: qsTr("SiK Radio")
visible: !ScreenTools.isiOS
checked: QGroundControl.linkManager.autoconnect3DRRadio
onClicked: QGroundControl.linkManager.autoconnect3DRRadio = checked
}
QGCCheckBox {
text: qsTr("PX4 Flow")
visible: !ScreenTools.isiOS
checked: QGroundControl.linkManager.autoconnectPX4Flow
onClicked: QGroundControl.linkManager.autoconnectPX4Flow = checked
}
QGCCheckBox {
text: qsTr("UDP")
checked: QGroundControl.linkManager.autoconnectUDP
onClicked: QGroundControl.linkManager.autoconnectUDP = checked
}
QGCCheckBox {
text: qsTr("RTK GPS")
checked: QGroundControl.linkManager.autoconnectRTKGPS
onClicked: QGroundControl.linkManager.autoconnectRTKGPS = checked
}
}
}
}
Item {
height: ScreenTools.defaultFontPixelHeight / 2
width: parent.width
}
}
}
} // settingsColumn
} // QGCFlickable
} // QGCViewPanel
} // QGCView
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