1 /****************************************************************************
2 **
3 ** Copyright (C) 2017 The Qt Company Ltd.
4 ** Contact: https://www.qt.io/licensing/
5 **
6 ** This file is part of the examples of the Qt Toolkit.
7 **
8 ** $QT_BEGIN_LICENSE:BSD$
9 ** Commercial License Usage
10 ** Licensees holding valid commercial Qt licenses may use this file in
11 ** accordance with the commercial license agreement provided with the
12 ** Software or, alternatively, in accordance with the terms contained in
13 ** a written agreement between you and The Qt Company. For licensing terms
14 ** and conditions see https://www.qt.io/terms-conditions. For further
15 ** information use the contact form at https://www.qt.io/contact-us.
16 **
17 ** BSD License Usage
18 ** Alternatively, you may use this file under the terms of the BSD license
19 ** as follows:
20 **
21 ** "Redistribution and use in source and binary forms, with or without
22 ** modification, are permitted provided that the following conditions are
23 ** met:
24 **   * Redistributions of source code must retain the above copyright
25 **     notice, this list of conditions and the following disclaimer.
26 **   * Redistributions in binary form must reproduce the above copyright
27 **     notice, this list of conditions and the following disclaimer in
28 **     the documentation and/or other materials provided with the
29 **     distribution.
30 **   * Neither the name of The Qt Company Ltd nor the names of its
31 **     contributors may be used to endorse or promote products derived
32 **     from this software without specific prior written permission.
33 **
34 **
35 ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
36 ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
37 ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
38 ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
39 ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
40 ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
41 ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
42 ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
43 ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
44 ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
45 ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
46 **
47 ** $QT_END_LICENSE$
48 **
49 ****************************************************************************/
50 
51 #include <QGuiApplication>
52 #include <QQmlApplicationEngine>
53 #include <QQmlContext>
54 #include <QObject>
55 #include <QTime>
56 #include <QBasicTimer>
57 #include <QDebug>
58 #include <QEasingCurve>
59 #include <QGeoCoordinate>
60 #include <QtPositioning/private/qwebmercator_p.h>
61 
62 #define ANIMATION_DURATION 4000
63 
64 //! [PlaneController1]
65 class PlaneController: public QObject
66 {
67     Q_OBJECT
68     Q_PROPERTY(QGeoCoordinate position READ position WRITE setPosition NOTIFY positionChanged)
69 //! [PlaneController1]
70     //! [C++Pilot1]
71     Q_PROPERTY(QGeoCoordinate from READ from WRITE setFrom NOTIFY fromChanged)
72     Q_PROPERTY(QGeoCoordinate to READ to WRITE setTo NOTIFY toChanged)
73     //! [C++Pilot1]
74 
75 public:
PlaneController()76     PlaneController()
77     {
78         easingCurve.setType(QEasingCurve::InOutQuad);
79         easingCurve.setPeriod(ANIMATION_DURATION);
80     }
81 
setFrom(const QGeoCoordinate & from)82     void setFrom(const QGeoCoordinate& from)
83     {
84         fromCoordinate = from;
85     }
86 
from() const87     QGeoCoordinate from() const
88     {
89         return fromCoordinate;
90     }
91 
setTo(const QGeoCoordinate & to)92     void setTo(const QGeoCoordinate& to)
93     {
94         toCoordinate = to;
95     }
96 
to() const97     QGeoCoordinate to() const
98     {
99         return toCoordinate;
100     }
101 
setPosition(const QGeoCoordinate & c)102     void setPosition(const QGeoCoordinate &c) {
103         if (currentPosition == c)
104             return;
105 
106         currentPosition = c;
107         emit positionChanged();
108     }
109 
position() const110     QGeoCoordinate position() const
111     {
112         return currentPosition;
113     }
114 
isFlying() const115     Q_INVOKABLE bool isFlying() const {
116         return timer.isActive();
117     }
118 
119 //! [C++Pilot2]
120 public slots:
startFlight()121     void startFlight()
122     {
123         if (timer.isActive())
124             return;
125 
126         startTime = QTime::currentTime();
127         finishTime = startTime.addMSecs(ANIMATION_DURATION);
128 
129         timer.start(15, this);
130         emit departed();
131     }
132 //! [C++Pilot2]
133 
swapDestinations()134     void swapDestinations() {
135         if (currentPosition == toCoordinate) {
136             // swap destinations
137             toCoordinate = fromCoordinate;
138             fromCoordinate = currentPosition;
139         }
140     }
141 
142 signals:
143     void positionChanged();
144     void arrived();
145     void departed();
146     void toChanged();
147     void fromChanged();
148 
149 protected:
timerEvent(QTimerEvent * event)150     void timerEvent(QTimerEvent *event) override
151     {
152         if (!event)
153             return;
154 
155         if (event->timerId() == timer.timerId())
156             updatePosition();
157         else
158             QObject::timerEvent(event);
159     }
160 
161 private:
162     //! [C++Pilot3]
updatePosition()163     void updatePosition()
164     {
165         // simple progress animation
166         qreal progress;
167         QTime current = QTime::currentTime();
168         if (current >= finishTime) {
169             progress = 1.0;
170             timer.stop();
171         } else {
172             progress = ((qreal)startTime.msecsTo(current) / ANIMATION_DURATION);
173         }
174 
175         setPosition(QWebMercator::coordinateInterpolation(
176                           fromCoordinate, toCoordinate, easingCurve.valueForProgress(progress)));
177 
178         if (!timer.isActive())
179             emit arrived();
180     }
181     //! [C++Pilot3]
182 
183 private:
184     QGeoCoordinate currentPosition;
185     QGeoCoordinate fromCoordinate, toCoordinate;
186     QBasicTimer timer;
187     QTime startTime, finishTime;
188     QEasingCurve easingCurve;
189 //! [PlaneController2]
190     // ...
191 };
192 //! [PlaneController2]
193 
194 //! [PlaneControllerMain]
main(int argc,char * argv[])195 int main(int argc, char *argv[])
196 {
197     QGuiApplication app(argc, argv);
198 
199     PlaneController oslo2berlin;
200     PlaneController berlin2london;
201 
202     QQmlApplicationEngine engine;
203     engine.rootContext()->setContextProperty("oslo2Berlin", &oslo2berlin);
204     engine.rootContext()->setContextProperty("berlin2London", &berlin2london);
205     engine.load(QUrl(QStringLiteral("qrc:/planespotter.qml")));
206 
207     return app.exec();
208 }
209 //! [PlaneControllerMain]
210 
211 #include "main.moc"
212