1 /**************************************************************************** 2 ** 3 ** Copyright (C) 2015 The Qt Company Ltd. 4 ** Contact: http://www.qt.io/licensing/ 5 ** 6 ** This file is part of the QtLocation module of the Qt Toolkit. 7 ** 8 ** $QT_BEGIN_LICENSE:LGPL3$ 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 http://www.qt.io/terms-conditions. For further 15 ** information use the contact form at http://www.qt.io/contact-us. 16 ** 17 ** GNU Lesser General Public License Usage 18 ** Alternatively, this file may be used under the terms of the GNU Lesser 19 ** General Public License version 3 as published by the Free Software 20 ** Foundation and appearing in the file LICENSE.LGPLv3 included in the 21 ** packaging of this file. Please review the following information to 22 ** ensure the GNU Lesser General Public License version 3 requirements 23 ** will be met: https://www.gnu.org/licenses/lgpl.html. 24 ** 25 ** GNU General Public License Usage 26 ** Alternatively, this file may be used under the terms of the GNU 27 ** General Public License version 2.0 or later as published by the Free 28 ** Software Foundation and appearing in the file LICENSE.GPL included in 29 ** the packaging of this file. Please review the following information to 30 ** ensure the GNU General Public License version 2.0 requirements will be 31 ** met: http://www.gnu.org/licenses/gpl-2.0.html. 32 ** 33 ** $QT_END_LICENSE$ 34 ** 35 ****************************************************************************/ 36 37 #ifndef QQUICKGEOMAPGESTUREAREA_P_H 38 #define QQUICKGEOMAPGESTUREAREA_P_H 39 40 // 41 // W A R N I N G 42 // ------------- 43 // 44 // This file is not part of the Qt API. It exists purely as an 45 // implementation detail. This header file may change from version to 46 // version without notice, or even be removed. 47 // 48 // We mean it. 49 // 50 51 #include <QtLocation/private/qlocationglobal_p.h> 52 53 #include <QtCore/QPointer> 54 #include <QtQuick/QQuickItem> 55 #include <QTouchEvent> 56 #include <QDebug> 57 #include <QElapsedTimer> 58 #include <QtPositioning/qgeocoordinate.h> 59 #include <QtGui/QVector2D> 60 61 QT_BEGIN_NAMESPACE 62 63 class QGraphicsSceneMouseEvent; 64 class QQuickGeoCoordinateAnimation; 65 class QDeclarativeGeoMap; 66 class QTouchEvent; 67 class QWheelEvent; 68 class QGeoMap; 69 70 class Q_LOCATION_PRIVATE_EXPORT QGeoMapPinchEvent : public QObject 71 { 72 Q_OBJECT 73 Q_PROPERTY(QPointF center READ center)74 Q_PROPERTY(QPointF center READ center) 75 Q_PROPERTY(qreal angle READ angle) 76 Q_PROPERTY(QPointF point1 READ point1) 77 Q_PROPERTY(QPointF point2 READ point2) 78 Q_PROPERTY(int pointCount READ pointCount) 79 Q_PROPERTY(bool accepted READ accepted WRITE setAccepted) 80 81 public: 82 QGeoMapPinchEvent(const QPointF ¢er, qreal angle, 83 const QPointF &point1, const QPointF &point2, 84 int pointCount = 0, bool accepted = true) 85 : QObject(), m_center(center), m_angle(angle), 86 m_point1(point1), m_point2(point2), 87 m_pointCount(pointCount), m_accepted(accepted) {} QGeoMapPinchEvent()88 QGeoMapPinchEvent() 89 : QObject(), 90 m_angle(0.0), 91 m_pointCount(0), 92 m_accepted(true) {} 93 center()94 QPointF center() const { return m_center; } setCenter(const QPointF & center)95 void setCenter(const QPointF ¢er) { m_center = center; } angle()96 qreal angle() const { return m_angle; } setAngle(qreal angle)97 void setAngle(qreal angle) { m_angle = angle; } point1()98 QPointF point1() const { return m_point1; } setPoint1(const QPointF & p)99 void setPoint1(const QPointF &p) { m_point1 = p; } point2()100 QPointF point2() const { return m_point2; } setPoint2(const QPointF & p)101 void setPoint2(const QPointF &p) { m_point2 = p; } pointCount()102 int pointCount() const { return m_pointCount; } setPointCount(int count)103 void setPointCount(int count) { m_pointCount = count; } accepted()104 bool accepted() const { return m_accepted; } setAccepted(bool a)105 void setAccepted(bool a) { m_accepted = a; } 106 107 private: 108 QPointF m_center; 109 qreal m_angle; 110 QPointF m_point1; 111 QPointF m_point2; 112 int m_pointCount; 113 bool m_accepted; 114 }; 115 116 class Q_LOCATION_PRIVATE_EXPORT QQuickGeoMapGestureArea: public QQuickItem 117 { 118 Q_OBJECT 119 Q_ENUMS(GeoMapGesture) 120 Q_FLAGS(AcceptedGestures) 121 122 Q_PROPERTY(bool enabled READ enabled WRITE setEnabled NOTIFY enabledChanged) 123 Q_PROPERTY(bool pinchActive READ isPinchActive NOTIFY pinchActiveChanged) 124 Q_PROPERTY(bool panActive READ isPanActive NOTIFY panActiveChanged) 125 Q_PROPERTY(bool rotationActive READ isRotationActive NOTIFY rotationActiveChanged) 126 Q_PROPERTY(bool tiltActive READ isTiltActive NOTIFY tiltActiveChanged) 127 Q_PROPERTY(AcceptedGestures acceptedGestures READ acceptedGestures WRITE setAcceptedGestures NOTIFY acceptedGesturesChanged) 128 Q_PROPERTY(qreal maximumZoomLevelChange READ maximumZoomLevelChange WRITE setMaximumZoomLevelChange NOTIFY maximumZoomLevelChangeChanged) 129 Q_PROPERTY(qreal flickDeceleration READ flickDeceleration WRITE setFlickDeceleration NOTIFY flickDecelerationChanged) 130 Q_PROPERTY(bool preventStealing READ preventStealing WRITE setPreventStealing NOTIFY preventStealingChanged REVISION 1) 131 132 public: 133 QQuickGeoMapGestureArea(QDeclarativeGeoMap *map); 134 ~QQuickGeoMapGestureArea(); 135 136 enum GeoMapGesture { 137 NoGesture = 0x0000, 138 PinchGesture = 0x0001, 139 PanGesture = 0x0002, 140 FlickGesture = 0x0004, 141 RotationGesture = 0x0008, 142 TiltGesture = 0x0010 143 }; 144 145 Q_DECLARE_FLAGS(AcceptedGestures, GeoMapGesture) 146 147 AcceptedGestures acceptedGestures() const; 148 void setAcceptedGestures(AcceptedGestures acceptedGestures); 149 150 bool isPinchActive() const; 151 bool isRotationActive() const; 152 bool isTiltActive() const; 153 bool isPanActive() const; 154 bool isActive() const; 155 156 bool enabled() const; 157 void setEnabled(bool enabled); 158 159 qreal maximumZoomLevelChange() const; 160 void setMaximumZoomLevelChange(qreal maxChange); 161 162 qreal flickDeceleration() const; 163 void setFlickDeceleration(qreal deceleration); 164 165 void handleTouchEvent(QTouchEvent *event); 166 #if QT_CONFIG(wheelevent) 167 void handleWheelEvent(QWheelEvent *event); 168 #endif 169 void handleMousePressEvent(QMouseEvent *event); 170 void handleMouseMoveEvent(QMouseEvent *event); 171 void handleMouseReleaseEvent(QMouseEvent *event); 172 void handleMouseUngrabEvent(); 173 void handleTouchUngrabEvent(); 174 175 void setMinimumZoomLevel(qreal min); 176 qreal minimumZoomLevel() const; 177 178 void setMaximumZoomLevel(qreal max); 179 qreal maximumZoomLevel() const; 180 181 void setMap(QGeoMap* map); 182 183 bool preventStealing() const; 184 void setPreventStealing(bool prevent); 185 186 Q_SIGNALS: 187 void panActiveChanged(); 188 void pinchActiveChanged(); 189 void rotationActiveChanged(); 190 void tiltActiveChanged(); 191 void enabledChanged(); 192 void maximumZoomLevelChangeChanged(); 193 void acceptedGesturesChanged(); 194 void flickDecelerationChanged(); 195 void pinchStarted(QGeoMapPinchEvent *pinch); 196 void pinchUpdated(QGeoMapPinchEvent *pinch); 197 void pinchFinished(QGeoMapPinchEvent *pinch); 198 void panStarted(); 199 void panFinished(); 200 void flickStarted(); 201 void flickFinished(); 202 void rotationStarted(QGeoMapPinchEvent *pinch); 203 void rotationUpdated(QGeoMapPinchEvent *pinch); 204 void rotationFinished(QGeoMapPinchEvent *pinch); 205 void tiltStarted(QGeoMapPinchEvent *pinch); 206 void tiltUpdated(QGeoMapPinchEvent *pinch); 207 void tiltFinished(QGeoMapPinchEvent *pinch); 208 void preventStealingChanged(); 209 private: 210 void update(); 211 212 // Create general data relating to the touch points 213 void touchPointStateMachine(); 214 void startOneTouchPoint(); 215 void updateOneTouchPoint(); 216 void startTwoTouchPoints(); 217 void updateTwoTouchPoints(); 218 219 // All two fingers vertical parallel panning related code, which encompasses tilting 220 void tiltStateMachine(); 221 bool canStartTilt(); 222 void startTilt(); 223 void updateTilt(); 224 void endTilt(); 225 226 // All two fingers rotation related code, which encompasses rotation 227 void rotationStateMachine(); 228 bool canStartRotation(); 229 void startRotation(); 230 void updateRotation(); 231 void endRotation(); 232 233 // All pinch related code, which encompasses zoom 234 void pinchStateMachine(); 235 bool canStartPinch(); 236 void startPinch(); 237 void updatePinch(); 238 void endPinch(); 239 240 // Pan related code (regardles of number of touch points), 241 // includes the flick based panning after letting go 242 void panStateMachine(); 243 bool canStartPan(); 244 void updatePan(); 245 bool tryStartFlick(); 246 void startFlick(int dx, int dy, int timeMs = 0); 247 void stopFlick(); 248 249 bool pinchEnabled() const; 250 void setPinchEnabled(bool enabled); 251 bool rotationEnabled() const; 252 void setRotationEnabled(bool enabled); 253 bool tiltEnabled() const; 254 void setTiltEnabled(bool enabled); 255 bool panEnabled() const; 256 void setPanEnabled(bool enabled); 257 bool flickEnabled() const; 258 void setFlickEnabled(bool enabled); 259 260 private Q_SLOTS: 261 void handleFlickAnimationStopped(); 262 263 264 private: 265 void stopPan(); 266 void clearTouchData(); 267 void updateFlickParameters(const QPointF &pos); 268 269 private: 270 QGeoMap* m_map; 271 QDeclarativeGeoMap *m_declarativeMap; 272 bool m_enabled; 273 274 // This should be intended as a "two fingers gesture" struct 275 struct Pinch 276 { PinchPinch277 Pinch() : m_pinchEnabled(true), m_rotationEnabled(true), m_tiltEnabled(true), 278 m_startDist(0), m_lastAngle(0.0) {} 279 280 QGeoMapPinchEvent m_event; 281 bool m_pinchEnabled; 282 bool m_rotationEnabled; 283 bool m_tiltEnabled; 284 struct Zoom 285 { ZoomPinch::Zoom286 Zoom() : m_minimum(0.0), m_maximum(30.0), m_start(0.0), m_previous(0.0), 287 maximumChange(4.0) {} 288 qreal m_minimum; 289 qreal m_maximum; 290 qreal m_start; 291 qreal m_previous; 292 qreal maximumChange; 293 } m_zoom; 294 295 struct Rotation 296 { RotationPinch::Rotation297 Rotation() : m_startBearing(0.0), m_previousTouchAngle(0.0), m_totalAngle(0.0) {} 298 qreal m_startBearing; 299 qreal m_previousTouchAngle; // needed for detecting crossing +- 180 in a safer way 300 qreal m_totalAngle; 301 } m_rotation; 302 303 struct Tilt 304 { TiltPinch::Tilt305 Tilt() {} 306 QPointF m_startTouchCentroid; 307 qreal m_startTilt; 308 } m_tilt; 309 310 QPointF m_lastPoint1; 311 QPointF m_lastPoint2; 312 qreal m_startDist; 313 qreal m_lastAngle; 314 } m_pinch; 315 316 AcceptedGestures m_acceptedGestures; 317 318 struct Pan 319 { PanPan320 Pan() : m_maxVelocity(2500), m_deceleration(2500), m_animation(0), m_flickEnabled(true), m_panEnabled(true) {} 321 322 qreal m_maxVelocity; 323 qreal m_deceleration; 324 QQuickGeoCoordinateAnimation *m_animation; 325 bool m_flickEnabled; 326 bool m_panEnabled; 327 } m_flick; 328 329 330 // these are calculated regardless of gesture or number of touch points 331 QVector2D m_flickVector; 332 QElapsedTimer m_lastPosTime; 333 QPointF m_lastPos; 334 QVector<QTouchEvent::TouchPoint> m_allPoints; 335 QVector<QTouchEvent::TouchPoint> m_touchPoints; 336 QScopedPointer<QTouchEvent::TouchPoint> m_mousePoint; 337 QPointF m_sceneStartPoint1; 338 339 // only set when two points in contact 340 QPointF m_sceneStartPoint2; 341 QGeoCoordinate m_startCoord; 342 QGeoCoordinate m_touchCenterCoord; 343 qreal m_twoTouchAngle; 344 qreal m_twoTouchAngleStart; 345 qreal m_distanceBetweenTouchPoints; 346 qreal m_distanceBetweenTouchPointsStart; 347 QPointF m_twoTouchPointsCentroidStart; 348 QPointF m_touchPointsCentroid; 349 bool m_preventStealing; 350 bool m_panEnabled; 351 352 private: 353 // prototype state machine... 354 enum TouchPointState 355 { 356 touchPoints0, 357 touchPoints1, 358 touchPoints2 359 } m_touchPointState; 360 361 enum PinchState 362 { 363 pinchInactive, 364 pinchInactiveTwoPoints, 365 pinchActive 366 } m_pinchState; 367 368 enum RotationState 369 { 370 rotationInactive, 371 rotationInactiveTwoPoints, 372 rotationActive 373 } m_rotationState; 374 375 enum TiltState 376 { 377 tiltInactive, 378 tiltInactiveTwoPoints, 379 tiltActive 380 } m_tiltState; 381 382 enum FlickState 383 { 384 flickInactive, 385 panActive, 386 flickActive 387 } m_flickState; 388 389 inline void setTouchPointState(const TouchPointState state); 390 inline void setFlickState(const FlickState state); 391 inline void setTiltState(const TiltState state); 392 inline void setRotationState(const RotationState state); 393 inline void setPinchState(const PinchState state); 394 }; 395 396 QT_END_NAMESPACE 397 QML_DECLARE_TYPE(QQuickGeoMapGestureArea) 398 399 #endif // QQUICKGEOMAPGESTUREAREA_P_H 400