diff --git a/ground/openpilotgcs/share/openpilotgcs/pfd/default/AltitudeScale.qml b/ground/openpilotgcs/share/openpilotgcs/pfd/default/AltitudeScale.qml
new file mode 100644
index 000000000..6e5b608f7
--- /dev/null
+++ b/ground/openpilotgcs/share/openpilotgcs/pfd/default/AltitudeScale.qml
@@ -0,0 +1,83 @@
+import Qt 4.7
+
+Item {
+ id: sceneItem
+ property variant sourceSize
+
+ Image {
+ id: altitude_bg
+ source: "image://svg/pfd.svg!altitude-bg"
+ sourceSize: sceneItem.sourceSize
+ clip: true
+
+ property variant scaledBounds: svgRenderer.scaledElementBounds("pfd.svg", "altitude-bg")
+
+ x: scaledBounds.x * sceneItem.width
+ y: scaledBounds.y * sceneItem.height
+ width: scaledBounds.width * sceneItem.width
+ height: scaledBounds.height * sceneItem.height
+
+ Image {
+ id: altitude_scale
+
+ source: "image://svg/pfd.svg!altitude-scale"
+ sourceSize: sceneItem.sourceSize
+
+ anchors.verticalCenter: parent.verticalCenter
+ // The altitude scale represents 30 meters,
+ // move it in 0..5m range
+ anchors.verticalCenterOffset: -height/30 * (PositionActual.Down-Math.floor(PositionActual.Down/5)*5)
+ anchors.left: parent.left
+
+ property int topNumber: 15-Math.floor(PositionActual.Down/5)*5
+
+ // Altitude numbers
+ Column {
+ Repeater {
+ model: 7
+ Item {
+ height: altitude_scale.height / 6
+ width: altitude_bg.width
+
+ Text {
+ text: altitude_scale.topNumber - index*5
+ color: "white"
+ font.pixelSize: parent.height / 4
+ font.family: "Arial"
+
+ anchors.horizontalCenter: parent.horizontalCenter
+ anchors.verticalCenter: parent.top
+ }
+ }
+ }
+ }
+ }
+ }
+
+
+ Image {
+ id: altitude_window
+ clip: true
+
+ source: "image://svg/pfd.svg!altitude-window"
+ sourceSize: sceneItem.sourceSize
+
+ property variant scaledBounds: svgRenderer.scaledElementBounds("pfd.svg", "altitude-window")
+
+ x: scaledBounds.x * sceneItem.width
+ y: scaledBounds.y * sceneItem.height
+ width: scaledBounds.width * sceneItem.width
+ height: scaledBounds.height * sceneItem.height
+
+ Text {
+ id: altitude_text
+ text: Math.floor(-PositionActual.Down).toFixed()
+ color: "white"
+ font {
+ family: "Arial"
+ pixelSize: parent.height * 0.6
+ }
+ anchors.centerIn: parent
+ }
+ }
+}
diff --git a/ground/openpilotgcs/share/openpilotgcs/pfd/default/Pfd.qml b/ground/openpilotgcs/share/openpilotgcs/pfd/default/Pfd.qml
new file mode 100644
index 000000000..517aa5b6a
--- /dev/null
+++ b/ground/openpilotgcs/share/openpilotgcs/pfd/default/Pfd.qml
@@ -0,0 +1,120 @@
+import Qt 4.7
+import "."
+import org.OpenPilot 1.0
+//import "/home/dima/work/RC/OsgEarthQml-build-desktop-Qt_4_8_1_in_PATH__System__Debug"
+
+Rectangle {
+ color: "#666666"
+
+ Image {
+ id: background
+ source: "image://svg/pfd.svg!background"
+
+ fillMode: Image.PreserveAspectFit
+ anchors.fill: parent
+
+ sourceSize.width: width
+ sourceSize.height: height
+
+ Item {
+ id: sceneItem
+ width: parent.paintedWidth
+ height: parent.paintedHeight
+ anchors.centerIn: parent
+ clip: true
+
+ Image {
+ id: world
+ source: "image://svg/pfd.svg!world"
+ sourceSize: background.sourceSize
+ smooth: true
+ visible: !qmlWidget.terrainEnabled
+
+ transform: [
+ Translate {
+ id: pitchTranslate
+ x: (world.parent.width - world.width)/2
+ y: (world.parent.height - world.height)/2 + AttitudeActual.Pitch*world.parent.height/94
+ },
+ Rotation {
+ angle: -AttitudeActual.Roll
+ origin.x : world.parent.width/2
+ origin.y : world.parent.height/2
+ }
+ ]
+ }
+
+ OsgEarth {
+ id: earthView
+
+ anchors.fill: parent
+ sceneFile: qmlWidget.earthFile
+ visible: qmlWidget.terrainEnabled
+
+ fieldOfView: 90
+
+ yaw: AttitudeActual.Yaw
+ pitch: AttitudeActual.Pitch
+ roll: AttitudeActual.Roll
+
+
+ latitude: -27.935474
+ longitude: 153.187147
+ altitude: 3000
+ //altitude: PositionActual.Down
+ }
+
+ Image {
+ id: rollscale
+ source: "image://svg/pfd.svg!rollscale"
+ sourceSize: background.sourceSize
+ smooth: true
+
+ transformOrigin: Item.Center
+ rotation: -AttitudeActual.Roll
+ }
+
+ Image {
+ id: foreground
+ source: "image://svg/pfd.svg!foreground"
+ sourceSize: background.sourceSize
+ anchors.centerIn: parent
+ }
+
+ Image {
+ id: compass
+ source: "image://svg/pfd.svg!compass"
+ sourceSize: background.sourceSize
+ clip: true
+
+ y: 12
+ anchors.horizontalCenter: parent.horizontalCenter
+
+ Image {
+ id: compass_band
+ source: "image://svg/pfd.svg!compass-band"
+ sourceSize: background.sourceSize
+
+ anchors.centerIn: parent
+ //the band is 540 degrees wide
+ anchors.horizontalCenterOffset: -1*AttitudeActual.Yaw/540*width
+ }
+ }
+
+ SpeedScale {
+ anchors.fill: parent
+ sourceSize: background.sourceSize
+ }
+
+ AltitudeScale {
+ anchors.fill: parent
+ sourceSize: background.sourceSize
+ }
+
+ PfdIndicators {
+ anchors.fill: parent
+ sourceSize: background.sourceSize
+ }
+ }
+ }
+}
diff --git a/ground/openpilotgcs/share/openpilotgcs/pfd/default/PfdIndicators.qml b/ground/openpilotgcs/share/openpilotgcs/pfd/default/PfdIndicators.qml
new file mode 100644
index 000000000..d520dcf00
--- /dev/null
+++ b/ground/openpilotgcs/share/openpilotgcs/pfd/default/PfdIndicators.qml
@@ -0,0 +1,70 @@
+import Qt 4.7
+
+Item {
+ id: sceneItem
+ property variant sourceSize
+
+ //telemetry status arrow
+ Image {
+ id: telemetry_status
+ source: "image://svg/pfd.svg!gcstelemetry-"+statusName
+ sourceSize: sceneItem.sourceSize
+
+ property string statusName : ["Disconnected","HandshakeReq","HandshakeAck","Connected"][GCSTelemetryStats.Status]
+
+ property variant scaledBounds: svgRenderer.scaledElementBounds("pfd.svg", "gcstelemetry-Disconnected")
+ x: scaledBounds.x * sceneItem.width
+ y: scaledBounds.y * sceneItem.height
+ width: scaledBounds.width * sceneItem.width
+ height: scaledBounds.height * sceneItem.height
+ }
+
+ //telemetry rate text
+ Text {
+ id: telemetry_rate
+ text: GCSTelemetryStats.TxDataRate.toFixed()+"/"+GCSTelemetryStats.RxDataRate.toFixed()
+ color: "white"
+ font.family: "Arial"
+ font.pixelSize: telemetry_status.height * 0.75
+
+ anchors.top: telemetry_status.bottom
+ anchors.horizontalCenter: telemetry_status.horizontalCenter
+ }
+
+ Text {
+ id: gps_text
+ text: "GPS: " + GPSPosition.Satellites + "\nPDP: " + GPSPosition.PDOP
+ color: "white"
+ font.family: "Arial"
+ font.pixelSize: telemetry_status.height * 0.75
+
+ visible: GPSPosition.Satellites > 0
+
+ property variant scaledBounds: svgRenderer.scaledElementBounds("pfd.svg", "gps-txt")
+ x: scaledBounds.x * sceneItem.width
+ y: scaledBounds.y * sceneItem.height
+ }
+
+ Text {
+ id: battery_text
+
+ text: FlightBatteryState.Voltage.toFixed(2)+" V\n" +
+ FlightBatteryState.Current.toFixed(2)+" A\n" +
+ FlightBatteryState.ConsumedEnergy.toFixed()+" mAh"
+
+
+ color: "white"
+ font.family: "Arial"
+
+ //I think it should be pixel size,
+ //but making it more consistent with C++ version instead
+ font.pointSize: scaledBounds.height * sceneItem.height
+
+ visible: FlightBatteryState.Voltage > 0 || FlightBatteryState.Current > 0
+
+ property variant scaledBounds: svgRenderer.scaledElementBounds("pfd.svg", "battery-txt")
+ x: scaledBounds.x * sceneItem.width
+ y: scaledBounds.y * sceneItem.height
+
+ }
+}
diff --git a/ground/openpilotgcs/share/openpilotgcs/pfd/default/SpeedScale.qml b/ground/openpilotgcs/share/openpilotgcs/pfd/default/SpeedScale.qml
new file mode 100644
index 000000000..ddc82b571
--- /dev/null
+++ b/ground/openpilotgcs/share/openpilotgcs/pfd/default/SpeedScale.qml
@@ -0,0 +1,91 @@
+import Qt 4.7
+
+Item {
+ id: sceneItem
+ property variant sourceSize
+ property real groundSpeed : 3.6 * Math.sqrt(Math.pow(VelocityActual.North,2)+
+ Math.pow(VelocityActual.East,2))
+
+ Image {
+ id: speed_bg
+ source: "image://svg/pfd.svg!speed-bg"
+ sourceSize: sceneItem.sourceSize
+ clip: true
+
+ property variant scaledBounds: svgRenderer.scaledElementBounds("pfd.svg", "speed-bg")
+
+ x: scaledBounds.x * sceneItem.width
+ y: scaledBounds.y * sceneItem.height
+ width: scaledBounds.width * sceneItem.width
+ height: scaledBounds.height * sceneItem.height
+
+ Image {
+ id: speed_scale
+
+ source: "image://svg/pfd.svg!speed-scale"
+ sourceSize: sceneItem.sourceSize
+
+ anchors.verticalCenter: parent.verticalCenter
+ // The speed scale represents 30 meters,
+ // move it in 0..5m range
+ anchors.verticalCenterOffset: height/30 * (sceneItem.groundSpeed-Math.floor(sceneItem.groundSpeed/5)*5)
+ anchors.right: parent.right
+
+ property int topNumber: Math.floor(sceneItem.groundSpeed/5)*5+15
+
+ // speed numbers
+ Column {
+ width: speed_bg.width
+ anchors.right: speed_scale.right
+
+ Repeater {
+ model: 7
+ Item {
+ height: speed_scale.height / 6
+ width: speed_bg.width
+
+ Text {
+ //don't show negative numbers
+ text: speed_scale.topNumber - index*5
+ color: "white"
+ visible: speed_scale.topNumber - index*5 >= 0
+
+ font.pixelSize: parent.height / 4
+ font.family: "Arial"
+
+ anchors.horizontalCenter: parent.horizontalCenter
+ anchors.verticalCenter: parent.top
+ }
+ }
+ }
+ }
+ }
+ }
+
+
+ Image {
+ id: speed_window
+ clip: true
+
+ source: "image://svg/pfd.svg!speed-window"
+ sourceSize: sceneItem.sourceSize
+
+ property variant scaledBounds: svgRenderer.scaledElementBounds("pfd.svg", "speed-window")
+
+ x: scaledBounds.x * sceneItem.width
+ y: scaledBounds.y * sceneItem.height
+ width: scaledBounds.width * sceneItem.width
+ height: scaledBounds.height * sceneItem.height
+
+ Text {
+ id: speed_text
+ text: Math.round(sceneItem.groundSpeed).toFixed()
+ color: "white"
+ font {
+ family: "Arial"
+ pixelSize: parent.height * 0.6
+ }
+ anchors.centerIn: parent
+ }
+ }
+}
diff --git a/ground/openpilotgcs/share/openpilotgcs/pfd/default/srtm.earth b/ground/openpilotgcs/share/openpilotgcs/pfd/default/srtm.earth
new file mode 100644
index 000000000..bd17c7eb0
--- /dev/null
+++ b/ground/openpilotgcs/share/openpilotgcs/pfd/default/srtm.earth
@@ -0,0 +1,26 @@
+
+
+
diff --git a/ground/openpilotgcs/share/openpilotgcs/pfd/default/yahoo_srtm.earth b/ground/openpilotgcs/share/openpilotgcs/pfd/default/yahoo_srtm.earth
new file mode 100644
index 000000000..1033290b5
--- /dev/null
+++ b/ground/openpilotgcs/share/openpilotgcs/pfd/default/yahoo_srtm.earth
@@ -0,0 +1,26 @@
+
+
+
diff --git a/ground/openpilotgcs/src/plugins/coreplugin/OpenPilotGCS.xml b/ground/openpilotgcs/src/plugins/coreplugin/OpenPilotGCS.xml
index d61dba982..ac8ac26cc 100644
--- a/ground/openpilotgcs/src/plugins/coreplugin/OpenPilotGCS.xml
+++ b/ground/openpilotgcs/src/plugins/coreplugin/OpenPilotGCS.xml
@@ -1691,6 +1691,30 @@
+
+
+
+ false
+ 0.0.0
+
+
+ false
+ %%DATAPATH%%pfd/default/Pfd.qml
+ %%DATAPATH%%pfd/default/srtm.earth
+
+
+
+
+ false
+ 0.0.0
+
+
+ true
+ %%DATAPATH%%pfd/default/Pfd.qml
+ %%DATAPATH%%pfd/default/srtm.earth
+
+
+
diff --git a/ground/openpilotgcs/src/plugins/pfdqml/PfdQml.pluginspec b/ground/openpilotgcs/src/plugins/pfdqml/PfdQml.pluginspec
new file mode 100644
index 000000000..563bacefd
--- /dev/null
+++ b/ground/openpilotgcs/src/plugins/pfdqml/PfdQml.pluginspec
@@ -0,0 +1,12 @@
+
+ The OpenPilot Project
+ (C) 2010 Edouard Lafargue
+ (C) 2012 Dmytro Poplavskiy
+ The GNU Public License (GPL) Version 3
+ QML based PFD widget
+ http://www.openpilot.org
+
+
+
+
+
diff --git a/ground/openpilotgcs/src/plugins/pfdqml/osgearth.cpp b/ground/openpilotgcs/src/plugins/pfdqml/osgearth.cpp
new file mode 100644
index 000000000..b4e8ac53e
--- /dev/null
+++ b/ground/openpilotgcs/src/plugins/pfdqml/osgearth.cpp
@@ -0,0 +1,311 @@
+/*
+ * This program 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.
+ *
+ * This program 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 this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include "osgearth.h"
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include
+
+OsgEarthItem::OsgEarthItem(QDeclarativeItem *parent):
+ QDeclarativeItem(parent),
+ m_fbo(0),
+ m_currentSize(640, 480),
+ m_roll(0.0),
+ m_pitch(0.0),
+ m_yaw(0.0),
+ m_latitude(-28.5),
+ m_longitude(153.0),
+ m_altitude(400.0),
+ m_fieldOfView(90.0),
+ m_sceneFile(QLatin1String("/usr/share/osgearth/maps/srtm.earth")),
+ m_cameraDirty(false)
+{
+ setSize(m_currentSize);
+ setFlag(ItemHasNoContents, false);
+}
+
+OsgEarthItem::~OsgEarthItem()
+{
+}
+
+void OsgEarthItem::geometryChanged(const QRectF &newGeometry, const QRectF &oldGeometry)
+{
+ Q_UNUSED(oldGeometry);
+ Q_UNUSED(newGeometry);
+
+ //Dynamic gyometry changes are not supported yet,
+ //terrain is rendered to fixed geompetry and scalled for now
+
+ /*
+ qDebug() << Q_FUNC_INFO << newGeometry;
+
+ int w = qRound(newGeometry.width());
+ int h = qRound(newGeometry.height());
+
+ if (m_currentSize != QSize(w,h) && m_gw.get()) {
+ m_currentSize = QSize(w,h);
+
+ m_gw->getEventQueue()->windowResize(0,0,w,h);
+ m_gw->resized(0,0,w,h);
+
+ osg::Camera *camera = m_viewer->getCamera();
+ camera->setViewport(new osg::Viewport(0,0,w,h));
+ camera->setProjectionMatrixAsPerspective(m_fieldOfView, qreal(w)/h, 1.0f, 10000.0f);
+ }
+ */
+}
+
+void OsgEarthItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *style, QWidget *widget)
+{
+ Q_UNUSED(painter);
+ Q_UNUSED(style);
+ QGLWidget *glWidget = qobject_cast(widget);
+
+ if (!m_glWidget) {
+ //make a shared gl widget to avoid
+ //osg rendering to mess with qpainter state
+ m_glWidget = new QGLWidget(widget, glWidget);
+ m_glWidget.data()->setAttribute(Qt::WA_PaintOutsidePaintEvent);
+ }
+
+ if (!m_viewer.get())
+ QMetaObject::invokeMethod(this, "initScene", Qt::QueuedConnection);
+
+ if (glWidget && m_fbo)
+ glWidget->drawTexture(boundingRect(), m_fbo->texture());
+}
+
+void OsgEarthItem::markCameraDirty()
+{
+ m_cameraDirty = true;
+ QMetaObject::invokeMethod(this, "updateFBO", Qt::QueuedConnection);
+}
+
+void OsgEarthItem::updateFBO()
+{
+ if (!m_cameraDirty || !m_viewer.get() || m_glWidget.isNull())
+ return;
+
+ m_cameraDirty = false;
+ m_glWidget.data()->makeCurrent();
+
+ if (m_fbo && m_fbo->size() != m_currentSize) {
+ delete m_fbo;
+ m_fbo = 0;
+ }
+
+ if (!m_fbo) {
+ m_fbo = new QGLFramebufferObject(m_currentSize, QGLFramebufferObject::CombinedDepthStencil);
+ QPainter p(m_fbo);
+ p.fillRect(0,0,m_currentSize.width(), m_currentSize.height(), Qt::gray);
+ }
+
+ //To find a camera view matrix, find placer matrixes for two points
+ //onr at requested coords and another latitude shifted by 0.01 deg
+ osgEarth::Util::ObjectPlacer placer(m_viewer->getSceneData());
+
+ osg::Matrixd positionMatrix;
+ placer.createPlacerMatrix(m_latitude, m_longitude, m_altitude, positionMatrix);
+ osg::Matrixd positionMatrix2;
+ placer.createPlacerMatrix(m_latitude+0.01, m_longitude, m_altitude, positionMatrix2);
+
+ osg::Vec3d eye(0.0f, 0.0f, 0.0f);
+ osg::Vec3d viewVector(0.0f, 0.0f, 0.0f);
+ osg::Vec3d upVector(0.0f, 0.0f, 1.0f);
+
+ eye = positionMatrix.preMult(eye);
+ upVector = positionMatrix.preMult(upVector);
+ upVector.normalize();
+ viewVector = positionMatrix2.preMult(viewVector) - eye;
+ viewVector.normalize();
+ viewVector *= 10.0;
+
+ //TODO: clarify the correct rotation order,
+ //currently assuming yaw, pitch, roll
+ osg::Quat q;
+ q.makeRotate(-m_yaw*M_PI/180.0, upVector);
+ upVector = q * upVector;
+ viewVector = q * viewVector;
+
+ osg::Vec3d side = viewVector ^ upVector;
+ q.makeRotate(m_pitch*M_PI/180.0, side);
+ upVector = q * upVector;
+ viewVector = q * viewVector;
+
+ q.makeRotate(m_roll*M_PI/180.0, viewVector);
+ upVector = q * upVector;
+ viewVector = q * viewVector;
+
+ osg::Vec3d center = eye + viewVector;
+
+// qDebug() << "e " << eye.x() << eye.y() << eye.z();
+// qDebug() << "c " << center.x() << center.y() << center.z();
+// qDebug() << "up" << upVector.x() << upVector.y() << upVector.z();
+
+ m_viewer->getCamera()->setViewMatrixAsLookAt(osg::Vec3d(eye.x(), eye.y(), eye.z()),
+ osg::Vec3d(center.x(), center.y(), center.z()),
+ osg::Vec3d(upVector.x(), upVector.y(), upVector.z()));
+
+ {
+ QPainter fboPainter(m_fbo);
+ fboPainter.beginNativePainting();
+ m_viewer->frame();
+ fboPainter.endNativePainting();
+ }
+ m_glWidget.data()->doneCurrent();
+
+ update();
+}
+
+void OsgEarthItem::setRoll(qreal arg)
+{
+ if (!qFuzzyCompare(m_roll, arg)) {
+ m_roll = arg;
+ markCameraDirty();
+ emit rollChanged(arg);
+ }
+}
+
+void OsgEarthItem::setPitch(qreal arg)
+{
+ if (!qFuzzyCompare(m_pitch, arg)) {
+ m_pitch = arg;
+ markCameraDirty();
+ emit pitchChanged(arg);
+ }
+}
+
+void OsgEarthItem::setYaw(qreal arg)
+{
+ if (!qFuzzyCompare(m_yaw, arg)) {
+ m_yaw = arg;
+ markCameraDirty();
+ emit yawChanged(arg);
+ }
+}
+
+void OsgEarthItem::setLatitude(double arg)
+{
+ //not sure qFuzzyCompare is accurate enough for geo coordinates
+ if (m_latitude != arg) {
+ m_latitude = arg;
+ emit latitudeChanged(arg);
+ }
+}
+
+void OsgEarthItem::setLongitude(double arg)
+{
+ if (m_longitude != arg) {
+ m_longitude = arg;
+ emit longitudeChanged(arg);
+ }
+}
+
+void OsgEarthItem::setAltitude(double arg)
+{
+ if (!qFuzzyCompare(m_altitude,arg)) {
+ m_altitude = arg;
+ emit altitudeChanged(arg);
+ }
+}
+
+//! Camera vertical field of view in degrees
+void OsgEarthItem::setFieldOfView(qreal arg)
+{
+ if (!qFuzzyCompare(m_fieldOfView,arg)) {
+ m_fieldOfView = arg;
+ emit fieldOfViewChanged(arg);
+
+ if (m_viewer.get()) {
+ m_viewer->getCamera()->setProjectionMatrixAsPerspective(
+ m_fieldOfView,
+ qreal(m_currentSize.width())/m_currentSize.height(),
+ 1.0f, 10000.0f);
+ }
+
+ markCameraDirty();
+ }
+}
+
+void OsgEarthItem::setSceneFile(QString arg)
+{
+ if (m_sceneFile != arg) {
+ m_sceneFile = arg;
+ emit sceneFileChanged(arg);
+ }
+}
+
+
+void OsgEarthItem::initScene()
+{
+ if (m_viewer.get())
+ return;
+
+ int w = m_currentSize.width();
+ int h = m_currentSize.height();
+
+ QString sceneFile = m_sceneFile;
+
+ //try to resolve the relative scene file name:
+ if (!QFileInfo(sceneFile).exists()) {
+ QDeclarativeView *view = qobject_cast(scene()->views().first());
+
+ if (view) {
+ QUrl baseUrl = view->engine()->baseUrl();
+ sceneFile = baseUrl.resolved(sceneFile).toLocalFile();
+ }
+ }
+
+ m_model = osgDB::readNodeFile(sceneFile.toStdString());
+
+ m_gw = new osgViewer::GraphicsWindowEmbedded(0,0,w,h);
+
+ m_viewer = new osgViewer::Viewer();
+ m_viewer->setThreadingModel(osgViewer::Viewer::SingleThreaded);
+ m_viewer->setSceneData(m_model);
+ m_viewer->getDatabasePager()->setDoPreCompile(true);
+
+ osg::Camera *camera = m_viewer->getCamera();
+ camera->setViewport(new osg::Viewport(0,0,w,h));
+ camera->setGraphicsContext(m_gw);
+ camera->setClearMask(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
+
+ // configure the near/far so we don't clip things that are up close
+ camera->setNearFarRatio(0.00002);
+ camera->setProjectionMatrixAsPerspective(m_fieldOfView, qreal(w)/h, 1.0f, 10000.0f);
+
+ markCameraDirty();
+}
+
diff --git a/ground/openpilotgcs/src/plugins/pfdqml/osgearth.h b/ground/openpilotgcs/src/plugins/pfdqml/osgearth.h
new file mode 100644
index 000000000..6a1095a07
--- /dev/null
+++ b/ground/openpilotgcs/src/plugins/pfdqml/osgearth.h
@@ -0,0 +1,117 @@
+/*
+ * This program 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.
+ *
+ * This program 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 this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef OSGEARTH_H
+#define OSGEARTH_H
+
+#include
+
+#include
+#include
+
+class QGLFramebufferObject;
+class QGLWidget;
+
+class OsgEarthItem : public QDeclarativeItem
+{
+ Q_OBJECT
+ Q_DISABLE_COPY(OsgEarthItem)
+
+ Q_PROPERTY(QString sceneFile READ sceneFile WRITE setSceneFile NOTIFY sceneFileChanged)
+ Q_PROPERTY(qreal fieldOfView READ fieldOfView WRITE setFieldOfView NOTIFY fieldOfViewChanged)
+
+ Q_PROPERTY(qreal roll READ roll WRITE setRoll NOTIFY rollChanged)
+ Q_PROPERTY(qreal pitch READ pitch WRITE setPitch NOTIFY pitchChanged)
+ Q_PROPERTY(qreal yaw READ yaw WRITE setYaw NOTIFY yawChanged)
+
+ Q_PROPERTY(double latitude READ latitude WRITE setLatitude NOTIFY latitudeChanged)
+ Q_PROPERTY(double longitude READ longitude WRITE setLongitude NOTIFY longitudeChanged)
+ Q_PROPERTY(double altitude READ altitude WRITE setAltitude NOTIFY altitudeChanged)
+
+public:
+ OsgEarthItem(QDeclarativeItem *parent = 0);
+ ~OsgEarthItem();
+
+ QString sceneFile() const { return m_sceneFile; }
+ qreal fieldOfView() const { return m_fieldOfView; }
+
+ qreal roll() const { return m_roll; }
+ qreal pitch() const { return m_pitch; }
+ qreal yaw() const { return m_yaw; }
+
+ double latitude() const { return m_latitude; }
+ double longitude() const { return m_longitude; }
+ double altitude() const { return m_altitude; }
+
+protected:
+ void geometryChanged(const QRectF &newGeometry, const QRectF &oldGeometry);
+ void paint(QPainter *painter, const QStyleOptionGraphicsItem *style, QWidget *widget);
+
+public slots:
+ void setSceneFile(QString arg);
+ void setFieldOfView(qreal arg);
+
+ void setRoll(qreal arg);
+ void setPitch(qreal arg);
+ void setYaw(qreal arg);
+
+ void setLatitude(double arg);
+ void setLongitude(double arg);
+ void setAltitude(double arg);
+
+signals:
+ void rollChanged(qreal arg);
+ void pitchChanged(qreal arg);
+ void yawChanged(qreal arg);
+
+ void latitudeChanged(double arg);
+ void longitudeChanged(double arg);
+ void altitudeChanged(double arg);
+
+ void sceneFileChanged(QString arg);
+ void fieldOfViewChanged(qreal arg);
+
+private slots:
+ void markCameraDirty();
+ void updateFBO();
+ void initScene();
+
+private:
+ osg::ref_ptr m_viewer;
+ osg::ref_ptr m_gw;
+ osg::ref_ptr m_model;
+ QWeakPointer m_glWidget;
+ QGLFramebufferObject *m_fbo;
+ QSize m_currentSize;
+
+ qreal m_roll;
+ qreal m_pitch;
+ qreal m_yaw;
+
+ double m_latitude;
+ double m_longitude;
+ double m_altitude;
+
+ qreal m_fieldOfView;
+ QString m_sceneFile;
+
+ bool m_cameraDirty;
+};
+
+QML_DECLARE_TYPE(OsgEarthItem)
+
+#endif // OSGEARTH_H
+
diff --git a/ground/openpilotgcs/src/plugins/pfdqml/pfdqml.pro b/ground/openpilotgcs/src/plugins/pfdqml/pfdqml.pro
new file mode 100644
index 000000000..7064f8a0c
--- /dev/null
+++ b/ground/openpilotgcs/src/plugins/pfdqml/pfdqml.pro
@@ -0,0 +1,35 @@
+TEMPLATE = lib
+TARGET = PfdQml
+QT += svg
+QT += opengl
+QT += declarative
+
+include(../../openpilotgcsplugin.pri)
+include(../../plugins/coreplugin/coreplugin.pri)
+include(pfdqml_dependencies.pri)
+
+LIBS += -losg -losgUtil -losgViewer -losgQt -losgDB -lOpenThreads -losgGA
+LIBS += -losgEarth -losgEarthFeatures -losgEarthUtil
+
+HEADERS += \
+ pfdqmlplugin.h \
+ pfdqmlgadget.h \
+ pfdqmlgadgetwidget.h \
+ pfdqmlgadgetfactory.h \
+ pfdqmlgadgetconfiguration.h \
+ pfdqmlgadgetoptionspage.h \
+ osgearth.h
+
+SOURCES += \
+ pfdqmlplugin.cpp \
+ pfdqmlgadget.cpp \
+ pfdqmlgadgetfactory.cpp \
+ pfdqmlgadgetwidget.cpp \
+ pfdqmlgadgetconfiguration.cpp \
+ pfdqmlgadgetoptionspage.cpp \
+ osgearth.cpp
+
+OTHER_FILES += PfdQml.pluginspec
+
+FORMS += pfdqmlgadgetoptionspage.ui
+
diff --git a/ground/openpilotgcs/src/plugins/pfdqml/pfdqml_dependencies.pri b/ground/openpilotgcs/src/plugins/pfdqml/pfdqml_dependencies.pri
new file mode 100644
index 000000000..9aae5fbc0
--- /dev/null
+++ b/ground/openpilotgcs/src/plugins/pfdqml/pfdqml_dependencies.pri
@@ -0,0 +1 @@
+include(../../plugins/uavobjects/uavobjects.pri)
diff --git a/ground/openpilotgcs/src/plugins/pfdqml/pfdqmlgadget.cpp b/ground/openpilotgcs/src/plugins/pfdqml/pfdqmlgadget.cpp
new file mode 100644
index 000000000..48661a581
--- /dev/null
+++ b/ground/openpilotgcs/src/plugins/pfdqml/pfdqmlgadget.cpp
@@ -0,0 +1,44 @@
+/*
+ * This program 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.
+ *
+ * This program 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 this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include "pfdqmlgadget.h"
+#include "pfdqmlgadgetwidget.h"
+#include "pfdqmlgadgetconfiguration.h"
+
+PfdQmlGadget::PfdQmlGadget(QString classId, PfdQmlGadgetWidget *widget, QWidget *parent) :
+ IUAVGadget(classId, parent),
+ m_widget(widget)
+{
+}
+
+PfdQmlGadget::~PfdQmlGadget()
+{
+ delete m_widget;
+}
+
+/*
+ This is called when a configuration is loaded, and updates the plugin's settings.
+ Careful: the plugin is already drawn before the loadConfiguration method is called the
+ first time, so you have to be careful not to assume all the plugin values are initialized
+ the first time you use them
+ */
+void PfdQmlGadget::loadConfiguration(IUAVGadgetConfiguration* config)
+{
+ PfdQmlGadgetConfiguration *m = qobject_cast(config);
+ m_widget->setQmlFile(m->qmlFile());
+ m_widget->setEarthFile(m->earthFile());
+ m_widget->setTerrainEnabled(m->terrainEnabled());
+}
diff --git a/ground/openpilotgcs/src/plugins/pfdqml/pfdqmlgadget.h b/ground/openpilotgcs/src/plugins/pfdqml/pfdqmlgadget.h
new file mode 100644
index 000000000..073e1f326
--- /dev/null
+++ b/ground/openpilotgcs/src/plugins/pfdqml/pfdqmlgadget.h
@@ -0,0 +1,45 @@
+/*
+ * This program 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.
+ *
+ * This program 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 this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef PFDQMLGADGET_H_
+#define PFDQMLQMLGADGET_H_
+
+#include
+#include "pfdqmlgadgetwidget.h"
+
+class IUAVGadget;
+class QWidget;
+class QString;
+class PfdQmlGadgetWidget;
+
+using namespace Core;
+
+class PfdQmlGadget : public Core::IUAVGadget
+{
+ Q_OBJECT
+public:
+ PfdQmlGadget(QString classId, PfdQmlGadgetWidget *widget, QWidget *parent = 0);
+ ~PfdQmlGadget();
+
+ QWidget *widget() { return m_widget; }
+ void loadConfiguration(IUAVGadgetConfiguration* config);
+
+private:
+ PfdQmlGadgetWidget *m_widget;
+};
+
+
+#endif // PFDQMLQMLGADGET_H_
diff --git a/ground/openpilotgcs/src/plugins/pfdqml/pfdqmlgadgetconfiguration.cpp b/ground/openpilotgcs/src/plugins/pfdqml/pfdqmlgadgetconfiguration.cpp
new file mode 100644
index 000000000..56926917e
--- /dev/null
+++ b/ground/openpilotgcs/src/plugins/pfdqml/pfdqmlgadgetconfiguration.cpp
@@ -0,0 +1,67 @@
+/*
+ * This program 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.
+ *
+ * This program 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 this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include "pfdqmlgadgetconfiguration.h"
+#include "utils/pathutils.h"
+
+/**
+ * Loads a saved configuration or defaults if non exist.
+ *
+ */
+PfdQmlGadgetConfiguration::PfdQmlGadgetConfiguration(QString classId, QSettings *qSettings, QObject *parent) :
+ IUAVGadgetConfiguration(classId, parent),
+ m_qmlFile("Unknown"),
+ m_earthFile("Unknown"),
+ m_terrainEnabled(true)
+{
+ //if a saved configuration exists load it
+ if(qSettings != 0) {
+ m_qmlFile = qSettings->value("qmlFile").toString();
+ m_qmlFile=Utils::PathUtils().InsertDataPath(m_qmlFile);
+
+ m_earthFile = qSettings->value("earthFile").toString();
+ m_earthFile=Utils::PathUtils().InsertDataPath(m_earthFile);
+
+ m_terrainEnabled = qSettings->value("terrainEnabled").toBool();
+ }
+}
+
+/**
+ * Clones a configuration.
+ *
+ */
+IUAVGadgetConfiguration *PfdQmlGadgetConfiguration::clone()
+{
+ PfdQmlGadgetConfiguration *m = new PfdQmlGadgetConfiguration(this->classId());
+ m->m_qmlFile = m_qmlFile;
+ m->m_earthFile = m_earthFile;
+ m->m_terrainEnabled = m_terrainEnabled;
+
+ return m;
+}
+
+/**
+ * Saves a configuration.
+ *
+ */
+void PfdQmlGadgetConfiguration::saveConfig(QSettings* qSettings) const {
+ QString qmlFile = Utils::PathUtils().RemoveDataPath(m_qmlFile);
+ qSettings->setValue("qmlFile", qmlFile);
+ QString earthFile = Utils::PathUtils().RemoveDataPath(m_earthFile);
+ qSettings->setValue("earthFile", earthFile);
+
+ qSettings->setValue("terrainEnabled", m_terrainEnabled);
+}
diff --git a/ground/openpilotgcs/src/plugins/pfdqml/pfdqmlgadgetconfiguration.h b/ground/openpilotgcs/src/plugins/pfdqml/pfdqmlgadgetconfiguration.h
new file mode 100644
index 000000000..c9986173b
--- /dev/null
+++ b/ground/openpilotgcs/src/plugins/pfdqml/pfdqmlgadgetconfiguration.h
@@ -0,0 +1,48 @@
+/*
+ * This program 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.
+ *
+ * This program 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 this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef PFDQMLGADGETCONFIGURATION_H
+#define PFDQMLGADGETCONFIGURATION_H
+
+#include
+
+using namespace Core;
+
+class PfdQmlGadgetConfiguration : public IUAVGadgetConfiguration
+{
+Q_OBJECT
+public:
+ explicit PfdQmlGadgetConfiguration(QString classId, QSettings* qSettings = 0, QObject *parent = 0);
+
+ void setQmlFile(const QString &fileName) { m_qmlFile=fileName; }
+ void setEarthFile(const QString &fileName) { m_earthFile=fileName; }
+ void setTerrainEnabled(bool flag) { m_terrainEnabled = flag; }
+
+ //get dial configuration functions
+ QString qmlFile() const { return m_qmlFile; }
+ QString earthFile() const { return m_earthFile; }
+ bool terrainEnabled() const { return m_terrainEnabled; }
+
+ void saveConfig(QSettings* settings) const;
+ IUAVGadgetConfiguration *clone();
+
+private:
+ QString m_qmlFile; // The name of the dial's SVG source file
+ QString m_earthFile; // The name of osgearth terrain file
+ bool m_terrainEnabled;
+};
+
+#endif // PfdQmlGADGETCONFIGURATION_H
diff --git a/ground/openpilotgcs/src/plugins/pfdqml/pfdqmlgadgetfactory.cpp b/ground/openpilotgcs/src/plugins/pfdqml/pfdqmlgadgetfactory.cpp
new file mode 100644
index 000000000..9616c4796
--- /dev/null
+++ b/ground/openpilotgcs/src/plugins/pfdqml/pfdqmlgadgetfactory.cpp
@@ -0,0 +1,49 @@
+/*
+ * This program 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.
+ *
+ * This program 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 this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+#include "pfdqmlgadgetfactory.h"
+#include "pfdqmlgadgetwidget.h"
+#include "pfdqmlgadget.h"
+#include "pfdqmlgadgetconfiguration.h"
+#include "pfdqmlgadgetoptionspage.h"
+#include
+
+PfdQmlGadgetFactory::PfdQmlGadgetFactory(QObject *parent) :
+ IUAVGadgetFactory(QString("PfdQmlGadget"),
+ tr("PFD (qml)"),
+ parent)
+{
+}
+
+PfdQmlGadgetFactory::~PfdQmlGadgetFactory()
+{
+}
+
+Core::IUAVGadget* PfdQmlGadgetFactory::createGadget(QWidget *parent)
+{
+ PfdQmlGadgetWidget* gadgetWidget = new PfdQmlGadgetWidget(parent);
+ return new PfdQmlGadget(QString("PfdQmlGadget"), gadgetWidget, parent);
+}
+
+IUAVGadgetConfiguration *PfdQmlGadgetFactory::createConfiguration(QSettings *qSettings)
+{
+ return new PfdQmlGadgetConfiguration(QString("PfdQmlGadget"), qSettings);
+}
+
+IOptionsPage *PfdQmlGadgetFactory::createOptionsPage(IUAVGadgetConfiguration *config)
+{
+ return new PfdQmlGadgetOptionsPage(qobject_cast(config));
+}
+
diff --git a/ground/openpilotgcs/src/plugins/pfdqml/pfdqmlgadgetfactory.h b/ground/openpilotgcs/src/plugins/pfdqml/pfdqmlgadgetfactory.h
new file mode 100644
index 000000000..950124010
--- /dev/null
+++ b/ground/openpilotgcs/src/plugins/pfdqml/pfdqmlgadgetfactory.h
@@ -0,0 +1,41 @@
+/*
+ * This program 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.
+ *
+ * This program 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 this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef PFDQMLGADGETFACTORY_H_
+#define PFDQMLGADGETFACTORY_H_
+
+#include
+
+namespace Core {
+class IUAVGadget;
+class IUAVGadgetFactory;
+}
+
+using namespace Core;
+
+class PfdQmlGadgetFactory : public IUAVGadgetFactory
+{
+ Q_OBJECT
+public:
+ PfdQmlGadgetFactory(QObject *parent = 0);
+ ~PfdQmlGadgetFactory();
+
+ Core::IUAVGadget *createGadget(QWidget *parent);
+ IUAVGadgetConfiguration *createConfiguration(QSettings *qSettings);
+ IOptionsPage *createOptionsPage(IUAVGadgetConfiguration *config);
+};
+
+#endif // PfdQmlGADGETFACTORY_H_
diff --git a/ground/openpilotgcs/src/plugins/pfdqml/pfdqmlgadgetoptionspage.cpp b/ground/openpilotgcs/src/plugins/pfdqml/pfdqmlgadgetoptionspage.cpp
new file mode 100644
index 000000000..01ee89c96
--- /dev/null
+++ b/ground/openpilotgcs/src/plugins/pfdqml/pfdqmlgadgetoptionspage.cpp
@@ -0,0 +1,77 @@
+/*
+ * This program 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.
+ *
+ * This program 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 this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include "pfdqmlgadgetoptionspage.h"
+#include "pfdqmlgadgetconfiguration.h"
+#include "ui_pfdqmlgadgetoptionspage.h"
+#include "extensionsystem/pluginmanager.h"
+#include "uavobjectmanager.h"
+#include "uavdataobject.h"
+
+
+#include
+#include
+#include
+
+PfdQmlGadgetOptionsPage::PfdQmlGadgetOptionsPage(PfdQmlGadgetConfiguration *config, QObject *parent) :
+ IOptionsPage(parent),
+ m_config(config)
+{
+}
+
+//creates options page widget (uses the UI file)
+QWidget *PfdQmlGadgetOptionsPage::createPage(QWidget *parent)
+{
+
+ options_page = new Ui::PfdQmlGadgetOptionsPage();
+ //main widget
+ QWidget *optionsPageWidget = new QWidget;
+ //main layout
+ options_page->setupUi(optionsPageWidget);
+
+ // Restore the contents from the settings:
+ options_page->qmlSourceFile->setExpectedKind(Utils::PathChooser::File);
+ options_page->qmlSourceFile->setPromptDialogFilter(tr("QML file (*.qml)"));
+ options_page->qmlSourceFile->setPromptDialogTitle(tr("Choose QML file"));
+ options_page->qmlSourceFile->setPath(m_config->qmlFile());
+
+ // Restore the contents from the settings:
+ options_page->earthFile->setExpectedKind(Utils::PathChooser::File);
+ options_page->earthFile->setPromptDialogFilter(tr("OsgEarth (*.earth)"));
+ options_page->earthFile->setPromptDialogTitle(tr("Choose OsgEarth terrain file"));
+ options_page->earthFile->setPath(m_config->earthFile());
+
+ options_page->showTerrain->setChecked(m_config->terrainEnabled());
+
+ return optionsPageWidget;
+}
+
+/**
+ * Called when the user presses apply or OK.
+ *
+ * Saves the current values
+ *
+ */
+void PfdQmlGadgetOptionsPage::apply()
+{
+ m_config->setQmlFile(options_page->qmlSourceFile->path());
+ m_config->setEarthFile(options_page->earthFile->path());
+ m_config->setTerrainEnabled(options_page->showTerrain->isChecked());
+}
+
+void PfdQmlGadgetOptionsPage::finish()
+{
+}
diff --git a/ground/openpilotgcs/src/plugins/pfdqml/pfdqmlgadgetoptionspage.h b/ground/openpilotgcs/src/plugins/pfdqml/pfdqmlgadgetoptionspage.h
new file mode 100644
index 000000000..8797275a6
--- /dev/null
+++ b/ground/openpilotgcs/src/plugins/pfdqml/pfdqmlgadgetoptionspage.h
@@ -0,0 +1,54 @@
+/*
+ * This program 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.
+ *
+ * This program 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 this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef PFDQMLGADGETOPTIONSPAGE_H
+#define PFDQMLGADGETOPTIONSPAGE_H
+
+#include "coreplugin/dialogs/ioptionspage.h"
+#include "QString"
+#include
+#include
+
+namespace Core {
+class IUAVGadgetConfiguration;
+}
+
+class PfdQmlGadgetConfiguration;
+
+namespace Ui {
+ class PfdQmlGadgetOptionsPage;
+}
+
+using namespace Core;
+
+class PfdQmlGadgetOptionsPage : public IOptionsPage
+{
+Q_OBJECT
+public:
+ explicit PfdQmlGadgetOptionsPage(PfdQmlGadgetConfiguration *config, QObject *parent = 0);
+
+ QWidget *createPage(QWidget *parent);
+ void apply();
+ void finish();
+
+private:
+ Ui::PfdQmlGadgetOptionsPage *options_page;
+ PfdQmlGadgetConfiguration *m_config;
+
+private slots:
+};
+
+#endif // PfdQmlGADGETOPTIONSPAGE_H
diff --git a/ground/openpilotgcs/src/plugins/pfdqml/pfdqmlgadgetoptionspage.ui b/ground/openpilotgcs/src/plugins/pfdqml/pfdqmlgadgetoptionspage.ui
new file mode 100644
index 000000000..dd8d03e4f
--- /dev/null
+++ b/ground/openpilotgcs/src/plugins/pfdqml/pfdqmlgadgetoptionspage.ui
@@ -0,0 +1,135 @@
+
+
+ PfdQmlGadgetOptionsPage
+
+
+
+ 0
+ 0
+ 441
+ 339
+
+
+
+
+ 0
+ 0
+
+
+
+ Form
+
+
+ -
+
+
+ 10
+
+
+ QLayout::SetMaximumSize
+
+
+ 10
+
+
-
+
+
+ QML file:
+
+
+
+ -
+
+
+
+ 0
+ 0
+
+
+
+
+
+
+ -
+
+
+ Qt::Horizontal
+
+
+
+ -
+
+
-
+
+
+ true
+
+
+ Show terrain
+
+
+ true
+
+
+
+
+
+ -
+
+
+ 10
+
+
+ QLayout::SetMaximumSize
+
+
+ 10
+
+
-
+
+
+ OsgEarth file:
+
+
+
+ -
+
+
+
+ 0
+ 0
+
+
+
+
+
+
+ -
+
+
+ Qt::Vertical
+
+
+ QSizePolicy::MinimumExpanding
+
+
+
+ 20
+ 40
+
+
+
+
+
+
+
+
+ Utils::PathChooser
+ QWidget
+
+ 1
+
+
+
+
+
diff --git a/ground/openpilotgcs/src/plugins/pfdqml/pfdqmlgadgetwidget.cpp b/ground/openpilotgcs/src/plugins/pfdqml/pfdqmlgadgetwidget.cpp
new file mode 100644
index 000000000..ac2d7ada2
--- /dev/null
+++ b/ground/openpilotgcs/src/plugins/pfdqml/pfdqmlgadgetwidget.cpp
@@ -0,0 +1,106 @@
+/*
+ * This program 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.
+ *
+ * This program 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 this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include "pfdqmlgadgetwidget.h"
+#include "extensionsystem/pluginmanager.h"
+#include "uavobjectmanager.h"
+#include "uavobject.h"
+#include "utils/svgimageprovider.h"
+#include "osgearth.h"
+
+#include
+#include
+#include
+#include
+#include
+
+#include
+#include
+#include
+
+PfdQmlGadgetWidget::PfdQmlGadgetWidget(QWidget *parent) :
+ QDeclarativeView(parent)
+{
+ setMinimumSize(64,64);
+ setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::MinimumExpanding);
+ setResizeMode(SizeRootObjectToView);
+
+ setViewport(new QGLWidget(QGLFormat(QGL::SampleBuffers)));
+
+ QStringList objectsToExport;
+ objectsToExport << "VelocityActual" <<
+ "PositionActual" <<
+ "AttitudeActual" <<
+ "GPSPosition" <<
+ "GCSTelemetryStats" <<
+ "FlightBatteryState";
+
+ ExtensionSystem::PluginManager *pm = ExtensionSystem::PluginManager::instance();
+ UAVObjectManager *objManager = pm->getObject();
+
+ foreach (const QString &objectName, objectsToExport) {
+ UAVObject* object = objManager->getObject(objectName);
+ if (object)
+ engine()->rootContext()->setContextProperty(objectName, object);
+ else
+ qWarning() << "Failed to load object" << objectName;
+ }
+
+ //to expose settings values
+ engine()->rootContext()->setContextProperty("qmlWidget", this);
+
+ qmlRegisterType("org.OpenPilot", 1, 0, "OsgEarth");
+}
+
+PfdQmlGadgetWidget::~PfdQmlGadgetWidget()
+{
+}
+
+void PfdQmlGadgetWidget::setQmlFile(QString fn)
+{
+ m_qmlFileName = fn;
+
+ engine()->removeImageProvider("svg");
+ SvgImageProvider *svgProvider = new SvgImageProvider(fn);
+ engine()->addImageProvider("svg", svgProvider);
+
+ //it's necessary to allow qml side to query svg element position
+ engine()->rootContext()->setContextProperty("svgRenderer", svgProvider);
+ engine()->setBaseUrl(QUrl::fromLocalFile(fn));
+
+ qDebug() << Q_FUNC_INFO << fn;
+ setSource(QUrl::fromLocalFile(fn));
+
+ foreach(const QDeclarativeError &error, errors()) {
+ qDebug() << error.description();
+ }
+}
+
+void PfdQmlGadgetWidget::setEarthFile(QString arg)
+{
+ if (m_earthFile != arg) {
+ m_earthFile = arg;
+ emit earthFileChanged(arg);
+ }
+}
+
+void PfdQmlGadgetWidget::setTerrainEnabled(bool arg)
+{
+ if (m_terrainEnabled != arg) {
+ m_terrainEnabled = arg;
+ emit terrainEnabledChanged(arg);
+ }
+}
diff --git a/ground/openpilotgcs/src/plugins/pfdqml/pfdqmlgadgetwidget.h b/ground/openpilotgcs/src/plugins/pfdqml/pfdqmlgadgetwidget.h
new file mode 100644
index 000000000..6e0f8b35f
--- /dev/null
+++ b/ground/openpilotgcs/src/plugins/pfdqml/pfdqmlgadgetwidget.h
@@ -0,0 +1,51 @@
+/*
+ * This program 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.
+ *
+ * This program 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 this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef PFDQMLGADGETWIDGET_H_
+#define PFDQMLGADGETWIDGET_H_
+
+#include "pfdqmlgadgetconfiguration.h"
+#include
+
+class PfdQmlGadgetWidget : public QDeclarativeView
+{
+ Q_OBJECT
+ Q_PROPERTY(QString earthFile READ earthFile WRITE setEarthFile NOTIFY earthFileChanged)
+ Q_PROPERTY(bool terrainEnabled READ terrainEnabled WRITE setTerrainEnabled NOTIFY terrainEnabledChanged)
+
+public:
+ PfdQmlGadgetWidget(QWidget *parent = 0);
+ ~PfdQmlGadgetWidget();
+ void setQmlFile(QString fn);
+
+ QString earthFile() const { return m_earthFile; }
+ bool terrainEnabled() const { return m_terrainEnabled; }
+
+public slots:
+ void setEarthFile(QString arg);
+ void setTerrainEnabled(bool arg);
+
+signals:
+ void earthFileChanged(QString arg);
+ void terrainEnabledChanged(bool arg);
+
+private:
+ QString m_qmlFileName;
+ QString m_earthFile;
+ bool m_terrainEnabled;
+};
+
+#endif /* PFDQMLGADGETWIDGET_H_ */
diff --git a/ground/openpilotgcs/src/plugins/pfdqml/pfdqmlplugin.cpp b/ground/openpilotgcs/src/plugins/pfdqml/pfdqmlplugin.cpp
new file mode 100644
index 000000000..f7d40a24d
--- /dev/null
+++ b/ground/openpilotgcs/src/plugins/pfdqml/pfdqmlplugin.cpp
@@ -0,0 +1,55 @@
+/*
+ * This program 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.
+ *
+ * This program 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 this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include "pfdqmlplugin.h"
+#include "pfdqmlgadgetfactory.h"
+#include
+#include
+#include
+#include
+
+
+PfdQmlPlugin::PfdQmlPlugin()
+{
+ // Do nothing
+}
+
+PfdQmlPlugin::~PfdQmlPlugin()
+{
+ // Do nothing
+}
+
+bool PfdQmlPlugin::initialize(const QStringList& args, QString *errMsg)
+{
+ Q_UNUSED(args);
+ Q_UNUSED(errMsg);
+ mf = new PfdQmlGadgetFactory(this);
+ addAutoReleasedObject(mf);
+
+ return true;
+}
+
+void PfdQmlPlugin::extensionsInitialized()
+{
+ // Do nothing
+}
+
+void PfdQmlPlugin::shutdown()
+{
+ // Do nothing
+}
+Q_EXPORT_PLUGIN(PfdQmlPlugin)
+
diff --git a/ground/openpilotgcs/src/plugins/pfdqml/pfdqmlplugin.h b/ground/openpilotgcs/src/plugins/pfdqml/pfdqmlplugin.h
new file mode 100644
index 000000000..e1ef1a122
--- /dev/null
+++ b/ground/openpilotgcs/src/plugins/pfdqml/pfdqmlplugin.h
@@ -0,0 +1,36 @@
+/*
+ * This program 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.
+ *
+ * This program 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 this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef PFDQMLPLUGIN_H_
+#define PFDQMLPLUGIN_H_
+
+#include
+
+class PfdQmlGadgetFactory;
+
+class PfdQmlPlugin : public ExtensionSystem::IPlugin
+{
+public:
+ PfdQmlPlugin();
+ ~PfdQmlPlugin();
+
+ void extensionsInitialized();
+ bool initialize(const QStringList &arguments, QString *errorString);
+ void shutdown();
+private:
+ PfdQmlGadgetFactory *mf;
+};
+#endif /* PFDQMLPLUGIN_H_ */
diff --git a/ground/openpilotgcs/src/plugins/plugins.pro b/ground/openpilotgcs/src/plugins/plugins.pro
index 154335e3a..63fd4c297 100644
--- a/ground/openpilotgcs/src/plugins/plugins.pro
+++ b/ground/openpilotgcs/src/plugins/plugins.pro
@@ -128,12 +128,17 @@ plugin_pfd.depends = plugin_coreplugin
plugin_pfd.depends += plugin_uavobjects
SUBDIRS += plugin_pfd
-# Primary Flight Display (PFD) gadget
+# QML viewer gadget
plugin_qmlview.subdir = qmlview
plugin_qmlview.depends = plugin_coreplugin
plugin_qmlview.depends += plugin_uavobjects
SUBDIRS += plugin_qmlview
+# Primary Flight Display (PFD) gadget, QML version
+plugin_pfdqml.subdir = pfdqml
+plugin_pfdqml.depends = plugin_coreplugin
+plugin_pfdqml.depends += plugin_uavobjects
+SUBDIRS += plugin_pfdqml
#IP connection plugin
plugin_ipconnection.subdir = ipconnection