Commit ccdc194d authored by Don Gagne's avatar Don Gagne

Separated Flight map into View and Widget

parent ff0579c1
......@@ -140,12 +140,12 @@ INCLUDEPATH += \
src/audio \
src/AutoPilotPlugins \
src/comm \
src/FlightDisplay \
src/input \
src/lib/qmapcontrol \
src/QmlControls \
src/uas \
src/ui \
src/ui/flightdisplay \
src/ui/linechart \
src/ui/map \
src/ui/mapdisplay \
......@@ -238,6 +238,8 @@ HEADERS += \
src/comm/QGCMAVLink.h \
src/comm/TCPLink.h \
src/comm/UDPLink.h \
src/FlightDisplay/FlightDisplayWidget.h \
src/FlightDisplay/FlightDisplayView.h \
src/GAudioOutput.h \
src/HomePositionManager.h \
src/LogCompressor.h \
......@@ -264,7 +266,6 @@ HEADERS += \
src/uas/UASInterface.h \
src/uas/UASMessageHandler.h \
src/uas/UASWaypointManager.h \
src/ui/flightdisplay/FlightDisplay.h \
src/ui/HDDisplay.h \
src/ui/HSIDisplay.h \
src/ui/HUD.h \
......@@ -373,6 +374,8 @@ SOURCES += \
src/comm/MockLinkMissionItemHandler.cc \
src/comm/TCPLink.cc \
src/comm/UDPLink.cc \
src/FlightDisplay/FlightDisplayWidget.cc \
src/FlightDisplay/FlightDisplayView.cc \
src/GAudioOutput.cc \
src/HomePositionManager.cc \
src/LogCompressor.cc \
......@@ -394,7 +397,6 @@ SOURCES += \
src/uas/UAS.cc \
src/uas/UASMessageHandler.cc \
src/uas/UASWaypointManager.cc \
src/ui/flightdisplay/FlightDisplay.cc \
src/ui/HDDisplay.cc \
src/ui/HSIDisplay.cc \
src/ui/HUD.cc \
......
......@@ -116,7 +116,8 @@
<file alias="AirframeComponentSummary.qml">src/AutoPilotPlugins/PX4/AirframeComponentSummary.qml</file>
<file alias="AirframeComponent.qml">src/AutoPilotPlugins/PX4/AirframeComponent.qml</file>
<file alias="MainToolBar.qml">src/ui/toolbar/MainToolBar.qml</file>
<file alias="FlightDisplay.qml">src/ui/flightdisplay/FlightDisplay.qml</file>
<file alias="FlightDisplayView.qml">src/FlightDisplay/FlightDisplayView.qml</file>
<file alias="FlightDisplayWidget.qml">src/FlightDisplay/FlightDisplayWidget.qml</file>
<file alias="MapDisplay.qml">src/ui/mapdisplay/MapDisplay.qml</file>
<!-- FlightMap module -->
......
......@@ -21,12 +21,6 @@ This file is part of the QGROUNDCONTROL project
======================================================================*/
/**
* @file
* @brief QGC Main Flight Display
* @author Gus Grubba <mavlink@grubba.com>
*/
#include <QQmlContext>
#include <QQmlEngine>
#include <QSettings>
......@@ -36,15 +30,15 @@ This file is part of the QGROUNDCONTROL project
#include "VideoReceiver.h"
#include "ScreenToolsController.h"
#include "FlightDisplay.h"
#include "FlightDisplayView.h"
const char* kMainFlightDisplayGroup = "MainFlightDisplay";
const char* kMainFlightDisplayViewGroup = "FlightDisplayView";
FlightDisplay::FlightDisplay(QWidget *parent)
FlightDisplayView::FlightDisplayView(QWidget *parent)
: QGCQmlWidgetHolder(parent)
{
setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::MinimumExpanding);
setObjectName("MainFlightDisplay");
setObjectName("FlightDisplayView");
// Get rid of layout default margins
QLayout* pl = layout();
if(pl) {
......@@ -90,26 +84,26 @@ FlightDisplay::FlightDisplay(QWidget *parent)
#endif
setContextPropertyObject("videoReceiver", pReceiver);
setSource(QUrl::fromUserInput("qrc:/qml/FlightDisplay.qml"));
setSource(QUrl::fromUserInput("qrc:/qml/FlightDisplayView.qml"));
setVisible(true);
}
FlightDisplay::~FlightDisplay()
FlightDisplayView::~FlightDisplayView()
{
}
void FlightDisplay::saveSetting(const QString &name, const QString& value)
void FlightDisplayView::saveSetting(const QString &name, const QString& value)
{
QSettings settings;
QString key(kMainFlightDisplayGroup);
QString key(kMainFlightDisplayViewGroup);
key += "/" + name;
settings.setValue(key, value);
}
QString FlightDisplay::loadSetting(const QString &name, const QString& defaultValue)
QString FlightDisplayView::loadSetting(const QString &name, const QString& defaultValue)
{
QSettings settings;
QString key(kMainFlightDisplayGroup);
QString key(kMainFlightDisplayViewGroup);
key += "/" + name;
return settings.value(key, defaultValue).toString();
}
......@@ -21,25 +21,17 @@ This file is part of the QGROUNDCONTROL project
======================================================================*/
/**
* @file
* @brief QGC Main Flight Display
* @author Gus Grubba <mavlink@grubba.com>
*/
#ifndef QGCFLIGHTDISPLAY_H
#define QGCFLIGHTDISPLAY_H
#ifndef FlightDisplayView_H
#define FlightDisplayView_H
#include "QGCQmlWidgetHolder.h"
class UASInterface;
class FlightDisplay : public QGCQmlWidgetHolder
class FlightDisplayView : public QGCQmlWidgetHolder
{
Q_OBJECT
public:
FlightDisplay(QWidget* parent = NULL);
~FlightDisplay();
FlightDisplayView(QWidget* parent = NULL);
~FlightDisplayView();
/// @brief Invokes the Flight Display Options menu
void showOptionsMenu() { emit showOptionsMenuChanged(); }
......@@ -60,4 +52,4 @@ signals:
};
#endif // QGCFLIGHTDISPLAY_H
#endif
/*=====================================================================
QGroundControl Open Source Ground Control Station
(c) 2009, 2015 QGROUNDCONTROL PROJECT <http://www.qgroundcontrol.org>
This file is part of the QGROUNDCONTROL project
QGROUNDCONTROL is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
QGROUNDCONTROL is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with QGROUNDCONTROL. If not, see <http://www.gnu.org/licenses/>.
======================================================================*/
import QtQuick 2.4
import QtQuick.Controls 1.3
import QtQuick.Controls.Styles 1.2
import QtQuick.Dialogs 1.2
import QGroundControl.FlightMap 1.0
import QGroundControl.ScreenTools 1.0
import QGroundControl.Controls 1.0
import QGroundControl.Palette 1.0
/// Flight Display View
Item {
id: root
property var __qgcPal: QGCPalette { colorGroupEnabled: enabled }
property var _activeVehicle: multiVehicleManager.activeVehicle
readonly property real _defaultLatitude: 37.803784
readonly property real _defaultLongitude: -122.462276
readonly property real _defaultRoll: 0
readonly property real _defaultPitch: 0
readonly property real _defaultHeading: 0
readonly property real _defaultAltitudeWGS84: 0
readonly property real _defaultGroundSpeed: 0
readonly property real _defaultAirSpeed: 0
readonly property real _defaultClimbRate: 0
property real _roll: _activeVehicle ? (isNaN(_activeVehicle.roll) ? _defaultRoll : _activeVehicle.roll) : _defaultRoll
property real _pitch: _activeVehicle ? (isNaN(_activeVehicle.pitch) ? _defaultPitch : _activeVehicle.pitch) : _defaultPitch
property real _latitude: _activeVehicle ? ((_activeVehicle.latitude === 0) ? _defaultLatitude : _activeVehicle.latitude) : _defaultLatitude
property real _longitude: _activeVehicle ? ((_activeVehicle.longitude === 0) ? _defaultLongitude : _activeVehicle.longitude) : _defaultLongitude
property real _heading: _activeVehicle ? (isNaN(_activeVehicle.heading) ? _defaultHeading : _activeVehicle.heading) : _defaultHeading
property real _altitudeWGS84: _activeVehicle ? _activeVehicle.altitudeWGS84 : _defaultAltitudeWGS84
property real _groundSpeed: _activeVehicle ? _activeVehicle.groundSpeed : _defaultGroundSpeed
property real _airSpeed: _activeVehicle ? _activeVehicle.airSpeed : _defaultAirSpeed
property real _climbRate: _activeVehicle ? _activeVehicle.climbRate : _defaultClimbRate
function getBool(value) {
return value === '0' ? false : true;
}
function setBool(value) {
return value ? "1" : "0";
}
FlightMap {
id: flightMap
anchors.fill: parent
mapName: "FlightDisplayView"
latitude: _latitude
longitude: _longitude
z: 10
showVehicles: true
}
QGCCompassWidget {
x: ScreenTools.defaultFontPixelSize * (7.1)
y: ScreenTools.defaultFontPixelSize * (0.42)
size: ScreenTools.defaultFontPixelSize * (13.3)
heading: _heading
active: multiVehicleManager.activeVehicleAvailable
z: flightMap.z + 2
}
QGCAttitudeWidget {
anchors.rightMargin: ScreenTools.defaultFontPixelSize * (7.1)
anchors.right: parent.right
y: ScreenTools.defaultFontPixelSize * (0.42)
size: ScreenTools.defaultFontPixelSize * (13.3)
rollAngle: _roll
pitchAngle: _pitch
active: multiVehicleManager.activeVehicleAvailable
z: flightMap.z + 2
}
QGCAltitudeWidget {
anchors.right: parent.right
height: parent.height * 0.65 > ScreenTools.defaultFontPixelSize * (23.4) ? ScreenTools.defaultFontPixelSize * (23.4) : parent.height * 0.65
width: ScreenTools.defaultFontPixelSize * (5)
altitude: _altitudeWGS84
z: 30
}
QGCSpeedWidget {
anchors.left: parent.left
width: ScreenTools.defaultFontPixelSize * (5)
height: parent.height * 0.65 > ScreenTools.defaultFontPixelSize * (23.4) ? ScreenTools.defaultFontPixelSize * (23.4) : parent.height * 0.65
speed: _groundSpeed
z: 40
}
QGCCurrentSpeed {
anchors.left: parent.left
width: ScreenTools.defaultFontPixelSize * (6.25)
airspeed: _airSpeed
groundspeed: _groundSpeed
active: multiVehicleManager.activeVehicleAvailable
z: 50
}
QGCCurrentAltitude {
anchors.right: parent.right
width: ScreenTools.defaultFontPixelSize * (6.25)
altitude: _altitudeWGS84
vertZ: _climbRate
active: multiVehicleManager.activeVehicleAvailable
z: 60
}
}
/*=====================================================================
QGroundControl Open Source Ground Control Station
(c) 2009, 2015 QGROUNDCONTROL PROJECT <http://www.qgroundcontrol.org>
This file is part of the QGROUNDCONTROL project
QGROUNDCONTROL is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
QGROUNDCONTROL is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with QGROUNDCONTROL. If not, see <http://www.gnu.org/licenses/>.
======================================================================*/
#include <QQmlContext>
#include <QQmlEngine>
#include <QSettings>
#include <VideoItem.h>
#include <VideoSurface.h>
#include "VideoReceiver.h"
#include "ScreenToolsController.h"
#include "FlightDisplayWidget.h"
const char* kMainFlightDisplayWidgetGroup = "FlightDisplayWidget";
FlightDisplayWidget::FlightDisplayWidget(QWidget *parent)
: QGCQmlWidgetHolder(parent)
{
setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::MinimumExpanding);
setObjectName("FlightDisplayWidget");
// Get rid of layout default margins
QLayout* pl = layout();
if(pl) {
pl->setContentsMargins(0,0,0,0);
}
#ifndef __android__
setMinimumWidth( 31 * ScreenToolsController::defaultFontPixelSize_s());
setMinimumHeight(33 * ScreenToolsController::defaultFontPixelSize_s());
#endif
setContextPropertyObject("flightDisplay", this);
/*
* 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=5000
*
* 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* pSurface = new VideoSurface;
setContextPropertyObject("videoDisplay", pSurface);
VideoReceiver* pReceiver = new VideoReceiver(this);
pReceiver->setUri(QLatin1Literal("udp://0.0.0.0:5000"));
#if defined(QGC_GST_STREAMING)
pReceiver->setVideoSink(pSurface->videoSink());
#endif
setContextPropertyObject("videoReceiver", pReceiver);
setSource(QUrl::fromUserInput("qrc:/qml/FlightDisplayWidget.qml"));
setVisible(true);
}
FlightDisplayWidget::~FlightDisplayWidget()
{
}
void FlightDisplayWidget::saveSetting(const QString &name, const QString& value)
{
QSettings settings;
QString key(kMainFlightDisplayWidgetGroup);
key += "/" + name;
settings.setValue(key, value);
}
QString FlightDisplayWidget::loadSetting(const QString &name, const QString& defaultValue)
{
QSettings settings;
QString key(kMainFlightDisplayWidgetGroup);
key += "/" + name;
return settings.value(key, defaultValue).toString();
}
/*=====================================================================
QGroundControl Open Source Ground Control Station
(c) 2009, 2015 QGROUNDCONTROL PROJECT <http://www.qgroundcontrol.org>
This file is part of the QGROUNDCONTROL project
QGROUNDCONTROL is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
QGROUNDCONTROL is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with QGROUNDCONTROL. If not, see <http://www.gnu.org/licenses/>.
======================================================================*/
#ifndef FlightDisplayWidget_H
#define FlightDisplayWidget_H
#include "QGCQmlWidgetHolder.h"
class FlightDisplayWidget : public QGCQmlWidgetHolder
{
Q_OBJECT
public:
FlightDisplayWidget(QWidget* parent = NULL);
~FlightDisplayWidget();
/// @brief Invokes the Flight Display Options menu
void showOptionsMenu() { emit showOptionsMenuChanged(); }
Q_PROPERTY(bool hasVideo READ hasVideo CONSTANT)
Q_INVOKABLE void saveSetting (const QString &key, const QString& value);
Q_INVOKABLE QString loadSetting (const QString &key, const QString& defaultValue);
#if defined(QGC_GST_STREAMING)
bool hasVideo () { return true; }
#else
bool hasVideo () { return false; }
#endif
signals:
void showOptionsMenuChanged ();
};
#endif
......@@ -33,7 +33,7 @@ import QtLocation 5.3
import QtPositioning 5.3
import QGroundControl.Controls 1.0
import QGroundControl.FlightMap 1.0
import QGroundControl.FlightMap 1.0
import QGroundControl.ScreenTools 1.0
import QGroundControl.MultiVehicleManager 1.0
import QGroundControl.Vehicle 1.0
......@@ -46,20 +46,16 @@ Item {
property real longitude: 0
property real zoomLevel: 18
property real heading: 0
property bool alwaysNorth: true
property bool interactive: true
property bool showVehicles: true
property string mapName: 'defaultMap'
property alias mapItem: map
property alias mapMenu: mapTypeMenu
property alias readOnly: map.readOnly
property bool showVehicles: false
Component.onCompleted: {
map.zoomLevel = 18
mapTypeMenu.update();
if (showVehicles) {
addExistingVehicles()
}
addExistingVehicles()
}
//-- Menu to select supported map types
......@@ -116,6 +112,7 @@ Item {
}
}
/*
function formatDistance(meters)
{
var dist = Math.round(meters)
......@@ -134,37 +131,56 @@ Item {
}
return dist
}
*/
// The following code is used to add and remove Vehicle markers from the map. Due to the following
// problems this code must be here is the base FlightMap control:
// - If you pass a reference to the Map control into another object and then try to call
// functions such as addMapItem on it, it will fail telling you addMapItem is not a function
// on that object
// - Due to the fact that you need to dynamically add the MapQuickItems, they need to be able
// to reference the Vehicle they are associated with in some way. In order to do that
// we need to keep a separate array of Vehicles which must be at the top level of the object
// hierarchy in order for the dynamically added object to see it.
property var vehicles: [] ///< List of known vehicles
property var vehicleMapItems: [] ///< List of know vehicle map items
property var _vehicles: [] ///< List of known vehicles
property var _vehicleMapItems: [] ///< List of known vehicle map items
Connections {
target: multiVehicleManager
onVehicleAdded: addVehicle(vehicle)
onVehicleRemoved: removeVehicle(vehicle)
}
function addVehicle(vehicle) {
var qmlItemTemplate = "VehicleMapItem { " +
"coordinate: vehicles[%1].coordinate; " +
"heading: vehicles[%1].heading " +
"}"
var qmlItemTemplate = "VehicleMapItem { " +
"coordinate: _vehicles[%1].coordinate; " +
"heading: _vehicles[%1].heading " +
"}"
var i = vehicles.length
qmlItemTemplate = qmlItemTemplate.replace("%1", i)
qmlItemTemplate = qmlItemTemplate.replace("%1", i)
var i = _vehicles.length
qmlItemTemplate = qmlItemTemplate.replace("%1", i)
qmlItemTemplate = qmlItemTemplate.replace("%1", i)
vehicles.push(vehicle)
var mapItem = Qt.createQmlObject (qmlItemTemplate, map)
vehicleMapItems.push(mapItem)
_vehicles.push(vehicle)
var mapItem = Qt.createQmlObject (qmlItemTemplate, map)
_vehicleMapItems.push(mapItem)
mapItem.z = map.z + 1
map.addMapItem(mapItem)
mapItem.z = map.z + 1
map.addMapItem(mapItem)
}
function removeVehicle(vehicle) {
for (var i=0; i<vehicles.length; i++) {
if (vehicles[i] == vehicle) {
vehicle[i] = undefined
map.removeMapItem(vehicleMapItems[i])
vehicleMapItems[i] = undefined
break
}
for (var i=0; i<_vehicles.length; i++) {
if (_vehicles[i] == vehicle) {
_vehicle[i] = undefined
map.removeMapItem(_vehicleMapItems[i])
_vehicleMapItems[i] = undefined
break
}
}
}
function addExistingVehicles() {
......@@ -173,18 +189,12 @@ Item {
}
}
Plugin {
id: mapPlugin
name: "QGroundControl"
}
Connections {
target: multiVehicleManager
onVehicleAdded: addVehicle(vehicle)
onVehicleRemoved: removeVehicle(vehicle)
}
Map {
id: map
......@@ -194,7 +204,6 @@ Item {
property int pressX : -1
property int pressY : -1
property bool changed: false
property bool readOnly: false
property variant scaleLengths: [5, 10, 25, 50, 100, 150, 250, 500, 1000, 2000, 5000, 10000, 20000, 50000, 100000, 200000, 500000, 1000000, 2000000]
plugin: mapPlugin
......@@ -206,18 +215,7 @@ Item {
gesture.flickDeceleration: 3000
gesture.enabled: root.interactive
/*
// There is a bug currently in Qt where it fails to render a map taller than 6 tiles high. Until
// that's fixed, we can't rotate the map as it would require a larger map, which can easily grow
// larger than 6 tiles high.
// https://bugreports.qt.io/browse/QTBUG-45508
transform: Rotation {
origin.x: map.width / 2
origin.y: map.height / 2
angle: map.visible ? (alwaysNorth ? 0 : -heading) : 0
}
*/
/*
onWidthChanged: {
scaleTimer.restart()
}
......@@ -229,6 +227,7 @@ Item {
onZoomLevelChanged:{
scaleTimer.restart()
}
*/
MouseArea {
anchors.fill: parent
......@@ -240,6 +239,7 @@ Item {
}
}
/*
function calculateScale() {
var coord1, coord2, dist, text, f
f = 0
......@@ -265,8 +265,46 @@ Item {
scaleImage.width = (scaleImage.sourceSize.width * f) - 2 * scaleImageLeft.sourceSize.width
scaleText.text = text
}
*/
}
Column {
anchors.margins: ScreenTools.defaultFontPixelWidth
anchors.right: parent.right
anchors.bottom: parent.bottom
spacing: ScreenTools.defaultFontPixelWidth / 2
QGCButton {
id: optionsButton
text: "Options"
menu: mapTypeMenu
}
Row {
layoutDirection: Qt.RightToLeft
spacing: ScreenTools.defaultFontPixelWidth / 2
property real zoomIncrement: 1.0
property real buttonWidth: (optionsButton.width - spacing) / 2
QGCButton {
width: parent.buttonWidth
text: "+"
onClicked: map.zoomLevel = map.zoomLevel + parent.zoomIncrement
}
QGCButton {
width: parent.buttonWidth
text: "-"
onClicked: map.zoomLevel = map.zoomLevel - parent.zoomIncrement
}
}
}
/*
The slider and scale display are commented out for now to try to save real estate - DonLakeFlyer
Not sure if I'll bring them back or not. Need room for waypoint list at bottom
QGCSlider {
id: zoomSlider;
minimum: map.minimumZoomLevel;
......@@ -345,15 +383,12 @@ Item {
map.calculateScale()
}
}
*/
onVisibleChanged: {
adjustSize();
}
onAlwaysNorthChanged: {
adjustSize();
}
onWidthChanged: {
adjustSize();
}
......
......@@ -32,11 +32,20 @@ import QGroundControl.ScreenTools 1.0
Item {
id: root
anchors.centerIn: parent
property real rollAngle : 0
property real pitchAngle: 0
property bool active: false ///< true: actively connected to data provider, false: show inactive control
property real rollAngle : _defaultRollAngle
property real pitchAngle: _defaultPitchAngle
property bool showPitch: true
readonly property real _defaultRollAngle: 0
readonly property real _defaultPitchAngle: 0
property real _rollAngle: active ? rollAngle : _defaultRollAngle
property real _pitchAngle: active ? pitchAngle : _defaultPitchAngle
anchors.centerIn: parent
Image {
id: rollDial
anchors { bottom: root.verticalCenter; horizontalCenter: parent.horizontalCenter}
......@@ -47,7 +56,7 @@ Item {
transform