diff --git a/.travis.yml b/.travis.yml
index c42feb37c27c4d0838c27aaafbc3585071fc76ce..a87e984ec72da807ed970d0b66ad1a61b21ee191 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -83,7 +83,7 @@ install:
# android dependencies: qt, gstreamer, android-ndk
- if [ "${SPEC}" = "android-g++" ]; then
- wget --quiet http://www.grubba.com/gstreamer-1.0-android-universal-1.14.4.tar.bz2 &&
+ wget --quiet https://s3-us-west-2.amazonaws.com/qgroundcontrol/dependencies/gstreamer-1.0-android-universal-1.14.4.tar.bz2 &&
tar jxf gstreamer-1.0-android-universal-1.14.4.tar.bz2 -C ${TRAVIS_BUILD_DIR} &&
wget --quiet https://s3-us-west-2.amazonaws.com/qgroundcontrol/dependencies/Qt5.11.0-android_armv7-min.tar.bz2 &&
tar jxf Qt5.11.0-android_armv7-min.tar.bz2 -C /tmp &&
diff --git a/QGCExternalLibs.pri b/QGCExternalLibs.pri
index 656935fd5e3de5d6fe0d8eb7c428fdd178cded0c..0c9fc138827a5d1a33f70fa9b519c68ace018bd3 100644
--- a/QGCExternalLibs.pri
+++ b/QGCExternalLibs.pri
@@ -132,6 +132,16 @@ MacBuild {
-lSDL2
}
+AndroidBuild {
+ contains(QT_ARCH, arm) {
+ ANDROID_EXTRA_LIBS += $$BASEDIR/libs/AndroidOpenSSL/arch-armeabi-v7a/lib/libcrypto.so
+ ANDROID_EXTRA_LIBS += $$BASEDIR/libs/AndroidOpenSSL/arch-armeabi-v7a/lib/libssl.so
+ } else {
+ ANDROID_EXTRA_LIBS += $$BASEDIR/libs/AndroidOpenSSL/arch-x86/lib/libcrypto.so
+ ANDROID_EXTRA_LIBS += $$BASEDIR/libs/AndroidOpenSSL/arch-x86/lib/libssl.so
+ }
+}
+
#
# [OPTIONAL] Zeroconf for UDP links
#
diff --git a/android/AndroidManifest.xml b/android/AndroidManifest.xml
index beddd03b6cc1420a604282d0812968789c0eb244..b696cd71962d92d408efa6679437f250db30a301 100644
--- a/android/AndroidManifest.xml
+++ b/android/AndroidManifest.xml
@@ -71,6 +71,8 @@
+
+
diff --git a/libs/AndroidOpenSSL/README.md b/libs/AndroidOpenSSL/README.md
new file mode 100644
index 0000000000000000000000000000000000000000..3ba978a556b2f9d72aed99cda64f455a0f218d80
--- /dev/null
+++ b/libs/AndroidOpenSSL/README.md
@@ -0,0 +1 @@
+These OpenSLL libraries foir Android are built using the scripts found here: https://github.com/esutton/android-openssl
\ No newline at end of file
diff --git a/libs/AndroidOpenSSL/arch-armeabi-v7a/lib/libcrypto.a b/libs/AndroidOpenSSL/arch-armeabi-v7a/lib/libcrypto.a
new file mode 100644
index 0000000000000000000000000000000000000000..40c26e62fee2e255809fe7f31913b9c2485ee0de
Binary files /dev/null and b/libs/AndroidOpenSSL/arch-armeabi-v7a/lib/libcrypto.a differ
diff --git a/libs/AndroidOpenSSL/arch-armeabi-v7a/lib/libcrypto.so b/libs/AndroidOpenSSL/arch-armeabi-v7a/lib/libcrypto.so
new file mode 100755
index 0000000000000000000000000000000000000000..293c784ebeaff80890ce95bc1e826506165a2d61
Binary files /dev/null and b/libs/AndroidOpenSSL/arch-armeabi-v7a/lib/libcrypto.so differ
diff --git a/libs/AndroidOpenSSL/arch-armeabi-v7a/lib/libssl.a b/libs/AndroidOpenSSL/arch-armeabi-v7a/lib/libssl.a
new file mode 100644
index 0000000000000000000000000000000000000000..f077c80d04df19f7879b84a55f8db0783045d724
Binary files /dev/null and b/libs/AndroidOpenSSL/arch-armeabi-v7a/lib/libssl.a differ
diff --git a/libs/AndroidOpenSSL/arch-armeabi-v7a/lib/libssl.so b/libs/AndroidOpenSSL/arch-armeabi-v7a/lib/libssl.so
new file mode 100755
index 0000000000000000000000000000000000000000..805a33e63dbb3b093b18df02c9ba7995da9c2b74
Binary files /dev/null and b/libs/AndroidOpenSSL/arch-armeabi-v7a/lib/libssl.so differ
diff --git a/libs/AndroidOpenSSL/arch-x86/lib/libcrypto.a b/libs/AndroidOpenSSL/arch-x86/lib/libcrypto.a
new file mode 100644
index 0000000000000000000000000000000000000000..6a8dae43c4453b9bf8d7c4d7b2e73f9c5050563c
Binary files /dev/null and b/libs/AndroidOpenSSL/arch-x86/lib/libcrypto.a differ
diff --git a/libs/AndroidOpenSSL/arch-x86/lib/libcrypto.so b/libs/AndroidOpenSSL/arch-x86/lib/libcrypto.so
new file mode 100755
index 0000000000000000000000000000000000000000..75525b60c05e870135bc706face52a3698305dc3
Binary files /dev/null and b/libs/AndroidOpenSSL/arch-x86/lib/libcrypto.so differ
diff --git a/libs/AndroidOpenSSL/arch-x86/lib/libssl.a b/libs/AndroidOpenSSL/arch-x86/lib/libssl.a
new file mode 100644
index 0000000000000000000000000000000000000000..15d038f70cf06767f7efb3e3960ad35ac497c44a
Binary files /dev/null and b/libs/AndroidOpenSSL/arch-x86/lib/libssl.a differ
diff --git a/libs/AndroidOpenSSL/arch-x86/lib/libssl.so b/libs/AndroidOpenSSL/arch-x86/lib/libssl.so
new file mode 100755
index 0000000000000000000000000000000000000000..17a1d6bda8ad6e3354f55f897bb2d380a3da0512
Binary files /dev/null and b/libs/AndroidOpenSSL/arch-x86/lib/libssl.so differ
diff --git a/libs/mavlink/include/mavlink/v2.0 b/libs/mavlink/include/mavlink/v2.0
index c38176a0a63556815ea117c6877ce2dd18739231..90d9b285e01fe8bfa3b4e8868ca71c5537d43302 160000
--- a/libs/mavlink/include/mavlink/v2.0
+++ b/libs/mavlink/include/mavlink/v2.0
@@ -1 +1 @@
-Subproject commit c38176a0a63556815ea117c6877ce2dd18739231
+Subproject commit 90d9b285e01fe8bfa3b4e8868ca71c5537d43302
diff --git a/src/FirmwarePlugin/APM/APMFirmwarePlugin.h b/src/FirmwarePlugin/APM/APMFirmwarePlugin.h
index 69a153ccd244ac33a72e05c37101f24fd40fd9c3..bac34679a75151a1e54e6f5e002e7603784a2a3f 100644
--- a/src/FirmwarePlugin/APM/APMFirmwarePlugin.h
+++ b/src/FirmwarePlugin/APM/APMFirmwarePlugin.h
@@ -84,6 +84,7 @@ public:
QString flightMode (uint8_t base_mode, uint32_t custom_mode) const override;
bool setFlightMode (const QString& flightMode, uint8_t* base_mode, uint32_t* custom_mode) override;
bool isGuidedMode (const Vehicle* vehicle) const override;
+ QString gotoFlightMode (void) const override { return QStringLiteral("Guided"); }
QString rtlFlightMode (void) const override { return QString("RTL"); }
QString missionFlightMode (void) const override { return QString("Auto"); }
void pauseVehicle (Vehicle* vehicle) override;
diff --git a/src/FirmwarePlugin/FirmwarePlugin.cc b/src/FirmwarePlugin/FirmwarePlugin.cc
index 057aca88f1604da82e3a5e34daa7bd08a7641b8e..db2a86969394f52d3033e41e4e42a1e4d2c43960 100644
--- a/src/FirmwarePlugin/FirmwarePlugin.cc
+++ b/src/FirmwarePlugin/FirmwarePlugin.cc
@@ -757,3 +757,8 @@ int FirmwarePlugin::versionCompare(Vehicle* vehicle, QString& compare)
int patch = versionNumbers[2].toInt();
return versionCompare(vehicle, major, minor, patch);
}
+
+QString FirmwarePlugin::gotoFlightMode(void) const
+{
+ return QString();
+}
diff --git a/src/FirmwarePlugin/FirmwarePlugin.h b/src/FirmwarePlugin/FirmwarePlugin.h
index d5c442b164a0fa21cafb74fd7c6842a16512c3ca..81d2d2abcd7e0e9a4fc87b1142ae2756b4c70a6b 100644
--- a/src/FirmwarePlugin/FirmwarePlugin.h
+++ b/src/FirmwarePlugin/FirmwarePlugin.h
@@ -114,6 +114,9 @@ public:
/// Returns whether the vehicle is in guided mode or not.
virtual bool isGuidedMode(const Vehicle* vehicle) const;
+ /// Returns the flight mode which the vehicle will be in if it is performing a goto location
+ virtual QString gotoFlightMode(void) const;
+
/// Set guided flight mode
virtual void setGuidedMode(Vehicle* vehicle, bool guidedMode);
diff --git a/src/FirmwarePlugin/PX4/PX4FirmwarePlugin.h b/src/FirmwarePlugin/PX4/PX4FirmwarePlugin.h
index fa2a4e8796a7fb35687396ec533aa2e75bbe2e2a..2c8059b61361edacda90a4d1d17947de254c05d3 100644
--- a/src/FirmwarePlugin/PX4/PX4FirmwarePlugin.h
+++ b/src/FirmwarePlugin/PX4/PX4FirmwarePlugin.h
@@ -42,6 +42,7 @@ public:
QString rtlFlightMode (void) const override { return _rtlFlightMode; }
QString landFlightMode (void) const override { return _landingFlightMode; }
QString takeControlFlightMode (void) const override { return _manualFlightMode; }
+ QString gotoFlightMode (void) const override { return _holdFlightMode; }
void pauseVehicle (Vehicle* vehicle) override;
void guidedModeRTL (Vehicle* vehicle) override;
void guidedModeLand (Vehicle* vehicle) override;
diff --git a/src/FlightDisplay/FlightDisplayView.qml b/src/FlightDisplay/FlightDisplayView.qml
index 7cc04b763e788e02ab56289f02c501a60e77d220..6c60bb2ab9e5ed8334a36eb6b8259d29bb9bfea5 100644
--- a/src/FlightDisplay/FlightDisplayView.qml
+++ b/src/FlightDisplay/FlightDisplayView.qml
@@ -488,13 +488,13 @@ QGCView {
exclusiveGroup: multiVehicleSelectorGroup
text: qsTr("Single")
checked: true
- color: mapPal.text
+ textColor: mapPal.text
}
QGCRadioButton {
exclusiveGroup: multiVehicleSelectorGroup
text: qsTr("Multi-Vehicle")
- color: mapPal.text
+ textColor: mapPal.text
}
}
diff --git a/src/FlightDisplay/FlightDisplayViewMap.qml b/src/FlightDisplay/FlightDisplayViewMap.qml
index 788c2f21273ee2e2606d179ebec1434e419fcc8f..ce8a6eaf72a965739f22a9131934921f7a22c5d7 100644
--- a/src/FlightDisplay/FlightDisplayViewMap.qml
+++ b/src/FlightDisplay/FlightDisplayViewMap.qml
@@ -295,6 +295,7 @@ FlightMap {
}
}
+ // GoTo Location visuals
MapQuickItem {
id: gotoLocationItem
visible: false
@@ -308,6 +309,22 @@ FlightMap {
label: qsTr("Goto here", "Goto here waypoint")
}
+ property bool inGotoFlightMode: _activeVehicle ? _activeVehicle.flightMode === _activeVehicle.gotoFlightMode : false
+ property var activeVehicle: _activeVehicle
+
+ onInGotoFlightModeChanged: {
+ if (!inGotoFlightMode && visible) {
+ // Hide goto indicator when vehicle falls out of guided mode
+ visible = false
+ }
+ }
+
+ onActiveVehicleChanged: {
+ if (!_activeVehicle) {
+ visible = false
+ }
+ }
+
function show(coord) {
gotoLocationItem.coordinate = coord
gotoLocationItem.visible = true
@@ -316,10 +333,17 @@ FlightMap {
function hide() {
gotoLocationItem.visible = false
}
- }
- // Orbit visuals
+ function actionConfirmed() {
+ // We leave the indicator visible. The handling for onInGuidedModeChanged will hide it.
+ }
+
+ function actionCancelled() {
+ hide()
+ }
+ }
+ // Orbit editing visuals
QGCMapCircleVisuals {
id: orbitMapCircle
mapControl: parent
@@ -328,9 +352,16 @@ FlightMap {
property alias center: _mapCircle.center
property alias clockwiseRotation: _mapCircle.clockwiseRotation
+ property var activeVehicle: _activeVehicle
readonly property real defaultRadius: 30
+ onActiveVehicleChanged: {
+ if (!_activeVehicle) {
+ visible = false
+ }
+ }
+
function show(coord) {
_mapCircle.radius.rawValue = defaultRadius
orbitMapCircle.center = coord
@@ -341,6 +372,15 @@ FlightMap {
orbitMapCircle.visible = false
}
+ function actionConfirmed() {
+ // Live orbit status is handled by telemetry so we hide here and telemetry will show again.
+ hide()
+ }
+
+ function actionCancelled() {
+ hide()
+ }
+
function radius() {
return _mapCircle.radius.rawValue
}
@@ -357,7 +397,6 @@ FlightMap {
}
// Orbit telemetry visuals
-
QGCMapCircleVisuals {
id: orbitTelemetryCircle
mapControl: parent
@@ -395,7 +434,7 @@ FlightMap {
onTriggered: {
gotoLocationItem.show(clickMenu.coord)
orbitMapCircle.hide()
- guidedActionsController.confirmAction(guidedActionsController.actionGoto, clickMenu.coord)
+ guidedActionsController.confirmAction(guidedActionsController.actionGoto, clickMenu.coord, gotoLocationItem)
}
}
@@ -406,7 +445,7 @@ FlightMap {
onTriggered: {
orbitMapCircle.show(clickMenu.coord)
gotoLocationItem.hide()
- guidedActionsController.confirmAction(guidedActionsController.actionOrbit, clickMenu.coord)
+ guidedActionsController.confirmAction(guidedActionsController.actionOrbit, clickMenu.coord, orbitMapCircle)
}
}
}
diff --git a/src/FlightDisplay/GuidedActionConfirm.qml b/src/FlightDisplay/GuidedActionConfirm.qml
index 8d36d74dc1a6688ef0e13d1164add68302237ec9..177e1944ad82a013cb151b143173a44f30027e75 100644
--- a/src/FlightDisplay/GuidedActionConfirm.qml
+++ b/src/FlightDisplay/GuidedActionConfirm.qml
@@ -34,16 +34,14 @@ Rectangle {
property int action
property var actionData
property bool hideTrigger: false
+ property var mapIndicator
property real _margins: ScreenTools.defaultFontPixelWidth
property bool _emergencyAction: action === guidedController.actionEmergencyStop
onHideTriggerChanged: {
if (hideTrigger) {
- hideTrigger = false
- altitudeSlider.visible = false
- visibleTimer.stop()
- visible = false
+ confirmCancelled()
}
}
@@ -57,6 +55,17 @@ Rectangle {
}
}
+ function confirmCancelled() {
+ altitudeSlider.visible = false
+ visible = false
+ hideTrigger = false
+ visibleTimer.stop()
+ if (mapIndicator) {
+ mapIndicator.actionCancelled()
+ mapIndicator = undefined
+ }
+ }
+
Timer {
id: visibleTimer
interval: 1000
@@ -107,12 +116,10 @@ Rectangle {
}
hideTrigger = false
guidedController.executeAction(_root.action, _root.actionData, altitudeChange)
- }
-
- onReject: {
- altitudeSlider.visible = false
- _root.visible = false
- hideTrigger = false
+ if (mapIndicator) {
+ mapIndicator.actionConfirmed()
+ mapIndicator = undefined
+ }
}
}
}
@@ -127,12 +134,10 @@ Rectangle {
source: "/res/XDelete.svg"
fillMode: Image.PreserveAspectFit
color: qgcPal.text
+
QGCMouseArea {
fillItem: parent
- onClicked: {
- altitudeSlider.visible = false
- _root.visible = false
- }
+ onClicked: confirmCancelled()
}
}
}
diff --git a/src/FlightDisplay/GuidedActionsController.qml b/src/FlightDisplay/GuidedActionsController.qml
index 58b3b68cfc4940d94c595079ceefe2cd70445f00..c099ed669c21dbabb532d645bce9cd9e7bf2e303 100644
--- a/src/FlightDisplay/GuidedActionsController.qml
+++ b/src/FlightDisplay/GuidedActionsController.qml
@@ -209,12 +209,13 @@ Item {
}
// Called when an action is about to be executed in order to confirm
- function confirmAction(actionCode, actionData) {
+ function confirmAction(actionCode, actionData, mapIndicator) {
var showImmediate = true
closeAll()
confirmDialog.action = actionCode
confirmDialog.actionData = actionData
confirmDialog.hideTrigger = true
+ confirmDialog.mapIndicator = mapIndicator
_actionData = actionData
switch (actionCode) {
case actionArm:
@@ -385,7 +386,6 @@ Item {
break
case actionOrbit:
_activeVehicle.guidedModeOrbit(orbitMapCircle.center, orbitMapCircle.radius() * (orbitMapCircle.clockwiseRotation ? 1 : -1), _activeVehicle.altitudeAMSL.rawValue + actionAltitudeChange)
- orbitMapCircle.hide()
break
case actionLandAbort:
_activeVehicle.abortLanding(50) // hardcoded value for climbOutAltitude that is currently ignored
diff --git a/src/FlightDisplay/VideoManager.cc b/src/FlightDisplay/VideoManager.cc
index 6a05f3c5e6d7c06888d258fb92a9e20b3001e524..49b7be4e64a3367fdc03db1a9d69ba400c86bf41 100644
--- a/src/FlightDisplay/VideoManager.cc
+++ b/src/FlightDisplay/VideoManager.cc
@@ -35,6 +35,7 @@ QGC_LOGGING_CATEGORY(VideoManagerLog, "VideoManagerLog")
VideoManager::VideoManager(QGCApplication* app, QGCToolbox* toolbox)
: QGCTool(app, toolbox)
{
+ _streamInfo = {};
}
//-----------------------------------------------------------------------------
@@ -164,7 +165,8 @@ VideoManager::isGStreamer()
videoSource == VideoSettings::videoSourceUDP ||
videoSource == VideoSettings::videoSourceRTSP ||
videoSource == VideoSettings::videoSourceAuto ||
- videoSource == VideoSettings::videoSourceTCP;
+ videoSource == VideoSettings::videoSourceTCP ||
+ videoSource == VideoSettings::videoSourceMPEGTS;
#else
return false;
#endif
@@ -197,14 +199,33 @@ VideoManager::_updateSettings()
{
if(!_videoSettings || !_videoReceiver)
return;
- if (_videoSettings->videoSource()->rawValue().toString() == VideoSettings::videoSourceUDP)
+ QString source = _videoSettings->videoSource()->rawValue().toString();
+ if (source == VideoSettings::videoSourceUDP)
_videoReceiver->setUri(QStringLiteral("udp://0.0.0.0:%1").arg(_videoSettings->udpPort()->rawValue().toInt()));
- else if (_videoSettings->videoSource()->rawValue().toString() == VideoSettings::videoSourceRTSP)
+ else if (source == VideoSettings::videoSourceMPEGTS)
+ _videoReceiver->setUri(QStringLiteral("mpegts://0.0.0.0:%1").arg(_videoSettings->udpPort()->rawValue().toInt()));
+ else if (source == VideoSettings::videoSourceRTSP)
_videoReceiver->setUri(_videoSettings->rtspUrl()->rawValue().toString());
- else if (_videoSettings->videoSource()->rawValue().toString() == VideoSettings::videoSourceTCP)
+ else if (source == VideoSettings::videoSourceTCP)
_videoReceiver->setUri(QStringLiteral("tcp://%1").arg(_videoSettings->tcpUrl()->rawValue().toString()));
- else if (isAutoStream())
- _videoReceiver->setUri(QString(_streamInfo.uri));
+ //-- Auto discovery
+ else if (isAutoStream()) {
+ switch(_streamInfo.type) {
+ case VIDEO_STREAM_TYPE_RTSP:
+ case VIDEO_STREAM_TYPE_TCP_MPEG:
+ _videoReceiver->setUri(QString(_streamInfo.uri));
+ break;
+ case VIDEO_STREAM_TYPE_RTPUDP:
+ _videoReceiver->setUri(QStringLiteral("udp://0.0.0.0:%1").arg(atoi(_streamInfo.uri)));
+ break;
+ case VIDEO_STREAM_TYPE_MPEG_TS_H264:
+ _videoReceiver->setUri(QStringLiteral("mpegts://0.0.0.0:%1").arg(atoi(_streamInfo.uri)));
+ break;
+ default:
+ _videoReceiver->setUri(QString(_streamInfo.uri));
+ break;
+ }
+ }
}
//-----------------------------------------------------------------------------
@@ -212,6 +233,7 @@ void
VideoManager::_restartVideo()
{
#if defined(QGC_GST_STREAMING)
+ qCDebug(VideoManagerLog) << "Restart video streaming";
if(!_videoReceiver)
return;
_videoReceiver->stop();
@@ -240,7 +262,7 @@ VideoManager::_setActiveVehicle(Vehicle* vehicle)
MAV_CMD_REQUEST_VIDEO_STREAM_INFORMATION, // Command id
false, // ShowError
1, // First camera only
- 0); // Reserved (Set to 0)
+ 1); // Request video stream information
}
}
diff --git a/src/FlightDisplay/VideoManager.h b/src/FlightDisplay/VideoManager.h
index 7fa28c42e305f38ca7c42cbf389c17fcf24d4d64..a21d1391be8305f390cd0ea525dff919b0b0b314 100644
--- a/src/FlightDisplay/VideoManager.h
+++ b/src/FlightDisplay/VideoManager.h
@@ -61,7 +61,7 @@ public:
#endif
void setfullScreen (bool f) { _fullScreen = f; emit fullScreenChanged(); }
- void setIsTaisync (bool t) { _isTaisync = t; emit isTaisyncChanged(); }
+ void setIsTaisync (bool t) { _isTaisync = t; emit isTaisyncChanged(); }
// Override from QGCTool
void setToolbox (QGCToolbox *toolbox);
diff --git a/src/MissionManager/CameraCalc.FactMetaData.json b/src/MissionManager/CameraCalc.FactMetaData.json
index 9860f5491bae0df69b62cdacc79424f00a83fcc6..2addaa89c990419b58f481d0eba245f4507e8792 100644
--- a/src/MissionManager/CameraCalc.FactMetaData.json
+++ b/src/MissionManager/CameraCalc.FactMetaData.json
@@ -18,7 +18,7 @@
"min": 0.1,
"units": "m",
"decimalPlaces": 2,
- "defaultValue": 10.0
+ "defaultValue": 50.0
},
{
"name": "ImageDensity",
@@ -27,7 +27,7 @@
"min": 0,
"units": "cm/px",
"decimalPlaces": 1,
- "defaultValue": 25
+ "defaultValue": 1.2
},
{
"name": "FrontalOverlap",
diff --git a/src/MissionManager/CameraCalc.cc b/src/MissionManager/CameraCalc.cc
index 5f15bb25e1c19e379ac03eb10c70d7cc349a7d27..c775c1b76f9733b486b2469b95fa21dc6b2557a7 100644
--- a/src/MissionManager/CameraCalc.cc
+++ b/src/MissionManager/CameraCalc.cc
@@ -127,8 +127,8 @@ void CameraCalc::_cameraNameChanged(void)
// These values are unknown for these types
fixedOrientation()->setRawValue(false);
minTriggerInterval()->setRawValue(0);
- if (isManualCamera()) {
- valueSetIsDistance()->setRawValue(false);
+ if (isManualCamera() && !valueSetIsDistance()->rawValue().toBool()) {
+ valueSetIsDistance()->setRawValue(true);
}
} else {
qWarning() << "Internal Error: Not known camera, but now manual or custom either";
diff --git a/src/MissionManager/FixedWingLandingComplexItem.cc b/src/MissionManager/FixedWingLandingComplexItem.cc
index 9e26762f0332e6b622ed682d05efdf99fa656ce4..813205af6c6bf11a3d9caf4a7a2d500d0d1794ec 100644
--- a/src/MissionManager/FixedWingLandingComplexItem.cc
+++ b/src/MissionManager/FixedWingLandingComplexItem.cc
@@ -373,7 +373,7 @@ bool FixedWingLandingComplexItem::scanForItem(QmlObjectListModel* visualItems, b
MissionItem& missionItemLand = item->missionItem();
if (missionItemLand.command() != MAV_CMD_NAV_LAND ||
!(missionItemLand.frame() == MAV_FRAME_GLOBAL_RELATIVE_ALT || missionItemLand.frame() == MAV_FRAME_GLOBAL) ||
- missionItemLand.param1() != 0 || missionItemLand.param2() != 0 || missionItemLand.param3() != 0 || missionItemLand.param4() == 1.0) {
+ missionItemLand.param1() != 0 || missionItemLand.param2() != 0 || missionItemLand.param3() != 0 || missionItemLand.param4() != 0) {
return false;
}
MAV_FRAME landPointFrame = missionItemLand.frame();
@@ -414,6 +414,7 @@ bool FixedWingLandingComplexItem::scanForItem(QmlObjectListModel* visualItems, b
}
MissionItem& missionItemDoLandStart = item->missionItem();
if (missionItemDoLandStart.command() != MAV_CMD_DO_LAND_START ||
+ missionItemDoLandStart.frame() != MAV_FRAME_MISSION ||
missionItemDoLandStart.param1() != 0 || missionItemDoLandStart.param2() != 0 || missionItemDoLandStart.param3() != 0 || missionItemDoLandStart.param4() != 0|| missionItemDoLandStart.param5() != 0|| missionItemDoLandStart.param6() != 0) {
return false;
}
diff --git a/src/MissionManager/MissionController.cc b/src/MissionManager/MissionController.cc
index f03b8fa837c947d70dd6cab72f7c2a71e1e1419a..90bebf479071fd73593f1c01c367a7eece4486fa 100644
--- a/src/MissionManager/MissionController.cc
+++ b/src/MissionManager/MissionController.cc
@@ -29,6 +29,7 @@
#include "QGCQGeoCoordinate.h"
#include "PlanMasterController.h"
#include "KML.h"
+#include "QGCCorePlugin.h"
#ifndef __mobile__
#include "MainWindow.h"
@@ -55,23 +56,24 @@ const char* MissionController::_jsonMavAutopilotKey = "MAV_AUTOPILOT";
const int MissionController::_missionFileVersion = 2;
+const QString MissionController::patternFWLandingName (tr("Fixed Wing Landing"));
+const QString MissionController::patternStructureScanName (tr("Structure Scan"));
+const QString MissionController::patternCorridorScanName (tr("Corridor Scan"));
+
MissionController::MissionController(PlanMasterController* masterController, QObject *parent)
- : PlanElementController (masterController, parent)
- , _missionManager (_managerVehicle->missionManager())
- , _missionItemCount (0)
- , _visualItems (nullptr)
- , _settingsItem (nullptr)
- , _firstItemsFromVehicle (false)
- , _itemsRequested (false)
- , _inRecalcSequence (false)
- , _surveyMissionItemName (tr("Survey"))
- , _fwLandingMissionItemName (tr("Fixed Wing Landing"))
- , _structureScanMissionItemName (tr("Structure Scan"))
- , _corridorScanMissionItemName (tr("Corridor Scan"))
- , _appSettings (qgcApp()->toolbox()->settingsManager()->appSettings())
- , _progressPct (0)
- , _currentPlanViewIndex (-1)
- , _currentPlanViewItem (nullptr)
+ : PlanElementController (masterController, parent)
+ , _missionManager (_managerVehicle->missionManager())
+ , _missionItemCount (0)
+ , _visualItems (nullptr)
+ , _settingsItem (nullptr)
+ , _firstItemsFromVehicle (false)
+ , _itemsRequested (false)
+ , _inRecalcSequence (false)
+ , _surveyMissionItemName (tr("Survey"))
+ , _appSettings (qgcApp()->toolbox()->settingsManager()->appSettings())
+ , _progressPct (0)
+ , _currentPlanViewIndex (-1)
+ , _currentPlanViewItem (nullptr)
{
_resetMissionFlightStatus();
managerVehicleChanged(_managerVehicle);
@@ -414,11 +416,11 @@ int MissionController::insertComplexMissionItem(QString itemName, QGeoCoordinate
if (itemName == _surveyMissionItemName) {
newItem = new SurveyComplexItem(_controllerVehicle, _flyView, QString() /* kmlFile */, _visualItems /* parent */);
newItem->setCoordinate(mapCenterCoordinate);
- } else if (itemName == _fwLandingMissionItemName) {
+ } else if (itemName == patternFWLandingName) {
newItem = new FixedWingLandingComplexItem(_controllerVehicle, _flyView, _visualItems /* parent */);
- } else if (itemName == _structureScanMissionItemName) {
+ } else if (itemName == patternStructureScanName) {
newItem = new StructureScanComplexItem(_controllerVehicle, _flyView, QString() /* kmlFile */, _visualItems /* parent */);
- } else if (itemName == _corridorScanMissionItemName) {
+ } else if (itemName == patternCorridorScanName) {
newItem = new CorridorScanComplexItem(_controllerVehicle, _flyView, QString() /* kmlFile */, _visualItems /* parent */);
} else {
qWarning() << "Internal error: Unknown complex item:" << itemName;
@@ -434,9 +436,9 @@ int MissionController::insertComplexMissionItemFromKMLOrSHP(QString itemName, QS
if (itemName == _surveyMissionItemName) {
newItem = new SurveyComplexItem(_controllerVehicle, _flyView, file, _visualItems);
- } else if (itemName == _structureScanMissionItemName) {
+ } else if (itemName == patternStructureScanName) {
newItem = new StructureScanComplexItem(_controllerVehicle, _flyView, file, _visualItems);
- } else if (itemName == _corridorScanMissionItemName) {
+ } else if (itemName == patternCorridorScanName) {
newItem = new CorridorScanComplexItem(_controllerVehicle, _flyView, file, _visualItems);
} else {
qWarning() << "Internal error: Unknown complex item:" << itemName;
@@ -1951,15 +1953,15 @@ QStringList MissionController::complexMissionItemNames(void) const
QStringList complexItems;
complexItems.append(_surveyMissionItemName);
- complexItems.append(_corridorScanMissionItemName);
+ complexItems.append(patternCorridorScanName);
if (_controllerVehicle->fixedWing()) {
- complexItems.append(_fwLandingMissionItemName);
+ complexItems.append(patternFWLandingName);
}
if (_controllerVehicle->multiRotor() || _controllerVehicle->vtol()) {
- complexItems.append(_structureScanMissionItemName);
+ complexItems.append(patternStructureScanName);
}
- return complexItems;
+ return qgcApp()->toolbox()->corePlugin()->complexMissionItemNames(_controllerVehicle, complexItems);
}
void MissionController::resumeMission(int resumeIndex)
diff --git a/src/MissionManager/MissionController.h b/src/MissionManager/MissionController.h
index 02747b6c9341eafd67a1d15083e1161ce0d580f1..6fa6e19efba2e9ec37dbe9ade2db2c656d7a3709 100644
--- a/src/MissionManager/MissionController.h
+++ b/src/MissionManager/MissionController.h
@@ -175,8 +175,8 @@ public:
VisualMissionItem* currentPlanViewItem (void) const;
double progressPct (void) const { return _progressPct; }
QString surveyComplexItemName (void) const { return _surveyMissionItemName; }
- QString corridorScanComplexItemName (void) const { return _corridorScanMissionItemName; }
- QString structureScanComplexItemName(void) const { return _structureScanMissionItemName; }
+ QString corridorScanComplexItemName (void) const { return patternCorridorScanName; }
+ QString structureScanComplexItemName(void) const { return patternStructureScanName; }
int missionItemCount (void) const { return _missionItemCount; }
int currentMissionIndex (void) const;
@@ -194,6 +194,12 @@ public:
int batteryChangePoint (void) const { return _missionFlightStatus.batteryChangePoint; } ///< -1 for not supported, 0 for not needed
int batteriesRequired (void) const { return _missionFlightStatus.batteriesRequired; } ///< -1 for not supported
+ // These are the names shown in the UI for the pattern items. They are public so custom builds can remove the ones
+ // they don't want through the QGCCorePlugin::
+ static const QString patternFWLandingName;
+ static const QString patternStructureScanName;
+ static const QString patternCorridorScanName;
+
signals:
void visualItemsChanged (void);
void waypointLinesChanged (void);
@@ -285,9 +291,6 @@ private:
bool _inRecalcSequence;
MissionFlightStatus_t _missionFlightStatus;
QString _surveyMissionItemName;
- QString _fwLandingMissionItemName;
- QString _structureScanMissionItemName;
- QString _corridorScanMissionItemName;
AppSettings* _appSettings;
double _progressPct;
int _currentPlanViewIndex;
diff --git a/src/MissionManager/QGCMapCircle.Facts.json b/src/MissionManager/QGCMapCircle.Facts.json
index f2ded5e5efea285b70279064ba7ed926e4d11456..2f496fa1d48a4054595d39c758f136c9beea4c09 100644
--- a/src/MissionManager/QGCMapCircle.Facts.json
+++ b/src/MissionManager/QGCMapCircle.Facts.json
@@ -3,7 +3,7 @@
"name": "Radius",
"shortDescription": "Radius for geofence circle.",
"type": "double",
- "decimalPlaces": 2,
+ "decimalPlaces": 1,
"min": 0.1,
"units": "m"
}
diff --git a/src/PlanView/GeoFenceEditor.qml b/src/PlanView/GeoFenceEditor.qml
index b5d12f23fa91c6da37496d6f63449f237c50361f..9788aea347a030ac59dbf6733fea0080641d8e02 100644
--- a/src/PlanView/GeoFenceEditor.qml
+++ b/src/PlanView/GeoFenceEditor.qml
@@ -10,13 +10,9 @@ import QGroundControl.FactControls 1.0
QGCFlickable {
id: root
- width: availableWidth
- height: availableHeight
- contentHeight: editorColumn.height
+ contentHeight: geoFenceEditorRect.height
clip: true
- property real availableWidth
- property real availableHeight
property var myGeoFenceController
property var flightMap
@@ -24,317 +20,290 @@ QGCFlickable {
readonly property real _margin: ScreenTools.defaultFontPixelWidth / 2
readonly property real _radius: ScreenTools.defaultFontPixelWidth / 2
- Column {
- id: editorColumn
+ Rectangle {
+ id: geoFenceEditorRect
anchors.left: parent.left
anchors.right: parent.right
+ height: geoFenceItems.y + geoFenceItems.height + (_margin * 2)
+ radius: _radius
+ color: qgcPal.missionItemEditor
+
+ QGCLabel {
+ id: geoFenceLabel
+ anchors.margins: _margin
+ anchors.left: parent.left
+ anchors.top: parent.top
+ text: qsTr("GeoFence")
+ anchors.leftMargin: ScreenTools.defaultFontPixelWidth
+ }
Rectangle {
- id: geoFenceEditorRect
- width: parent.width
- height: geoFenceItems.y + geoFenceItems.height + (_margin * 2)
- radius: _radius
- color: qgcPal.missionItemEditor
-
- QGCLabel {
- id: geoFenceLabel
+ id: geoFenceItems
+ anchors.margins: _margin
+ anchors.left: parent.left
+ anchors.right: parent.right
+ anchors.top: geoFenceLabel.bottom
+ height: fenceColumn.y + fenceColumn.height + (_margin * 2)
+ color: qgcPal.windowShadeDark
+ radius: _radius
+
+ Column {
+ id: fenceColumn
anchors.margins: _margin
- anchors.left: parent.left
anchors.top: parent.top
- text: qsTr("GeoFence")
- anchors.leftMargin: ScreenTools.defaultFontPixelWidth
- }
-
- Rectangle {
- id: geoFenceItems
- anchors.margins: _margin
anchors.left: parent.left
anchors.right: parent.right
- anchors.top: geoFenceLabel.bottom
- height: fenceColumn.y + fenceColumn.height + (_margin * 2)
- color: qgcPal.windowShadeDark
- radius: _radius
+ spacing: ScreenTools.defaultFontPixelHeight / 2
- Column {
- id: fenceColumn
- anchors.margins: _margin
- anchors.top: parent.top
+ QGCLabel {
anchors.left: parent.left
anchors.right: parent.right
- spacing: ScreenTools.defaultFontPixelHeight / 2
-
- QGCLabel {
- anchors.left: parent.left
- anchors.right: parent.right
- wrapMode: Text.WordWrap
- font.pointSize: myGeoFenceController.supported ? ScreenTools.smallFontPointSize : ScreenTools.defaultFontPointSize
- text: myGeoFenceController.supported ?
- qsTr("GeoFencing allows you to set a virtual ‘fence’ around the area you want to fly in.") :
- qsTr("This vehicle does not support GeoFence.")
- }
+ wrapMode: Text.WordWrap
+ font.pointSize: myGeoFenceController.supported ? ScreenTools.smallFontPointSize : ScreenTools.defaultFontPointSize
+ text: myGeoFenceController.supported ?
+ qsTr("GeoFencing allows you to set a virtual ‘fence’ around the area you want to fly in.") :
+ qsTr("This vehicle does not support GeoFence.")
+ }
- Column {
- anchors.left: parent.left
- anchors.right: parent.right
- spacing: ScreenTools.defaultFontPixelHeight / 2
- visible: myGeoFenceController.supported
+ Column {
+ anchors.left: parent.left
+ anchors.right: parent.right
+ spacing: ScreenTools.defaultFontPixelHeight / 2
+ visible: myGeoFenceController.supported
- Repeater {
- model: myGeoFenceController.params
+ Repeater {
+ model: myGeoFenceController.params
- Item {
- width: fenceColumn.width
- height: textField.height
+ Item {
+ width: fenceColumn.width
+ height: textField.height
- property bool showCombo: modelData.enumStrings.length > 0
+ property bool showCombo: modelData.enumStrings.length > 0
- QGCLabel {
- id: textFieldLabel
- anchors.baseline: textField.baseline
- text: myGeoFenceController.paramLabels[index]
- }
+ QGCLabel {
+ id: textFieldLabel
+ anchors.baseline: textField.baseline
+ text: myGeoFenceController.paramLabels[index]
+ }
- FactTextField {
- id: textField
- anchors.right: parent.right
- width: _editFieldWidth
- showUnits: true
- fact: modelData
- visible: !parent.showCombo
- }
+ FactTextField {
+ id: textField
+ anchors.right: parent.right
+ width: _editFieldWidth
+ showUnits: true
+ fact: modelData
+ visible: !parent.showCombo
+ }
- FactComboBox {
- id: comboField
- anchors.right: parent.right
- width: _editFieldWidth
- indexModel: false
- fact: showCombo ? modelData : _nullFact
- visible: parent.showCombo
+ FactComboBox {
+ id: comboField
+ anchors.right: parent.right
+ width: _editFieldWidth
+ indexModel: false
+ fact: showCombo ? modelData : _nullFact
+ visible: parent.showCombo
- property var _nullFact: Fact { }
- }
+ property var _nullFact: Fact { }
}
}
+ }
- SectionHeader {
- id: insertSection
- text: qsTr("Insert GeoFence")
- }
+ SectionHeader {
+ id: insertSection
+ text: qsTr("Insert GeoFence")
+ }
- QGCButton {
- anchors.left: parent.left
- anchors.right: parent.right
- text: qsTr("Polygon Fence")
+ QGCButton {
+ anchors.left: parent.left
+ anchors.right: parent.right
+ text: qsTr("Polygon Fence")
- onClicked: {
- var rect = Qt.rect(flightMap.centerViewport.x, flightMap.centerViewport.y, flightMap.centerViewport.width, flightMap.centerViewport.height)
- var topLeftCoord = flightMap.toCoordinate(Qt.point(rect.x, rect.y), false /* clipToViewPort */)
- var bottomRightCoord = flightMap.toCoordinate(Qt.point(rect.x + rect.width, rect.y + rect.height), false /* clipToViewPort */)
- myGeoFenceController.addInclusionPolygon(topLeftCoord, bottomRightCoord)
- }
+ onClicked: {
+ var rect = Qt.rect(flightMap.centerViewport.x, flightMap.centerViewport.y, flightMap.centerViewport.width, flightMap.centerViewport.height)
+ var topLeftCoord = flightMap.toCoordinate(Qt.point(rect.x, rect.y), false /* clipToViewPort */)
+ var bottomRightCoord = flightMap.toCoordinate(Qt.point(rect.x + rect.width, rect.y + rect.height), false /* clipToViewPort */)
+ myGeoFenceController.addInclusionPolygon(topLeftCoord, bottomRightCoord)
}
+ }
- QGCButton {
- anchors.left: parent.left
- anchors.right: parent.right
- text: qsTr("Circular Fence")
+ QGCButton {
+ anchors.left: parent.left
+ anchors.right: parent.right
+ text: qsTr("Circular Fence")
- onClicked: {
- var rect = Qt.rect(flightMap.centerViewport.x, flightMap.centerViewport.y, flightMap.centerViewport.width, flightMap.centerViewport.height)
- var topLeftCoord = flightMap.toCoordinate(Qt.point(rect.x, rect.y), false /* clipToViewPort */)
- var bottomRightCoord = flightMap.toCoordinate(Qt.point(rect.x + rect.width, rect.y + rect.height), false /* clipToViewPort */)
- myGeoFenceController.addInclusionCircle(topLeftCoord, bottomRightCoord)
- }
+ onClicked: {
+ var rect = Qt.rect(flightMap.centerViewport.x, flightMap.centerViewport.y, flightMap.centerViewport.width, flightMap.centerViewport.height)
+ var topLeftCoord = flightMap.toCoordinate(Qt.point(rect.x, rect.y), false /* clipToViewPort */)
+ var bottomRightCoord = flightMap.toCoordinate(Qt.point(rect.x + rect.width, rect.y + rect.height), false /* clipToViewPort */)
+ myGeoFenceController.addInclusionCircle(topLeftCoord, bottomRightCoord)
}
+ }
- SectionHeader {
- id: polygonSection
- text: qsTr("Polygon Fences")
- }
+ SectionHeader {
+ id: polygonSection
+ text: qsTr("Polygon Fences")
+ }
+
+ QGCLabel {
+ text: qsTr("None")
+ visible: polygonSection.checked && myGeoFenceController.polygons.count === 0
+ }
+
+ GridLayout {
+ anchors.left: parent.left
+ anchors.right: parent.right
+ columns: 3
+ flow: GridLayout.TopToBottom
+ visible: polygonSection.checked && myGeoFenceController.polygons.count > 0
QGCLabel {
- text: qsTr("None")
- visible: polygonSection.checked && myGeoFenceController.polygons.count === 0
+ text: qsTr("Inclusion")
+ Layout.column: 0
+ Layout.alignment: Qt.AlignHCenter
}
- GridLayout {
- anchors.left: parent.left
- anchors.right: parent.right
- columns: 3
- flow: GridLayout.TopToBottom
- visible: polygonSection.checked && myGeoFenceController.polygons.count > 0
+ Repeater {
+ model: myGeoFenceController.polygons
- QGCLabel {
- text: qsTr("Inclusion")
- Layout.column: 0
+ QGCCheckBox {
+ checked: object.inclusion
+ onClicked: object.inclusion = checked
Layout.alignment: Qt.AlignHCenter
}
+ }
- Repeater {
- model: myGeoFenceController.polygons
+ QGCLabel {
+ text: qsTr("Edit")
+ Layout.column: 1
+ Layout.alignment: Qt.AlignHCenter
+ }
- QGCCheckBox {
- checked: object.inclusion
- onClicked: object.inclusion = checked
- Layout.alignment: Qt.AlignHCenter
- }
- }
+ Repeater {
+ model: myGeoFenceController.polygons
- QGCLabel {
- text: qsTr("Edit")
- Layout.column: 1
+ QGCRadioButton {
+ checked: _interactive
Layout.alignment: Qt.AlignHCenter
- }
-
- Repeater {
- model: myGeoFenceController.polygons
-
- QGCRadioButton {
- checked: _interactive
- Layout.alignment: Qt.AlignHCenter
- property bool _interactive: object.interactive
+ property bool _interactive: object.interactive
- on_InteractiveChanged: checked = _interactive
+ on_InteractiveChanged: checked = _interactive
- onClicked: {
- myGeoFenceController.clearAllInteractive()
- object.interactive = checked
- }
+ onClicked: {
+ myGeoFenceController.clearAllInteractive()
+ object.interactive = checked
}
}
+ }
- QGCLabel {
- text: qsTr("Delete")
- Layout.column: 2
- Layout.alignment: Qt.AlignHCenter
- }
+ QGCLabel {
+ text: qsTr("Delete")
+ Layout.column: 2
+ Layout.alignment: Qt.AlignHCenter
+ }
- Repeater {
- model: myGeoFenceController.polygons
+ Repeater {
+ model: myGeoFenceController.polygons
- QGCColoredImage {
- width: ScreenTools.defaultFontPixelHeight
- height: width
- sourceSize.height: width
- source: "/res/XDelete.svg"
- fillMode: Image.PreserveAspectFit
- color: qgcPal.text
- Layout.alignment: Qt.AlignHCenter
+ QGCButton {
+ text: qsTr("Del")
+ Layout.alignment: Qt.AlignHCenter
+ onClicked: myGeoFenceController.deletePolygon(index)
+ }
+ }
+ } // GridLayout
- property int _polygonIndex: index
+ SectionHeader {
+ id: circleSection
+ text: qsTr("Circular Fences")
+ }
- QGCMouseArea {
- fillItem: parent
- onClicked: myGeoFenceController.deletePolygon(parent._polygonIndex)
- }
- }
- }
- } // GridLayout
+ QGCLabel {
+ text: qsTr("None")
+ visible: circleSection.checked && myGeoFenceController.circles.count === 0
+ }
- SectionHeader {
- id: circleSection
- text: qsTr("Circular Fences")
- }
+ GridLayout {
+ anchors.left: parent.left
+ anchors.right: parent.right
+ columns: 4
+ flow: GridLayout.TopToBottom
+ visible: polygonSection.checked && myGeoFenceController.circles.count > 0
QGCLabel {
- text: qsTr("None")
- visible: circleSection.checked && myGeoFenceController.circles.count === 0
+ text: qsTr("Inclusion")
+ Layout.column: 0
+ Layout.alignment: Qt.AlignHCenter
}
- GridLayout {
- anchors.left: parent.left
- anchors.right: parent.right
- columns: 4
- flow: GridLayout.TopToBottom
- visible: polygonSection.checked && myGeoFenceController.circles.count > 0
+ Repeater {
+ model: myGeoFenceController.circles
- QGCLabel {
- text: qsTr("Inclusion")
- Layout.column: 0
+ QGCCheckBox {
+ checked: object.inclusion
+ onClicked: object.inclusion = checked
Layout.alignment: Qt.AlignHCenter
}
+ }
- Repeater {
- model: myGeoFenceController.circles
+ QGCLabel {
+ text: qsTr("Edit")
+ Layout.column: 1
+ Layout.alignment: Qt.AlignHCenter
+ }
- QGCCheckBox {
- checked: object.inclusion
- onClicked: object.inclusion = checked
- Layout.alignment: Qt.AlignHCenter
- }
- }
+ Repeater {
+ model: myGeoFenceController.circles
- QGCLabel {
- text: qsTr("Edit")
- Layout.column: 1
+ QGCRadioButton {
+ checked: _interactive
Layout.alignment: Qt.AlignHCenter
- }
-
- Repeater {
- model: myGeoFenceController.circles
- QGCRadioButton {
- checked: _interactive
- Layout.alignment: Qt.AlignHCenter
+ property bool _interactive: object.interactive
- property bool _interactive: object.interactive
+ on_InteractiveChanged: checked = _interactive
- on_InteractiveChanged: checked = _interactive
-
- onClicked: {
- myGeoFenceController.clearAllInteractive()
- object.interactive = checked
- }
+ onClicked: {
+ myGeoFenceController.clearAllInteractive()
+ object.interactive = checked
}
}
+ }
- QGCLabel {
- text: qsTr("Radius")
- Layout.column: 2
- Layout.alignment: Qt.AlignHCenter
- }
-
- Repeater {
- model: myGeoFenceController.circles
+ QGCLabel {
+ text: qsTr("Radius")
+ Layout.column: 2
+ Layout.alignment: Qt.AlignHCenter
+ }
- FactTextField {
- fact: object.radius
- Layout.fillWidth: true
- Layout.alignment: Qt.AlignHCenter
- }
- }
+ Repeater {
+ model: myGeoFenceController.circles
- QGCLabel {
- text: qsTr("Delete")
- Layout.column: 3
+ FactTextField {
+ fact: object.radius
+ Layout.fillWidth: true
Layout.alignment: Qt.AlignHCenter
}
+ }
- Repeater {
- model: myGeoFenceController.circles
-
- QGCColoredImage {
- width: ScreenTools.defaultFontPixelHeight
- height: width
- sourceSize.height: width
- source: "/res/XDelete.svg"
- fillMode: Image.PreserveAspectFit
- color: qgcPal.text
- Layout.alignment: Qt.AlignHCenter
+ QGCLabel {
+ text: qsTr("Delete")
+ Layout.column: 3
+ Layout.alignment: Qt.AlignHCenter
+ }
- property int _circleIndex: index
+ Repeater {
+ model: myGeoFenceController.circles
- QGCMouseArea {
- fillItem: parent
- onClicked: myGeoFenceController.deleteCircle(parent._polygonIndex)
- }
- }
+ QGCButton {
+ text: qsTr("Del")
+ Layout.alignment: Qt.AlignHCenter
+ onClicked: myGeoFenceController.deleteCircle(index)
}
- } // GridLayout
- }
+ }
+ } // GridLayout
}
}
- } // Rectangle
- }
+ }
+ } // Rectangle
}
diff --git a/src/PlanView/MissionItemEditor.qml b/src/PlanView/MissionItemEditor.qml
index 511e6898f6353e67ab2f2bf655912cba40839eea..694eecb93db4c8f62d9d8f3db7d6efb0f07e46fa 100644
--- a/src/PlanView/MissionItemEditor.qml
+++ b/src/PlanView/MissionItemEditor.qml
@@ -15,7 +15,7 @@ import QGroundControl.Palette 1.0
/// Mission item edit control
Rectangle {
id: _root
- height: editorLoader.y + (editorLoader.visible ? editorLoader.height : 0) + (_margin * 2)
+ height: editorLoader.visible ? (editorLoader.y + editorLoader.height + (_margin * 2)) : (commandPicker.y + commandPicker.height + _margin / 2)
color: _currentItem ? qgcPal.missionItemEditor : qgcPal.windowShade
radius: _radius
@@ -90,8 +90,7 @@ Rectangle {
sourceSize.height: _hamburgerSize
source: "qrc:/qmlimages/Hamburger.svg"
visible: missionItem.isCurrentItem && missionItem.sequenceNumber !== 0
- color: qgcPal.windowShade
-
+ color: qgcPal.text
}
QGCMouseArea {
diff --git a/src/PlanView/PlanView.qml b/src/PlanView/PlanView.qml
index d03f08d4fb1825175370c4664414084355281469..15f81051084a0e17a4f27c23f544907f47fe33a4 100644
--- a/src/PlanView/PlanView.qml
+++ b/src/PlanView/PlanView.qml
@@ -760,14 +760,6 @@ QGCView {
anchors.left: parent.left
anchors.leftMargin: ScreenTools.defaultFontPixelWidth
readonly property real _buttonRadius: ScreenTools.defaultFontPixelHeight * 0.75
- QGCColoredImage {
- width: height
- height: ScreenTools.defaultFontPixelWidth * 2.5
- sourceSize.height: height
- source: "qrc:/res/waypoint.svg"
- color: qgcPal.text
- anchors.verticalCenter: parent.verticalCenter
- }
QGCLabel {
text: qsTr("Plan")
color: qgcPal.text
@@ -831,7 +823,7 @@ QGCView {
QGCListView {
id: missionItemEditorListView
anchors.fill: parent
- spacing: ScreenTools.defaultFontPixelHeight * 0.5
+ spacing: ScreenTools.defaultFontPixelHeight / 4
orientation: ListView.Vertical
model: _missionController.visualItems
cacheBuffer: Math.max(height * 2, 0)
@@ -865,9 +857,9 @@ QGCView {
GeoFenceEditor {
anchors.top: rightControls.bottom
anchors.topMargin: ScreenTools.defaultFontPixelHeight * 0.5
+ anchors.bottom: parent.bottom
anchors.left: parent.left
anchors.right: parent.right
- availableHeight: ScreenTools.availableHeight
myGeoFenceController: _geoFenceController
flightMap: editorMap
visible: _editingLayer == _layerGeoFence
diff --git a/src/PlanView/RallyPointItemEditor.qml b/src/PlanView/RallyPointItemEditor.qml
index a85c84b7395e8898ab4dff84c681e420f8bb921c..9ec63847a3e4b813db249765b7d25f4d98126362 100644
--- a/src/PlanView/RallyPointItemEditor.qml
+++ b/src/PlanView/RallyPointItemEditor.qml
@@ -50,7 +50,7 @@ Rectangle {
color: _outerTextColor
}
- Image {
+ QGCColoredImage {
id: hamburger
anchors.rightMargin: _margin
anchors.right: parent.right
@@ -59,6 +59,7 @@ Rectangle {
height: width
sourceSize.height: height
source: "qrc:/qmlimages/Hamburger.svg"
+ color: qgcPal.text
MouseArea {
anchors.fill: parent
diff --git a/src/PlanView/SimpleItemEditor.qml b/src/PlanView/SimpleItemEditor.qml
index be5f0659955ade1daa21308a9c5f29980da6a784..e638b45aa3a9102cc24f19951b864eaa7b8e20de 100644
--- a/src/PlanView/SimpleItemEditor.qml
+++ b/src/PlanView/SimpleItemEditor.qml
@@ -18,23 +18,46 @@ Rectangle {
color: qgcPal.windowShadeDark
radius: _radius
- property bool _specifiesAltitude: missionItem.specifiesAltitude
- property real _margin: ScreenTools.defaultFontPixelHeight / 2
- property bool _supportsTerrainFrame: missionItem
-
readonly property int _altModeRelative: 0
readonly property int _altModeAbsolute: 1
readonly property int _altModeAboveTerrain: 2
readonly property int _altModeTerrainFrame: 3
- ExclusiveGroup {
- id: altRadios
- onCurrentChanged: {
- altModeLabel.text = Qt.binding(function() { return current.helpText })
- missionItem.altitudeMode = current.altModeValue
+ property bool _specifiesAltitude: missionItem.specifiesAltitude
+ property real _margin: ScreenTools.defaultFontPixelHeight / 2
+ property bool _supportsTerrainFrame: missionItem
+
+ property string _altModeRelativeHelpText: qsTr("Altitude relative to home altitude")
+ property string _altModeAbsoluteHelpText: qsTr("Altitude above mean sea level")
+ property string _altModeAboveTerrainHelpText: qsTr("Altitude above terrain\nActual AMSL altitude: %1 %2").arg(missionItem.amslAltAboveTerrain.valueString).arg(missionItem.amslAltAboveTerrain.units)
+ property string _altModeTerrainFrameHelpText: qsTr("Using terrain reference frame")
+
+ function updateAltitudeModeText() {
+ if (missionItem.altitudeMode === _altModeRelative) {
+ altModeLabel.text = qsTr("Altitude")
+ altModeHelp.text = _altModeRelativeHelpText
+ } else if (missionItem.altitudeMode === _altModeAbsolute) {
+ altModeLabel.text = qsTr("Above Mean Sea Level")
+ altModeHelp.text = _altModeAbsoluteHelpText
+ } else if (missionItem.altitudeMode === _altModeAboveTerrain) {
+ altModeLabel.text = qsTr("Above Terrain")
+ altModeHelp.text = Qt.binding(function() { return _altModeAboveTerrainHelpText })
+ } else if (missionItem.altitudeMode === _altModeTerrainFrame) {
+ altModeLabel.text = qsTr("Terrain Frame")
+ altModeHelp.text = _altModeTerrainFrameHelpText
+ } else {
+ altModeLabel.text = qsTr("Internal Error")
+ altModeHelp.text = ""
}
}
+ Component.onCompleted: updateAltitudeModeText()
+
+ Connections {
+ target: missionItem
+ onAltitudeModeChanged: updateAltitudeModeText()
+ }
+
Column {
id: valuesColumn
anchors.margins: _margin
@@ -97,56 +120,70 @@ Rectangle {
anchors.right: parent.right
spacing: _margin
- QGCLabel {
- font.pointSize: ScreenTools.smallFontPointSize
- text: qsTr("Altitude")
- }
-
- RowLayout {
- QGCRadioButton {
- text: qsTr("Rel")
- exclusiveGroup: altRadios
- checked: missionItem.altitudeMode === altModeValue
-
- readonly property int altModeValue: _altModeRelative
- readonly property string helpText: qsTr("Relative to home altitude")
- }
- QGCRadioButton {
- text: qsTr("AMSL")
- exclusiveGroup: altRadios
- checked: missionItem.altitudeMode === altModeValue
- visible: QGroundControl.corePlugin.options.showMissionAbsoluteAltitude || missionItem.altitudeMode === altModeValue
-
- readonly property int altModeValue: _altModeAbsolute
- readonly property string helpText: qsTr("Above Mean Sea Level")
+ Item {
+ width: altHamburger.x + altHamburger.width
+ height: altModeLabel.height
+
+ QGCLabel { id: altModeLabel }
+
+ QGCColoredImage {
+ id: altHamburger
+ anchors.leftMargin: ScreenTools.defaultFontPixelWidth / 4
+ anchors.left: altModeLabel.right
+ anchors.top: altModeLabel.top
+ width: height
+ height: altModeLabel.height
+ sourceSize.height: height
+ source: "qrc:/qmlimages/Hamburger.svg"
+ color: qgcPal.text
}
- QGCRadioButton {
- text: qsTr("AGL")
- exclusiveGroup: altRadios
- checked: missionItem.altitudeMode === altModeValue
- readonly property int altModeValue: _altModeAboveTerrain
- property string helpText: qsTr("Calculated from terrain data\nAMSL Alt ") + missionItem.amslAltAboveTerrain.valueString + " " + missionItem.amslAltAboveTerrain.units
+ QGCMouseArea {
+ anchors.fill: parent
+ onClicked: altHamburgerMenu.popup()
}
- QGCRadioButton {
- text: qsTr("TerrF")
- exclusiveGroup: altRadios
- checked: missionItem.altitudeMode === altModeValue
- visible: missionItem.altitudeMode === altModeValue
-
- readonly property int altModeValue: _altModeTerrainFrame
- readonly property string helpText: qsTr("Using terrain reference frame")
+
+ Menu {
+ id: altHamburgerMenu
+
+ MenuItem {
+ text: qsTr("Altitude Relative To Home")
+ checkable: true
+ checked: missionItem.altitudeMode === _altModeRelative
+ onTriggered: missionItem.altitudeMode = _altModeRelative
+ }
+
+ MenuItem {
+ text: qsTr("Altitude Above Mean Sea Level")
+ checkable: true
+ checked: missionItem.altitudeMode === _altModeAbsolute
+ visible: QGroundControl.corePlugin.options.showMissionAbsoluteAltitude
+ onTriggered: missionItem.altitudeMode = _altModeAbsolute
+ }
+
+ MenuItem {
+ text: qsTr("Altitude Above Terrain")
+ checkable: true
+ checked: missionItem.altitudeMode === _altModeAboveTerrain
+ onTriggered: missionItem.altitudeMode = _altModeAboveTerrain
+ }
+
+ MenuItem {
+ text: qsTr("Terrain Frame")
+ checkable: true
+ checked: missionItem.altitudeMode === _altModeTerrainFrame
+ visible: missionItem.altitudeMode === _altModeTerrainFrame
+ onTriggered: missionItem.altitudeMode = _altModeTerrainFrame
+ }
}
}
- FactValueSlider {
- fact: missionItem.altitude
- digitCount: 3
- incrementSlots: 1
+ FactTextField {
+ fact: missionItem.altitude
}
QGCLabel {
- id: altModeLabel
+ id: altModeHelp
anchors.left: parent.left
anchors.right: parent.right
wrapMode: Text.WordWrap
diff --git a/src/PositionManager/PositionManager.cpp b/src/PositionManager/PositionManager.cpp
index 146749ca34ae0cbc0cc39227dcaaa3d304cee0fc..09f485142162f1ca634be70045d1fec08b4edda7 100644
--- a/src/PositionManager/PositionManager.cpp
+++ b/src/PositionManager/PositionManager.cpp
@@ -36,7 +36,6 @@ void QGCPositionManager::setToolbox(QGCToolbox *toolbox)
if(!_defaultSource) {
//-- Otherwise, create a default one
_defaultSource = QGeoPositionInfoSource::createDefaultSource(this);
- qDebug() << _defaultSource;
}
_simulatedSource = new SimulatedPosition();
diff --git a/src/QmlControls/QGCCheckBox.qml b/src/QmlControls/QGCCheckBox.qml
index 5dbfb55053e844a1024289677258c1220353def7..9292f7cac49612d985d5a9f73bddd115efa6682f 100644
--- a/src/QmlControls/QGCCheckBox.qml
+++ b/src/QmlControls/QGCCheckBox.qml
@@ -6,96 +6,50 @@ import QGroundControl.Palette 1.0
import QGroundControl.ScreenTools 1.0
CheckBox {
- activeFocusOnPress: true
+ property color textColor: _qgcPal.text
+ property bool textBold: false
+ property real textFontPointSize: ScreenTools.defaultFontPointSize
+
+ property var _qgcPal: QGCPalette { colorGroupEnabled: enabled }
+ property bool _noText: text === ""
+ property real _radius: ScreenTools.defaultFontPixelHeight * 0.16
- property var __qgcPal: QGCPalette { colorGroupEnabled: enabled }
+ activeFocusOnPress: true
style: CheckBoxStyle {
label: Item {
- implicitWidth: text.implicitWidth + 2
- implicitHeight: ScreenTools.implicitCheckBoxHeight
+ implicitWidth: _noText ? 0 : text.implicitWidth + ScreenTools.defaultFontPixelWidth * 0.25
+ implicitHeight: _noText ? 0 : Math.max(text.implicitHeight, ScreenTools.checkBoxIndicatorSize)
baselineOffset: text.baselineOffset
- Rectangle {
- anchors.margins: -1
- anchors.leftMargin: -3
- anchors.rightMargin: -3
- anchors.fill: text
- visible: control.activeFocus
- height: 6
- radius: 3
- color: "#224f9fef"
- border.color: "#47b"
- opacity: 0.6
- }
-
Text {
- id: text
- text: control.text
- antialiasing: true
- font.pointSize: ScreenTools.defaultFontPointSize
- font.family: ScreenTools.normalFontFamily
- color: control.__qgcPal.text
- anchors.verticalCenter: parent.verticalCenter
+ id: text
+ text: control.text
+ font.pointSize: textFontPointSize
+ font.bold: control.textBold
+ color: control.textColor
+ anchors.centerIn: parent
}
- } // label
+ }
indicator: Item {
implicitWidth: ScreenTools.checkBoxIndicatorSize
implicitHeight: implicitWidth
Rectangle {
- anchors.fill: parent
- anchors.bottomMargin: -1
- color: "#44ffffff"
- radius: baserect.radius
- }
-
- Rectangle {
- id: baserect
- property var enabledGradient: Gradient {
- GradientStop {color: "#eee" ; position: 0}
- GradientStop {color: control.pressed ? "#eee" : "#fff" ; position: 0.1}
- GradientStop {color: "#fff" ; position: 1}
- }
- property var disabledGradient: Gradient {
- GradientStop {color: "#999" ; position: 0}
- GradientStop {color: __qgcPal.textField ; position: 0.1}
- GradientStop {color: __qgcPal.textField ; position: 0.9}
- GradientStop {color: "#999" ; position: 1}
- }
- gradient: control.enabled ? enabledGradient : disabledGradient
-
-
- radius: ScreenTools.defaultFontPixelHeight * 0.16
- anchors.fill: parent
- border.color: control.activeFocus ? "#47b" : "#999"
- opacity: control.enabled ? 1 : 0.5
- }
-
- Image {
- source: "/qmlimages/check.png"
- opacity: control.checkedState === Qt.Checked ? control.enabled ? 1 : 0.5 : 0
- anchors.centerIn: parent
- anchors.verticalCenterOffset: 1
- Behavior on opacity {NumberAnimation {duration: 80}}
- }
-
- Rectangle {
- anchors.fill: parent
- anchors.margins: Math.round(baserect.radius)
- antialiasing: true
- gradient: Gradient {
- GradientStop {color: control.pressed ? "#555" : "#999" ; position: 0}
- GradientStop {color: "#555" ; position: 1}
+ anchors.fill: parent
+ radius: _radius
+ border.color: "black"
+ opacity: control.checkedState === Qt.PartiallyChecked ? 0.5 : 1
+
+ Rectangle {
+ anchors.margins: parent.height / 4
+ anchors.fill: parent
+ radius: _radius
+ color: "black"
+ visible: control.checkedState === Qt.Checked
}
- radius: baserect.radius - 1
- anchors.centerIn: parent
- anchors.alignWhenCentered: true
- border.color: "#222"
- Behavior on opacity {NumberAnimation {duration: 80}}
- opacity: control.checkedState === Qt.PartiallyChecked ? control.enabled ? 1 : 0.5 : 0
}
- } // indicator
- } // style
+ }
+ }
}
diff --git a/src/QmlControls/QGCMouseArea.qml b/src/QmlControls/QGCMouseArea.qml
index b58eb3498b2b518bf336cd559ebfb3e21017f383..e1a9f2c532ceddcec1b990212844d90bb58e28c1 100644
--- a/src/QmlControls/QGCMouseArea.qml
+++ b/src/QmlControls/QGCMouseArea.qml
@@ -1,4 +1,4 @@
-import QtQuick 2.3
+import QtQuick 2.11
import QGroundControl 1.0
import QGroundControl.ScreenTools 1.0
diff --git a/src/QmlControls/QGCRadioButton.qml b/src/QmlControls/QGCRadioButton.qml
index e28d327e349a19888d2d12f3690048e77e90ce34..79792d386e99e27002a31f4806ddc9b391d36b3f 100644
--- a/src/QmlControls/QGCRadioButton.qml
+++ b/src/QmlControls/QGCRadioButton.qml
@@ -6,41 +6,30 @@ import QGroundControl.Palette 1.0
import QGroundControl.ScreenTools 1.0
RadioButton {
- property var color: qgcPal.text ///< Text color
- property int textStyle: Text.Normal
- property color textStyleColor: qgcPal.text
- property bool textBold: false
- property var qgcPal: QGCPalette { colorGroupEnabled: enabled }
+ property color textColor: _qgcPal.text
+ property bool textBold: false
+ property real textFontPointSize: ScreenTools.defaultFontPointSize
+
+ property var _qgcPal: QGCPalette { colorGroupEnabled: enabled }
+
+ property bool _noText: text === ""
+
+ activeFocusOnPress: true
style: RadioButtonStyle {
+ spacing: _noText ? 0 : ScreenTools.defaultFontPixelWidth / 2
+
label: Item {
- implicitWidth: text.implicitWidth + ScreenTools.defaultFontPixelWidth * 0.25
- implicitHeight: ScreenTools.implicitRadioButtonHeight
+ implicitWidth: _noText ? 0 : text.implicitWidth + ScreenTools.defaultFontPixelWidth * 0.25
+ implicitHeight: _noText ? 0 : Math.max(text.implicitHeight, ScreenTools.radioButtonIndicatorSize)
baselineOffset: text.y + text.baselineOffset
- Rectangle {
- anchors.fill: text
- anchors.margins: -1
- anchors.leftMargin: -3
- anchors.rightMargin:-3
- visible: control.activeFocus
- height: ScreenTools.defaultFontPixelWidth * 0.25
- radius: height * 0.5
- color: "#224f9fef"
- border.color: "#47b"
- opacity: 0.6
- }
-
Text {
id: text
text: control.text
- font.pointSize: ScreenTools.defaultFontPointSize
- font.family: ScreenTools.normalFontFamily
+ font.pointSize: textFontPointSize
font.bold: control.textBold
- antialiasing: true
- color: control.color
- style: control.textStyle
- styleColor: control.textStyleColor
+ color: control.textColor
anchors.centerIn: parent
}
}
@@ -49,9 +38,9 @@ RadioButton {
width: ScreenTools.radioButtonIndicatorSize
height: width
color: "white"
- border.color: control.qgcPal.text
- antialiasing: true
+ border.color: "black"
radius: height / 2
+ opacity: control.enabled ? 1 : 0.5
Rectangle {
anchors.centerIn: parent
@@ -60,7 +49,7 @@ RadioButton {
antialiasing: true
radius: height / 2
color: "black"
- opacity: control.checked ? (control.enabled ? 1 : 0.5) : 0
+ visible: control.checked
}
}
}
diff --git a/src/QmlControls/SliderSwitch.qml b/src/QmlControls/SliderSwitch.qml
index 2fcf738dc6c88df66e0d67bba9f29b1e01ee10f3..112223a47d6d63c9a72307d855ca7d4d0bb54d7e 100644
--- a/src/QmlControls/SliderSwitch.qml
+++ b/src/QmlControls/SliderSwitch.qml
@@ -14,7 +14,6 @@ Rectangle {
color: qgcPal.windowShade
signal accept ///< Action confirmed
- signal reject ///< Action rejected
property string confirmText ///< Text for slider
property alias fontPointSize: label.font.pointSize ///< Point size for text
@@ -70,12 +69,6 @@ Rectangle {
property bool dragActive: drag.active
property real _dragOffset: 1
- //Component.onCompleted: console.log(height, ScreenTools.minTouchPixels)
-
- onPressed: {
- mouse.x
- }
-
onDragActiveChanged: {
if (!sliderDragArea.drag.active) {
if (slider.x > _maxXDrag - _border) {
diff --git a/src/QmlControls/ToolStrip.qml b/src/QmlControls/ToolStrip.qml
index 10d6eba22ac32d44b79c2861f8f5160ceacc7153..4ab074dec41af5aa55b7fbb1223924932477b427 100644
--- a/src/QmlControls/ToolStrip.qml
+++ b/src/QmlControls/ToolStrip.qml
@@ -7,8 +7,8 @@
*
****************************************************************************/
-import QtQuick 2.3
-import QtQuick.Controls 1.2
+import QtQuick 2.11
+import QtQuick.Controls 1.4
import QGroundControl.ScreenTools 1.0
import QGroundControl.Palette 1.0
@@ -17,7 +17,7 @@ Rectangle {
id: _root
color: qgcPal.window
width: ScreenTools.isMobile ? ScreenTools.minTouchPixels : ScreenTools.defaultFontPixelWidth * 7
- height: buttonStripColumn.height + (buttonStripColumn.anchors.margins * 2)
+ height: toolStripColumn.height + (toolStripColumn.anchors.margins * 2)
radius: _radius
border.width: 1
border.color: qgcPal.globalTheme === QGCPalette.Light ? Qt.rgba(0,0,0,0.35) : Qt.rgba(1,1,1,0.35)
@@ -35,9 +35,7 @@ Rectangle {
readonly property real _radius: ScreenTools.defaultFontPixelWidth / 2
readonly property real _margin: ScreenTools.defaultFontPixelWidth / 2
- readonly property real _buttonSpacing: ScreenTools.defaultFontPixelWidth
-
- property bool _showOptionalElements: !ScreenTools.isTinyScreen
+ readonly property real _buttonSpacing: ScreenTools.defaultFontPixelHeight / 4
QGCPalette { id: qgcPal }
ExclusiveGroup { id: dropButtonsExclusiveGroup }
@@ -57,129 +55,141 @@ Rectangle {
}
Column {
- id: buttonStripColumn
+ id: toolStripColumn
anchors.margins: ScreenTools.defaultFontPixelWidth / 2
anchors.top: parent.top
anchors.left: parent.left
anchors.right: parent.right
+ spacing: _buttonSpacing
QGCLabel {
anchors.horizontalCenter: parent.horizontalCenter
text: title
- visible: _showOptionalElements
+ font.pointSize: ScreenTools.smallFontPointSize
}
- Item { width: 1; height: _buttonSpacing; visible: _showOptionalElements }
-
Rectangle {
anchors.left: parent.left
anchors.right: parent.right
height: 1
color: qgcPal.text
- visible: _showOptionalElements
}
- Repeater {
- id: repeater
-
- delegate: Column {
- id: buttonColumn
- width: buttonStripColumn.width
- visible: _root.buttonVisible ? _root.buttonVisible[index] : true
-
- property bool checked: false
- property ExclusiveGroup exclusiveGroup: dropButtonsExclusiveGroup
-
- QGCPalette { id: _repeaterPal; colorGroupEnabled: _buttonEnabled }
-
- property bool _buttonEnabled: _root.buttonEnabled ? _root.buttonEnabled[index] : true
- property var _iconSource: modelData.iconSource
- property var _alternateIconSource: modelData.alternateIconSource
- property var _source: (_root.showAlternateIcon && _root.showAlternateIcon[index]) ? _alternateIconSource : _iconSource
- property bool rotateImage: _root.rotateImage ? _root.rotateImage[index] : false
- property bool animateImage: _root.animateImage ? _root.animateImage[index] : false
-
- onExclusiveGroupChanged: {
- if (exclusiveGroup) {
- exclusiveGroup.bindCheckable(buttonColumn)
- }
- }
-
- onRotateImageChanged: {
- if (rotateImage) {
- imageRotation.running = true
- } else {
- imageRotation.running = false
- button.rotation = 0
- }
- }
-
- onAnimateImageChanged: {
- if (animateImage) {
- opacityAnimation.running = true
- } else {
- opacityAnimation.running = false
- button.opacity = 1
+ Column {
+ anchors.left: parent.left
+ anchors.right: parent.right
+ spacing: _buttonSpacing
+
+ Repeater {
+ id: repeater
+
+ delegate: FocusScope {
+ id: scope
+ width: toolStripColumn.width
+ height: buttonRect.height
+ visible: _root.buttonVisible ? _root.buttonVisible[index] : true
+
+ property bool checked: false
+ property ExclusiveGroup exclusiveGroup: dropButtonsExclusiveGroup
+
+ property bool _buttonEnabled: _root.buttonEnabled ? _root.buttonEnabled[index] : true
+ property var _iconSource: modelData.iconSource
+ property var _alternateIconSource: modelData.alternateIconSource
+ property var _source: (_root.showAlternateIcon && _root.showAlternateIcon[index]) ? _alternateIconSource : _iconSource
+ property bool rotateImage: _root.rotateImage ? _root.rotateImage[index] : false
+ property bool animateImage: _root.animateImage ? _root.animateImage[index] : false
+ property bool _hovered: false
+ property bool _showHighlight: checked || (_buttonEnabled && _hovered)
+
+ QGCPalette { id: _repeaterPal; colorGroupEnabled: _buttonEnabled }
+
+ onExclusiveGroupChanged: {
+ if (exclusiveGroup) {
+ exclusiveGroup.bindCheckable(scope)
+ }
}
- }
- Item {
- width: 1
- height: _buttonSpacing
- visible: index == 0 ? _showOptionalElements : true
- }
+ onRotateImageChanged: {
+ if (rotateImage) {
+ imageRotation.running = true
+ } else {
+ imageRotation.running = false
+ buttonImage.rotation = 0
+ }
+ }
- FocusScope {
- id: scope
- anchors.left: parent.left
- anchors.right: parent.right
- height: width * 0.8
+ onAnimateImageChanged: {
+ if (animateImage) {
+ opacityAnimation.running = true
+ } else {
+ opacityAnimation.running = false
+ buttonImage.opacity = 1
+ }
+ }
Rectangle {
- anchors.fill: parent
- color: checked ? _repeaterPal.buttonHighlight : _repeaterPal.button
-
- QGCColoredImage {
- id: button
- height: parent.height
- width: height
- anchors.centerIn: parent
- source: _source
- sourceSize.height: height
- fillMode: Image.PreserveAspectFit
- mipmap: true
- smooth: true
- color: checked ? _repeaterPal.buttonHighlightText : _repeaterPal.buttonText
-
- RotationAnimation on rotation {
- id: imageRotation
- loops: Animation.Infinite
- from: 0
- to: 360
- duration: 500
- running: false
+ id: buttonRect
+ anchors.left: parent.left
+ anchors.right: parent.right
+ height: buttonColumn.height
+ color: _showHighlight ? _repeaterPal.buttonHighlight : _repeaterPal.window
+
+ Column {
+ id: buttonColumn
+ anchors.left: parent.left
+ anchors.right: parent.right
+ spacing: -buttonImage.height / 8
+
+ QGCColoredImage {
+ id: buttonImage
+ anchors.left: parent.left
+ anchors.right: parent.right
+ height: width * 0.8
+ //anchors.centerIn: parent
+ source: _source
+ sourceSize.height: height
+ fillMode: Image.PreserveAspectFit
+ mipmap: true
+ smooth: true
+ color: _showHighlight ? _repeaterPal.buttonHighlightText : _repeaterPal.text
+
+ RotationAnimation on rotation {
+ id: imageRotation
+ loops: Animation.Infinite
+ from: 0
+ to: 360
+ duration: 500
+ running: false
+ }
+
+ NumberAnimation on opacity {
+ id: opacityAnimation
+ running: false
+ from: 0
+ to: 1.0
+ loops: Animation.Infinite
+ duration: 2000
+ }
}
- NumberAnimation on opacity {
- id: opacityAnimation
- running: false
- from: 0
- to: 1.0
- loops: Animation.Infinite
- duration: 2000
+ QGCLabel {
+ id: buttonLabel
+ anchors.horizontalCenter: parent.horizontalCenter
+ font.pointSize: ScreenTools.smallFontPointSize
+ text: modelData.name
+ color: _showHighlight ? _repeaterPal.buttonHighlightText : _repeaterPal.text
+ enabled: _buttonEnabled
}
- }
+ } // Column
QGCMouseArea {
- // Size of mouse area is expanded to make touch easier
- anchors.leftMargin: -buttonStripColumn.anchors.margins
- anchors.rightMargin: -buttonStripColumn.anchors.margins
- anchors.left: parent.left
- anchors.right: parent.right
- anchors.top: parent.top
- height: parent.height + (_showOptionalElements? buttonLabel.height + buttonColumn.spacing : 0)
- visible: _buttonEnabled
- preventStealing: true
+ anchors.fill: parent
+ visible: _buttonEnabled
+ hoverEnabled: true
+ preventStealing: true
+
+ onContainsMouseChanged: _hovered = containsMouse
+ onContainsPressChanged: _hovered = containsPress
onClicked: {
scope.focus = true
@@ -205,23 +215,8 @@ Rectangle {
}
}
}
- }
- }
-
- Item {
- width: 1
- height: ScreenTools.defaultFontPixelHeight * 0.25
- visible: _showOptionalElements
- }
-
- QGCLabel {
- id: buttonLabel
- anchors.horizontalCenter: parent.horizontalCenter
- font.pointSize: ScreenTools.smallFontPointSize
- text: modelData.name
- visible: _showOptionalElements
- enabled: _buttonEnabled
- }
+ } // Rectangle
+ } // FocusScope
}
}
}
diff --git a/src/Settings/VideoSettings.cc b/src/Settings/VideoSettings.cc
index 8be433f2537defd557eea08872be6cb3e727d312..16ea77d446c64445a64662ba733c9f32bc4a52e2 100644
--- a/src/Settings/VideoSettings.cc
+++ b/src/Settings/VideoSettings.cc
@@ -25,6 +25,7 @@ const char* VideoSettings::videoSourceAuto = "Automatic Video Stream";
const char* VideoSettings::videoSourceRTSP = "RTSP Video Stream";
const char* VideoSettings::videoSourceUDP = "UDP Video Stream";
const char* VideoSettings::videoSourceTCP = "TCP-MPEG2 Video Stream";
+const char* VideoSettings::videoSourceMPEGTS = "MPEG-TS (h.264) Video Stream";
DECLARE_SETTINGGROUP(Video, "Video")
{
@@ -40,6 +41,7 @@ DECLARE_SETTINGGROUP(Video, "Video")
videoSourceList.append(videoSourceUDP);
#endif
videoSourceList.append(videoSourceTCP);
+ videoSourceList.append(videoSourceMPEGTS);
#endif
#ifndef QGC_DISABLE_UVC
QList cameras = QCameraInfo::availableCameras();
@@ -150,6 +152,11 @@ bool VideoSettings::streamConfigured(void)
qCDebug(VideoManagerLog) << "Testing configuration for TCP Stream:" << tcpUrl()->rawValue().toString();
return !tcpUrl()->rawValue().toString().isEmpty();
}
+ //-- If MPEG-TS, check if port is set
+ if(vSource == videoSourceMPEGTS) {
+ qCDebug(VideoManagerLog) << "Testing configuration for MPEG-TS Stream:" << udpPort()->rawValue().toInt();
+ return udpPort()->rawValue().toInt() != 0;
+ }
//-- If Auto, check for received URL
if(vSource == videoSourceAuto) {
qCDebug(VideoManagerLog) << "Testing configuration for Auto Stream:" << qgcApp()->toolbox()->videoManager()->autoURL();
diff --git a/src/Settings/VideoSettings.h b/src/Settings/VideoSettings.h
index d0002fd0c07e14a88f11e991ef542069b3280b19..ff560235851f9de52338eb4514335725def43b85 100644
--- a/src/Settings/VideoSettings.h
+++ b/src/Settings/VideoSettings.h
@@ -40,12 +40,14 @@ public:
Q_PROPERTY(QString rtspVideoSource READ rtspVideoSource CONSTANT)
Q_PROPERTY(QString udpVideoSource READ udpVideoSource CONSTANT)
Q_PROPERTY(QString tcpVideoSource READ tcpVideoSource CONSTANT)
+ Q_PROPERTY(QString mpegtsVideoSource READ mpegtsVideoSource CONSTANT)
bool streamConfigured ();
QString autoVideoSource () { return videoSourceAuto; }
QString rtspVideoSource () { return videoSourceRTSP; }
QString udpVideoSource () { return videoSourceUDP; }
QString tcpVideoSource () { return videoSourceTCP; }
+ QString mpegtsVideoSource () { return videoSourceMPEGTS; }
static const char* videoSourceNoVideo;
static const char* videoDisabled;
@@ -53,6 +55,7 @@ public:
static const char* videoSourceRTSP;
static const char* videoSourceAuto;
static const char* videoSourceTCP;
+ static const char* videoSourceMPEGTS;
signals:
void streamConfiguredChanged ();
diff --git a/src/Vehicle/Vehicle.cc b/src/Vehicle/Vehicle.cc
index f8cd2b75dcc4d1e2b2c5dc77c488bda6486e5cd3..4b9b33ef6e71b62d3c19c916f666fd761cffff64 100644
--- a/src/Vehicle/Vehicle.cc
+++ b/src/Vehicle/Vehicle.cc
@@ -2962,6 +2962,11 @@ bool Vehicle::takeoffVehicleSupported() const
return _firmwarePlugin->isCapable(this, FirmwarePlugin::TakeoffVehicleCapability);
}
+QString Vehicle::gotoFlightMode() const
+{
+ return _firmwarePlugin->gotoFlightMode();
+}
+
void Vehicle::guidedModeRTL(void)
{
if (!guidedModeSupported()) {
diff --git a/src/Vehicle/Vehicle.h b/src/Vehicle/Vehicle.h
index 4afdb3b6cb3f8267a9cf97caafa13d4dd36cedf3..b330984442289aba2681bde17bca3ad7ae07baf1 100644
--- a/src/Vehicle/Vehicle.h
+++ b/src/Vehicle/Vehicle.h
@@ -636,13 +636,14 @@ public:
Q_PROPERTY(QGCMapCircle* orbitMapCircle READ orbitMapCircle CONSTANT)
// Vehicle state used for guided control
- Q_PROPERTY(bool flying READ flying NOTIFY flyingChanged) ///< Vehicle is flying
- Q_PROPERTY(bool landing READ landing NOTIFY landingChanged) ///< Vehicle is in landing pattern (DO_LAND_START)
- Q_PROPERTY(bool guidedMode READ guidedMode WRITE setGuidedMode NOTIFY guidedModeChanged) ///< Vehicle is in Guided mode and can respond to guided commands
- Q_PROPERTY(bool guidedModeSupported READ guidedModeSupported CONSTANT) ///< Guided mode commands are supported by this vehicle
- Q_PROPERTY(bool pauseVehicleSupported READ pauseVehicleSupported CONSTANT) ///< Pause vehicle command is supported
- Q_PROPERTY(bool orbitModeSupported READ orbitModeSupported CONSTANT) ///< Orbit mode is supported by this vehicle
- Q_PROPERTY(bool takeoffVehicleSupported READ takeoffVehicleSupported CONSTANT) ///< Guided takeoff supported
+ Q_PROPERTY(bool flying READ flying NOTIFY flyingChanged) ///< Vehicle is flying
+ Q_PROPERTY(bool landing READ landing NOTIFY landingChanged) ///< Vehicle is in landing pattern (DO_LAND_START)
+ Q_PROPERTY(bool guidedMode READ guidedMode WRITE setGuidedMode NOTIFY guidedModeChanged) ///< Vehicle is in Guided mode and can respond to guided commands
+ Q_PROPERTY(bool guidedModeSupported READ guidedModeSupported CONSTANT) ///< Guided mode commands are supported by this vehicle
+ Q_PROPERTY(bool pauseVehicleSupported READ pauseVehicleSupported CONSTANT) ///< Pause vehicle command is supported
+ Q_PROPERTY(bool orbitModeSupported READ orbitModeSupported CONSTANT) ///< Orbit mode is supported by this vehicle
+ Q_PROPERTY(bool takeoffVehicleSupported READ takeoffVehicleSupported CONSTANT) ///< Guided takeoff supported
+ Q_PROPERTY(QString gotoFlightMode READ gotoFlightMode CONSTANT) ///< Flight mode vehicle is in while performing goto
Q_PROPERTY(ParameterManager* parameterManager READ parameterManager CONSTANT)
@@ -761,10 +762,11 @@ public:
/// @param percent 0-no power, 100-full power
Q_INVOKABLE void motorTest(int motor, int percent);
- bool guidedModeSupported (void) const;
- bool pauseVehicleSupported (void) const;
- bool orbitModeSupported (void) const;
- bool takeoffVehicleSupported(void) const;
+ bool guidedModeSupported (void) const;
+ bool pauseVehicleSupported (void) const;
+ bool orbitModeSupported (void) const;
+ bool takeoffVehicleSupported (void) const;
+ QString gotoFlightMode (void) const;
// Property accessors
diff --git a/src/VideoStreaming/VideoReceiver.cc b/src/VideoStreaming/VideoReceiver.cc
index a50436afe5afeee19ea0d3122381f43a772ecfdd..3ff914693a145ff8322ec56e4e5e03a423cc6ebe 100644
--- a/src/VideoStreaming/VideoReceiver.cc
+++ b/src/VideoStreaming/VideoReceiver.cc
@@ -239,9 +239,10 @@ VideoReceiver::start()
#else
bool isTaisyncUSB = false;
#endif
- bool isUdp = _uri.contains("udp://") && !isTaisyncUSB;
- bool isRtsp = _uri.contains("rtsp://") && !isTaisyncUSB;
- bool isTCP = _uri.contains("tcp://") && !isTaisyncUSB;
+ bool isUdp = _uri.contains("udp://") && !isTaisyncUSB;
+ bool isRtsp = _uri.contains("rtsp://") && !isTaisyncUSB;
+ bool isTCP = _uri.contains("tcp://") && !isTaisyncUSB;
+ bool isMPEGTS = _uri.contains("mpegts://") && !isTaisyncUSB;
if (!isTaisyncUSB && _uri.isEmpty()) {
qCritical() << "VideoReceiver::start() failed because URI is not specified";
@@ -281,7 +282,7 @@ VideoReceiver::start()
break;
}
- if(isUdp || isTaisyncUSB) {
+ if(isUdp || isMPEGTS || isTaisyncUSB) {
dataSource = gst_element_factory_make("udpsrc", "udp-source");
} else if(isTCP) {
dataSource = gst_element_factory_make("tcpclientsrc", "tcpclient-source");
@@ -309,24 +310,26 @@ VideoReceiver::start()
} else if(isTCP) {
QUrl url(_uri);
g_object_set(static_cast(dataSource), "host", qPrintable(url.host()), "port", url.port(), nullptr );
+ } else if(isMPEGTS) {
+ QUrl url(_uri);
+ g_object_set(static_cast(dataSource), "port", url.port(), nullptr);
} else {
g_object_set(static_cast(dataSource), "location", qPrintable(_uri), "latency", 17, "udp-reconnect", 1, "timeout", _udpReconnect_us, NULL);
}
- // Currently, we expect H264 when using anything except for TCP. Long term we may want this to be settable
- if (isTCP) {
- if ((demux = gst_element_factory_make("tsdemux", "mpeg2-ts-demuxer")) == nullptr) {
+ if (isTCP || isMPEGTS) {
+ if ((demux = gst_element_factory_make("tsdemux", "mpeg-ts-demuxer")) == nullptr) {
qCritical() << "VideoReceiver::start() failed. Error with gst_element_factory_make('tsdemux')";
break;
}
} else {
if(!isTaisyncUSB) {
if ((demux = gst_element_factory_make("rtph264depay", "rtp-h264-depacketizer")) == nullptr) {
- qCritical() << "VideoReceiver::start() failed. Error with gst_element_factory_make('rtph264depay')";
- break;
+ qCritical() << "VideoReceiver::start() failed. Error with gst_element_factory_make('rtph264depay')";
+ break;
+ }
}
}
- }
if ((parser = gst_element_factory_make("h264parse", "h264-parser")) == nullptr) {
qCritical() << "VideoReceiver::start() failed. Error with gst_element_factory_make('h264parse')";
@@ -374,13 +377,13 @@ VideoReceiver::start()
qCritical() << "Unable to link Taisync USB elements.";
break;
}
- } else if (isTCP) {
+ } else if (isTCP || isMPEGTS) {
if(!gst_element_link(dataSource, demux)) {
- qCritical() << "Unable to link TCP dataSource to Demux.";
+ qCritical() << "Unable to link TCP/MPEG-TS dataSource to Demux.";
break;
}
if(!gst_element_link_many(parser, _tee, queue, decoder, queue1, _videoSink, nullptr)) {
- qCritical() << "Unable to link TCP pipline to parser.";
+ qCritical() << "Unable to link TCP/MPEG-TS pipline to parser.";
break;
}
g_signal_connect(demux, "pad-added", G_CALLBACK(newPadCB), parser);
@@ -469,7 +472,7 @@ VideoReceiver::start()
void
VideoReceiver::stop()
{
- if(!qgcApp()->runningUnitTests()) {
+ if(qgcApp()->runningUnitTests()) {
return;
}
#if defined(QGC_GST_STREAMING)
diff --git a/src/VideoStreaming/VideoStreaming.cc b/src/VideoStreaming/VideoStreaming.cc
index 265d6ecaeac69805668090d83ea3e170711ac8a9..cd02747e7a87ee4789fa939890dc641e22ae8de7 100644
--- a/src/VideoStreaming/VideoStreaming.cc
+++ b/src/VideoStreaming/VideoStreaming.cc
@@ -130,11 +130,13 @@ void initializeVideoStreaming(int &argc, char* argv[], char* logpath, char* debu
#else
//-- Generic initialization
if (logpath) {
+ QString gstDebugFile = QString("%1/%2").arg(logpath).arg("gstreamer-log.txt");
+ qDebug() << "GStreamer debug output:" << gstDebugFile;
if (debuglevel) {
qputenv("GST_DEBUG", debuglevel);
}
qputenv("GST_DEBUG_NO_COLOR", "1");
- qputenv("GST_DEBUG_FILE", QString("%1/%2").arg(logpath).arg("gstreamer-log.txt").toUtf8());
+ qputenv("GST_DEBUG_FILE", gstDebugFile.toUtf8());
qputenv("GST_DEBUG_DUMP_DOT_DIR", logpath);
}
GError* error = nullptr;
diff --git a/src/api/QGCCorePlugin.h b/src/api/QGCCorePlugin.h
index 13deb754b36299775f9001bf4a08d3d2f348fb2c..a4812577ec933c2593e3647e866efb722b113ad0 100644
--- a/src/api/QGCCorePlugin.h
+++ b/src/api/QGCCorePlugin.h
@@ -139,6 +139,11 @@ public:
/// Custom builds must override to provide their own location.
virtual QString stableDownloadLocation(void) const { return QString("qgroundcontrol.com"); }
+ /// Returns the complex mission items to display in the Plan UI
+ /// @param complexMissionItemNames Default set of complex items
+ /// @return Complex items to be made available to user
+ virtual QStringList complexMissionItemNames(Vehicle* vehicle, const QStringList& complexMissionItemNames) { Q_UNUSED(vehicle); return complexMissionItemNames; }
+
bool showTouchAreas(void) const { return _showTouchAreas; }
bool showAdvancedUI(void) const { return _showAdvancedUI; }
void setShowTouchAreas(bool show);
diff --git a/src/ui/preferences/GeneralSettings.qml b/src/ui/preferences/GeneralSettings.qml
index fdb49133e4eca3d21567d10792f5011780fabc91..2a906c2cc44f64d193a255b512126ac86226936a 100644
--- a/src/ui/preferences/GeneralSettings.qml
+++ b/src/ui/preferences/GeneralSettings.qml
@@ -37,7 +37,7 @@ QGCView {
property Fact _userBrandImageIndoor: QGroundControl.settingsManager.brandImageSettings.userBrandImageIndoor
property Fact _userBrandImageOutdoor: QGroundControl.settingsManager.brandImageSettings.userBrandImageOutdoor
property real _labelWidth: ScreenTools.defaultFontPixelWidth * 20
- property real _comboFieldWidth: ScreenTools.defaultFontPixelWidth * 25
+ property real _comboFieldWidth: ScreenTools.defaultFontPixelWidth * 28
property real _valueFieldWidth: ScreenTools.defaultFontPixelWidth * 10
property Fact _mapProvider: QGroundControl.settingsManager.flightMapSettings.mapProvider
property Fact _mapType: QGroundControl.settingsManager.flightMapSettings.mapType
@@ -51,6 +51,7 @@ QGCView {
property bool _isUDP: _isGst && _videoSource === QGroundControl.settingsManager.videoSettings.udpVideoSource
property bool _isRTSP: _isGst && _videoSource === QGroundControl.settingsManager.videoSettings.rtspVideoSource
property bool _isTCP: _isGst && _videoSource === QGroundControl.settingsManager.videoSettings.tcpVideoSource
+ property bool _isMPEGTS: _isGst && _videoSource === QGroundControl.settingsManager.videoSettings.mpegtsVideoSource
readonly property real _internalWidthRatio: 0.8
@@ -707,7 +708,6 @@ QGCView {
Layout.fillWidth: false
Layout.fillHeight: false
columns: 2
-
QGCLabel {
text: qsTr("Video Source")
visible: QGroundControl.settingsManager.videoSettings.videoSource.visible
@@ -722,12 +722,12 @@ QGCView {
QGCLabel {
text: qsTr("UDP Port")
- visible: _isUDP && QGroundControl.settingsManager.videoSettings.udpPort.visible
+ visible: (_isUDP || _isMPEGTS) && QGroundControl.settingsManager.videoSettings.udpPort.visible
}
FactTextField {
Layout.preferredWidth: _comboFieldWidth
fact: QGroundControl.settingsManager.videoSettings.udpPort
- visible: _isUDP && QGroundControl.settingsManager.videoSettings.udpPort.visible
+ visible: (_isUDP || _isMPEGTS) && QGroundControl.settingsManager.videoSettings.udpPort.visible
}
QGCLabel {