diff --git a/QGCCommon.pri b/QGCCommon.pri
index bf0a81b612e9bdea6cbef887b3e3b5a53be9432e..345aa8e076c27a5c739565b98bfb8e021b987e15 100644
--- a/QGCCommon.pri
+++ b/QGCCommon.pri
@@ -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 {
diff --git a/qgroundcontrol.pro b/qgroundcontrol.pro
index 320cc7595404cac7e22f70c152c3e09f47c7f884..3d84270e147018eba19d923005ef78c6e70289b8 100644
--- a/qgroundcontrol.pro
+++ b/qgroundcontrol.pro
@@ -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
}
diff --git a/qgroundcontrol.qrc b/qgroundcontrol.qrc
index 8f9bbf04e8d72dcd9f3c908c02a2dd0dfe60c393..79e71888df79f1dc375f2eadbef137b2e5f25d37 100644
--- a/qgroundcontrol.qrc
+++ b/qgroundcontrol.qrc
@@ -15,6 +15,8 @@
src/ViewWidgets/LogDownload.qml
src/VehicleSetup/FirmwareUpgrade.qml
src/FlightDisplay/FlightDisplayView.qml
+ src/FlightDisplay/FlightDisplayViewUVC.qml
+ src/FlightDisplay/FlightDisplayViewDummy.qml
src/AutoPilotPlugins/PX4/PX4FlightModes.qml
src/AutoPilotPlugins/PX4/PX4AdvancedFlightModes.qml
src/AutoPilotPlugins/PX4/PX4SimpleFlightModes.qml
diff --git a/src/FlightDisplay/FlightDisplayView.qml b/src/FlightDisplay/FlightDisplayView.qml
index b8be023456dbf4a733b55186cf4f3818082a3c11..d66428385e64a468db0ed0e7a899ce27c85b61e2 100644
--- a/src/FlightDisplay/FlightDisplayView.qml
+++ b/src/FlightDisplay/FlightDisplayView.qml
@@ -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"
}
}
diff --git a/src/FlightDisplay/FlightDisplayViewDummy.qml b/src/FlightDisplay/FlightDisplayViewDummy.qml
new file mode 100644
index 0000000000000000000000000000000000000000..286c321432ca8995364e01c30fb4ebff1b8f1cb6
--- /dev/null
+++ b/src/FlightDisplay/FlightDisplayViewDummy.qml
@@ -0,0 +1,15 @@
+/****************************************************************************
+ *
+ * (c) 2009-2016 QGROUNDCONTROL PROJECT
+ *
+ * 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)
+}
diff --git a/src/FlightDisplay/FlightDisplayViewUVC.qml b/src/FlightDisplay/FlightDisplayViewUVC.qml
new file mode 100644
index 0000000000000000000000000000000000000000..f9608320557348951e12a495a9afae4d7f507d1e
--- /dev/null
+++ b/src/FlightDisplay/FlightDisplayViewUVC.qml
@@ -0,0 +1,35 @@
+/****************************************************************************
+ *
+ * (c) 2009-2016 QGROUNDCONTROL PROJECT
+ *
+ * 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()
+ }
+}
diff --git a/src/FlightDisplay/FlightDisplayViewVideo.qml b/src/FlightDisplay/FlightDisplayViewVideo.qml
index 653f8ab2fb4faa83bf720cc478bc4bff5499f2ab..2b82520948f95229ad601ed5dd3d44af33c716e5 100644
--- a/src/FlightDisplay/FlightDisplayViewVideo.qml
+++ b/src/FlightDisplay/FlightDisplayViewVideo.qml
@@ -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
diff --git a/src/FlightDisplay/VideoManager.cc b/src/FlightDisplay/VideoManager.cc
index 9739d4f08ca7d92334143ac15abe561fd066a290..b8a1f7c8103811510e2d29527f89ff272b25c990 100644
--- a/src/FlightDisplay/VideoManager.cc
+++ b/src/FlightDisplay/VideoManager.cc
@@ -19,51 +19,36 @@
#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";
+#if defined(QGC_GST_STREAMING)
+static const char* kRTSPStream = "RTSP Video Stream";
+#endif
+static const char* kNoVideo = "No Video Available";
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,20 +81,32 @@ 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)
{
+ if(vSource == kNoVideo)
+ return;
_videoSource = vSource;
QSettings settings;
settings.setValue(kVideoSourceKey, vSource);
emit videoSourceChanged();
+#ifndef QGC_DISABLE_UVC
QList cameras = QCameraInfo::availableCameras();
foreach (const QCameraInfo &cameraInfo, cameras) {
if(cameraInfo.description() == vSource) {
@@ -119,8 +116,51 @@ VideoManager::setVideoSource(QString vSource)
break;
}
}
+#endif
emit isGStreamerChanged();
qCDebug(VideoManagerLog) << "New Video Source:" << vSource;
+ /*
+ * Not working. Requires restart for now. (Undef KRTSP/kUDP above when enabling this)
+ 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. (Undef KRTSP/kUDP above when enabling this)
+ 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. (Undef KRTSP/kUDP above when enabling this)
+ if(_videoSource == kRTSPStream)
+ _updateVideo();
+ */
}
//-----------------------------------------------------------------------------
@@ -129,20 +169,25 @@ VideoManager::videoSourceList()
{
_videoSourceList.clear();
#if defined(QGC_GST_STREAMING)
- _videoSourceList.append(kGStreamerSource);
+ _videoSourceList.append(kUDPStream);
+ _videoSourceList.append(kRTSPStream);
#endif
+#ifndef QGC_DISABLE_UVC
QList cameras = QCameraInfo::availableCameras();
foreach (const QCameraInfo &cameraInfo, cameras) {
qCDebug(VideoManagerLog) << "UVC Video source ID:" << cameraInfo.deviceName() << " Name:" << cameraInfo.description();
_videoSourceList.append(cameraInfo.description());
}
+#endif
+ if(_videoSourceList.count() == 0)
+ _videoSourceList.append(kNoVideo);
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 +195,7 @@ void VideoManager::_updateTimer(void)
{
elapsed = time(0) - _videoSurface->lastFrame();
}
- if(elapsed > 2)
+ if(elapsed > 2 && _videoSurface)
{
_videoRunning = false;
_videoSurface->setLastFrame(0);
@@ -167,5 +212,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);
+ #if defined(QGC_GST_STREAMING)
+ _videoReceiver->setVideoSink(_videoSurface->videoSink());
+ if(_videoSource == kUDPStream)
+ _videoReceiver->setUri(QStringLiteral("udp://0.0.0.0:%1").arg(_udpPort));
+ else
+ _videoReceiver->setUri(_rtspURL);
+ #endif
+ _videoReceiver->start();
+ }
+}
diff --git a/src/FlightDisplay/VideoManager.h b/src/FlightDisplay/VideoManager.h
index 2a249f0e9c679ff2015f4346e9a00105e6130d99..2ff5cfac6e476c9eea7b5c16c2c5fa9408bc2406 100644
--- a/src/FlightDisplay/VideoManager.h
+++ b/src/FlightDisplay/VideoManager.h
@@ -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
diff --git a/src/FlightMap/QGCVideoBackground.qml b/src/FlightMap/QGCVideoBackground.qml
index 842bc9f7dcd4111c3bf3dd5e5e8cd5e3bf2a022e..4a99d6da368f6c7ba0d680cd36e8291eb8bea5e4 100644
--- a/src/FlightMap/QGCVideoBackground.qml
+++ b/src/FlightMap/QGCVideoBackground.qml
@@ -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();
- }
- }
}
diff --git a/src/VideoStreaming/VideoReceiver.cc b/src/VideoStreaming/VideoReceiver.cc
index b637700c23a83cdb93cfb77859757a9c9ab2ce30..520aa48b279351f84ad9fec61a9be0d7711136a4 100644
--- a/src/VideoStreaming/VideoReceiver.cc
+++ b/src/VideoStreaming/VideoReceiver.cc
@@ -49,6 +49,23 @@ void VideoReceiver::setVideoSink(GstElement* sink)
}
#endif
+#if defined(QGC_GST_STREAMING)
+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);
+}
+#endif
+
void VideoReceiver::start()
{
#if defined(QGC_GST_STREAMING)
@@ -56,7 +73,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 +88,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 +138,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;
}
diff --git a/src/VideoStreaming/VideoStreaming.pri b/src/VideoStreaming/VideoStreaming.pri
index 1b967c8f55f86715c5839988b904a1f4b3eb5aa6..03a3bc1bb0add0b350a230d152ada34936dcc370 100644
--- a/src/VideoStreaming/VideoStreaming.pri
+++ b/src/VideoStreaming/VideoStreaming.pri
@@ -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
diff --git a/src/VideoStreaming/VideoSurface.cc b/src/VideoStreaming/VideoSurface.cc
index 7c153f5facc4bc6f3abc4b4cf1ff1e0e33fc02bd..77fb96ab988b51a1c5db77aeba67f535217df8c0 100644
--- a/src/VideoStreaming/VideoSurface.cc
+++ b/src/VideoStreaming/VideoSurface.cc
@@ -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;
}
diff --git a/src/VideoStreaming/VideoSurface.h b/src/VideoStreaming/VideoSurface.h
index 964f7f497e9f1fc96a8f1c5a7f3a93586101061f..1f84e7966442ad53c0a63ccda8ee7c56b6b65949 100644
--- a/src/VideoStreaming/VideoSurface.h
+++ b/src/VideoStreaming/VideoSurface.h
@@ -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
};
diff --git a/src/VideoStreaming/gstqtvideosink/gstqtvideosinkplugin.cpp b/src/VideoStreaming/gstqtvideosink/gstqtvideosinkplugin.cpp
index 77bb1e90b04ee97c23b49d403180e37f40f93e9b..132f60764980d8474b634d58f22042cf52ae3c11 100644
--- a/src/VideoStreaming/gstqtvideosink/gstqtvideosinkplugin.cpp
+++ b/src/VideoStreaming/gstqtvideosink/gstqtvideosinkplugin.cpp
@@ -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;
diff --git a/src/ui/preferences/GeneralSettings.qml b/src/ui/preferences/GeneralSettings.qml
index 1044e9155c1be915b87bcbeff11436400f13be19..1a119646a07f8fefdfb5c4edd695162073ecd377 100644
--- a/src/ui/preferences/GeneralSettings.qml
+++ b/src/ui/preferences/GeneralSettings.qml
@@ -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