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