diff options
-rw-r--r-- | .gitignore | 1 | ||||
-rw-r--r-- | examples/location/location.pro | 3 | ||||
-rw-r--r-- | examples/location/planespotter/Plane.qml | 115 | ||||
-rw-r--r-- | examples/location/planespotter/airplane.png | bin | 0 -> 831 bytes | |||
-rw-r--r-- | examples/location/planespotter/main.cpp | 201 | ||||
-rw-r--r-- | examples/location/planespotter/planespotter.pro | 10 | ||||
-rw-r--r-- | examples/location/planespotter/planespotter.qml | 226 | ||||
-rw-r--r-- | examples/location/planespotter/qml.qrc | 7 | ||||
-rw-r--r-- | src/location/doc/images/planespotter.jpg | bin | 0 -> 116116 bytes | |||
-rw-r--r-- | src/location/doc/src/examples/planespotter.qdoc | 169 |
10 files changed, 731 insertions, 1 deletions
@@ -46,6 +46,7 @@ src/location/doc/snippets/cpp/cppsnippet src/location/doc/snippets/places/placescppsnippet examples/location/places_list/places_list examples/location/places_map/places_map +examples/location/planespotter/planespotter examples/positioning/geoflickr/geoflickr examples/positioning/logfilepositionsource/logfilepositionsource examples/positioning/satelliteinfo/satelliteinfo diff --git a/examples/location/location.pro b/examples/location/location.pro index 816d739d..851e37ac 100644 --- a/examples/location/location.pro +++ b/examples/location/location.pro @@ -4,5 +4,6 @@ qtHaveModule(quick) { SUBDIRS += places \ places_list \ places_map \ - mapviewer + mapviewer \ + planespotter } diff --git a/examples/location/planespotter/Plane.qml b/examples/location/planespotter/Plane.qml new file mode 100644 index 00000000..8037f153 --- /dev/null +++ b/examples/location/planespotter/Plane.qml @@ -0,0 +1,115 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of The Qt Company Ltd nor the names of its +** contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQuick 2.4 +import QtLocation 5.5 + +//! [PlaneMapQuick1] +// Plane.qml +MapQuickItem { + id: plane + property string pilotName; + property int bearing: 0; + + anchorPoint.x: image.width/2 + anchorPoint.y: image.height/2 + + sourceItem: Grid { + //... +//! [PlaneMapQuick1] + columns: 1 + Grid { + horizontalItemAlignment: Grid.AlignHCenter + Image { + id: image + rotation: bearing + source: "airplane.png" + } + Rectangle { + id: bubble + color: "lightblue" + border.width: 1 + width: text.width * 1.3 + height: text.height * 1.3 + radius: 5 + Text { + id: text + anchors.centerIn: parent + text: pilotName + } + } + } + + Rectangle { + id: message + color: "lightblue" + border.width: 1 + width: banner.width * 1.3 + height: banner.height * 1.3 + radius: 5 + opacity: 0 + Text { + id: banner + anchors.centerIn: parent + } + SequentialAnimation { + id: playMessage + running: false + NumberAnimation { target: message; + property: "opacity"; + to: 1.0; + duration: 200 + easing.type: Easing.InOutQuad + } + PauseAnimation { duration: 1000 } + NumberAnimation { target: message; + property: "opacity"; + to: 0.0; + duration: 200} + } + } + } + function showMessage(message) { + banner.text = message + playMessage.start() +//! [PlaneMapQuick2] + } +} +//! [PlaneMapQuick2] diff --git a/examples/location/planespotter/airplane.png b/examples/location/planespotter/airplane.png Binary files differnew file mode 100644 index 00000000..080460dd --- /dev/null +++ b/examples/location/planespotter/airplane.png diff --git a/examples/location/planespotter/main.cpp b/examples/location/planespotter/main.cpp new file mode 100644 index 00000000..c71a6999 --- /dev/null +++ b/examples/location/planespotter/main.cpp @@ -0,0 +1,201 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of The Qt Company Ltd nor the names of its +** contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include <QGuiApplication> +#include <QQmlApplicationEngine> +#include <QQmlContext> +#include <QObject> +#include <QTime> +#include <QBasicTimer> +#include <QDebug> +#include <QEasingCurve> +#include <QGeoCoordinate> +#include <QtPositioning/private/qgeoprojection_p.h> + +#define ANIMATION_DURATION 4000 + +//! [PlaneController1] +class PlaneController: public QObject +{ + Q_OBJECT + Q_PROPERTY(QGeoCoordinate position READ position WRITE setPosition NOTIFY positionChanged) +//! [PlaneController1] + //! [C++Pilot1] + Q_PROPERTY(QGeoCoordinate from READ from WRITE setFrom NOTIFY fromChanged) + Q_PROPERTY(QGeoCoordinate to READ to WRITE setTo NOTIFY toChanged) + //! [C++Pilot1] + +public: + PlaneController() + { + easingCurve.setType(QEasingCurve::InOutQuad); + easingCurve.setPeriod(ANIMATION_DURATION); + } + + void setFrom(const QGeoCoordinate& from) + { + fromCoordinate = from; + } + + QGeoCoordinate from() const + { + return fromCoordinate; + } + + void setTo(const QGeoCoordinate& to) + { + toCoordinate = to; + } + + QGeoCoordinate to() const + { + return toCoordinate; + } + + void setPosition(const QGeoCoordinate &c) { + if (currentPosition == c) + return; + + currentPosition = c; + emit positionChanged(); + } + + QGeoCoordinate position() const + { + return currentPosition; + } + + Q_INVOKABLE bool isFlying() const { + return timer.isActive(); + } + +//! [C++Pilot2] +public slots: + void startFlight() + { + if (timer.isActive()) + return; + + startTime = QTime::currentTime(); + finishTime = startTime.addMSecs(ANIMATION_DURATION); + + timer.start(15, this); + emit departed(); + } +//! [C++Pilot2] + + void swapDestinations() { + if (currentPosition == toCoordinate) { + // swap destinations + toCoordinate = fromCoordinate; + fromCoordinate = currentPosition; + } + } + +signals: + void positionChanged(); + void arrived(); + void departed(); + void toChanged(); + void fromChanged(); + +protected: + void timerEvent(QTimerEvent *event) Q_DECL_OVERRIDE + { + if (!event) + return; + + if (event->timerId() == timer.timerId()) + updatePosition(); + else + QObject::timerEvent(event); + } + +private: + //! [C++Pilot3] + void updatePosition() + { + // simple progress animation + qreal progress; + QTime current = QTime::currentTime(); + if (current >= finishTime) { + progress = 1.0; + timer.stop(); + } else { + progress = ((qreal)startTime.msecsTo(current) / ANIMATION_DURATION); + } + + setPosition(QGeoProjection::coordinateInterpolation( + fromCoordinate, toCoordinate, easingCurve.valueForProgress(progress))); + + if (!timer.isActive()) + emit arrived(); + } + //! [C++Pilot3] + +private: + QGeoCoordinate currentPosition; + QGeoCoordinate fromCoordinate, toCoordinate; + QBasicTimer timer; + QTime startTime, finishTime; + QEasingCurve easingCurve; +//! [PlaneController2] + // ... +}; +//! [PlaneController2] + +//! [PlaneControllerMain] +int main(int argc, char *argv[]) +{ + QGuiApplication app(argc, argv); + + PlaneController oslo2berlin; + PlaneController berlin2london; + + QQmlApplicationEngine engine; + engine.rootContext()->setContextProperty("oslo2Berlin", &oslo2berlin); + engine.rootContext()->setContextProperty("berlin2London", &berlin2london); + engine.load(QUrl(QStringLiteral("qrc:/planespotter.qml"))); + + return app.exec(); +} +//! [PlaneControllerMain] + +#include "main.moc" diff --git a/examples/location/planespotter/planespotter.pro b/examples/location/planespotter/planespotter.pro new file mode 100644 index 00000000..d3be902c --- /dev/null +++ b/examples/location/planespotter/planespotter.pro @@ -0,0 +1,10 @@ +TEMPLATE = app +TARGET = planespotter +QT += qml quick positioning positioning-private location + +SOURCES += main.cpp + +RESOURCES += qml.qrc + +target.path = $$[QT_INSTALL_EXAMPLES]/location/planespotter +INSTALLS += target diff --git a/examples/location/planespotter/planespotter.qml b/examples/location/planespotter/planespotter.qml new file mode 100644 index 00000000..59b8b00b --- /dev/null +++ b/examples/location/planespotter/planespotter.qml @@ -0,0 +1,226 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of The Qt Company Ltd nor the names of its +** contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQuick 2.4 +import QtQuick.Window 2.2 +import QtPositioning 5.5 +import QtLocation 5.5 + +Window { + width: 700 + height: 500 + visible: true + + property variant topLeftEurope: QtPositioning.coordinate(60.5, 0.0) + property variant bottomRightEurope: QtPositioning.coordinate(51.0, 14.0) + property variant viewOfEurope: + QtPositioning.rectangle(topLeftEurope, bottomRightEurope) + + property variant berlin: QtPositioning.coordinate(52.5175, 13.384) + property variant oslo: QtPositioning.coordinate(59.9154, 10.7425) + property variant london: QtPositioning.coordinate(51.5, 0.1275) + + Map { + id: mapOfEurope + anchors.centerIn: parent; + anchors.fill: parent + plugin: Plugin { + name: "osm" + } + + Plane { + id: qmlPlane + pilotName: "QML" + coordinate: oslo2Berlin.position + + SequentialAnimation { + id: qmlPlaneAnimation + property real rotationDirection : 0; + NumberAnimation { + target: qmlPlane; property: "bearing"; duration: 1000 + easing.type: Easing.InOutQuad + to: qmlPlaneAnimation.rotationDirection + } + //! [QmlPlane1] + CoordinateAnimation { + id: coordinateAnimation; duration: 5000 + target: oslo2Berlin; property: "position" + easing.type: Easing.InOutQuad + } + //! [QmlPlane1] + + onStopped: { + if (coordinateAnimation.to === berlin) + qmlPlane.showMessage(qsTr("Hello Berlin!")) + else if (coordinateAnimation.to === oslo) + qmlPlane.showMessage(qsTr("Hello Oslo!")) + } + onStarted: { + if (coordinateAnimation.from === oslo) + qmlPlane.showMessage(qsTr("See you Oslo!")) + else if (coordinateAnimation.from === berlin) + qmlPlane.showMessage(qsTr("See you Berlin!")) + } + } + + //! [QmlPlane2] + MouseArea { + anchors.fill: parent + onClicked: { + if (qmlPlaneAnimation.running) { + console.log("Plane still in the air."); + return; + } + + if (oslo2Berlin.position === berlin) { + coordinateAnimation.from = berlin; + coordinateAnimation.to = oslo; + } else if (oslo2Berlin.position === oslo) { + coordinateAnimation.from = oslo; + coordinateAnimation.to = berlin; + } + + qmlPlaneAnimation.rotationDirection = oslo2Berlin.position.azimuthTo(coordinateAnimation.to) + qmlPlaneAnimation.start() + } + } + //! [QmlPlane2] + Component.onCompleted: { + oslo2Berlin.position = oslo; + } + } + + //! [CppPlane1] + Plane { + id: cppPlane + pilotName: "C++" + coordinate: berlin2London.position + + MouseArea { + anchors.fill: parent + onClicked: { + if (cppPlaneAnimation.running || berlin2London.isFlying()) { + console.log("Plane still in the air."); + return; + } + + berlin2London.swapDestinations(); + cppPlaneAnimation.rotationDirection = berlin2London.position.azimuthTo(berlin2London.to) + cppPlaneAnimation.start(); + cppPlane.departed(); + } + } + //! [CppPlane1] + //! [CppPlane3] + SequentialAnimation { + id: cppPlaneAnimation + property real rotationDirection : 0; + NumberAnimation { + target: cppPlane; property: "bearing"; duration: 1000 + easing.type: Easing.InOutQuad + to: cppPlaneAnimation.rotationDirection + } + ScriptAction { script: berlin2London.startFlight() } + } + //! [CppPlane3] + + Component.onCompleted: { + berlin2London.position = berlin; + berlin2London.to = london; + berlin2London.from = berlin; + berlin2London.arrived.connect(arrived) + } + + function arrived(){ + if (berlin2London.to === berlin) + cppPlane.showMessage(qsTr("Hello Berlin!")) + else if (berlin2London.to === london) + cppPlane.showMessage(qsTr("Hello London!")) + } + + function departed(){ + if (berlin2London.from === berlin) + cppPlane.showMessage(qsTr("See you Berlin!")) + else if (berlin2London.from === london) + cppPlane.showMessage(qsTr("See you London!")) + } + //! [CppPlane2] + } + //! [CppPlane2] + + onWidthChanged: { + if (width > 0) + mapOfEurope.fitViewportToGeoShape(viewOfEurope) + } + + onHeightChanged: { + if (height > 0) + mapOfEurope.fitViewportToGeoShape(viewOfEurope) + } + } + + Rectangle { + id: infoBox + anchors.centerIn: parent + color: "white" + border.width: 1 + width: text.width * 1.3 + height: text.height * 1.3 + radius: 5 + Text { + id: text + anchors.centerIn: parent + text: qsTr("Hit the plane to start the flight!") + } + + Timer { + interval: 5000; running: true; repeat: false; + onTriggered: fadeOut.start() + } + + NumberAnimation { + id: fadeOut; target: infoBox; + property: "opacity"; + to: 0.0; + duration: 200 + easing.type: Easing.InOutQuad + } + } +} diff --git a/examples/location/planespotter/qml.qrc b/examples/location/planespotter/qml.qrc new file mode 100644 index 00000000..6903ec0f --- /dev/null +++ b/examples/location/planespotter/qml.qrc @@ -0,0 +1,7 @@ +<RCC> + <qresource prefix="/"> + <file>planespotter.qml</file> + <file>Plane.qml</file> + <file>airplane.png</file> + </qresource> +</RCC> diff --git a/src/location/doc/images/planespotter.jpg b/src/location/doc/images/planespotter.jpg Binary files differnew file mode 100644 index 00000000..d65a0328 --- /dev/null +++ b/src/location/doc/images/planespotter.jpg diff --git a/src/location/doc/src/examples/planespotter.qdoc b/src/location/doc/src/examples/planespotter.qdoc new file mode 100644 index 00000000..991e83c4 --- /dev/null +++ b/src/location/doc/src/examples/planespotter.qdoc @@ -0,0 +1,169 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the documentation of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:FDL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Free Documentation License Usage +** Alternatively, this file may be used under the terms of the GNU Free +** Documentation License version 1.3 as published by the Free Software +** Foundation and appearing in the file included in the packaging of +** this file. Please review the following information to ensure +** the GNU Free Documentation License version 1.3 requirements +** will be met: http://www.gnu.org/copyleft/fdl.html. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +/*! + \example planespotter + \title Plane Spotter (QML) + \ingroup qtlocation-examples + + \brief The \c {Plane Spotter} example demonstrates the tight integration of + location and positioning data types into QML + + \image planespotter.jpg + + The \c {Plane Spotter} example demonstrates how to integrate location and positioning + related C++ data types into QML and vice versa. This is useful when it is desirable to + run CPU intensive position calculations in native environments + but the results are supposed to be displayed using QML. + + The example shows a map of Europe and airplanes on two routes across Europe. + The first airplane commutes between Oslo and Berlin and the second airplane + commutes between London and Berlin. The position tracking of each airplane + is implemented in C++. The Oslo-Berlin plane is piloted in QML and the London-Berlin + plane is commanded by a C++ pilot. + + \include examples-run.qdocinc + + \section1 Integrating C++ Data Structures + + Starting with Qt 5.5, it has become much easier to integrate non-QObject based + data types into QML. This is achieved by adding \l Q_GADGET support to QtQml. + The macro converts classes into a light-weight + version of a QObject without the required \l QObject inheritance but retains + the reflection capabilities of \l QMetaObject. As a result they can be directly + exposed to QML and do not require any further wrapper classes. + + To make use of this new development a significant number of Position and Location + related data types were converted to Q_GADGETs. They retain their API and value + type character but have become introspectable via \l QMetaObject. This conversion + was done to the following classes: + + \list + \li \l QGeoCircle + \li \l QGeoCoordinate + \li \l QGeoRectangle + \li \l QGeoShape + \endlist + + Using \l QGeoCoordinate as an example, the C++ types are directly exposed to the + QML environment via its meta type: + + \code + qRegisterMetaType<QGeoCoordinate>(); + QMetaType::registerEqualsComparator<QGeoCoordinate>(); + \endcode + + The above registration of \l QGeoCoordinate is automatically done once by the + QtPositioning QML plugin. + + This example makes use of the feature as part of its position controller + implementation. The main purpose of the class is to track the current + coordinates of the plane at a given time. It exposes the position + via its position property. + + \snippet planespotter/main.cpp PlaneController1 + \snippet planespotter/main.cpp PlaneController2 + + The example's \c main() function is responsible for the binding of the + \c PlaneController class instances into the QML context: + + \snippet planespotter/main.cpp PlaneControllerMain + + Similar to QObject derived classes, \l QGeoCoordinate can be integrated without + an additional QML wrapper. + + \section1 Steering the Planes + + As mentioned above, the primary purpose of \c PlaneController class is to track the current + positions of the two planes (Oslo-Berlin and London-Berlin) and advertise them as a property + to the QML layer. Its secondary purpose is to set and progress a plane along a given + flight path. In a sense it can act as a pilot. This is very much like + \l CoordinateAnimation which can animate the transition from one geo coordinate to another. + This example demonstrates how the \c {PlaneController}'s position property is modified + by C++ code using the PlaneController's own piloting abilities and by QML code using + \l CoordinateAnimation as pilot. The Oslo-Berlin plane is animated using QML code + and the London-Berlin plane is animated using C++ code. + + No matter which pilot is used, the results to the pilot's + actions are visible in C++ and QML and thus the example demonstrates unhindered and direct + exchange of position data through the C++/QML boundary. + + The visual representation of each \c Plane is done using + the \l MapQuickItem type which permits the embedding of arbitrary QtQuick items + into a map: + + \snippet planespotter/Plane.qml PlaneMapQuick1 + \snippet planespotter/Plane.qml PlaneMapQuick2 + + \section2 The C++ Pilot + + The C++ plane is steered by C++. The \c from and \c to property of the controller + class set the origin and destination which the pilot uses to calculate the + bearing for the plane: + + \snippet planespotter/main.cpp C++Pilot1 + + The pilot employs a \l QBasicTimer and \l {QTimerEvent}{QTimerEvents} to + constantly update the position. During each timer iteration + \c PlaneController::updatePosition() is called and a new position calculated. + + \snippet planespotter/main.cpp C++Pilot3 + + Once the new position is calculated, \c setPosition() is called and + the subsequent change notification of the property pushes the new position + to the QML layer. + + The C++ plane is started by clicking on the plane: + + \snippet planespotter/planespotter.qml CppPlane1 + \snippet planespotter/planespotter.qml CppPlane2 + + \l {azimuthTo}() calculates the bearing in degrees from one coordinate to another. + Note that the above code utilizes a QML animation to tie the rotation + and the position change into a single animation flow: + + \snippet planespotter/planespotter.qml CppPlane3 + + First, \l NumberAnimation rotates the plane into the correct direction + and once that is done the \c startFlight() function takes care of + starting the plane's position change. + + \snippet planespotter/main.cpp C++Pilot2 + + \section2 The QML Pilot + + The \l CoordinateAnimation type is used to control the flight from Oslo + to Berlin and vice versa. It replaces the above \l ScriptAction. + + \snippet planespotter/planespotter.qml QmlPlane1 + + The \l MouseArea of the QML plane implements the logic for the course setting + and starts the animation when required. + + \snippet planespotter/planespotter.qml QmlPlane2 + +*/ |