diff options
author | Ivan Solovev <ivan.solovev@qt.io> | 2021-07-26 15:19:56 +0200 |
---|---|---|
committer | Qt Cherry-pick Bot <cherrypick_bot@qt-project.org> | 2021-07-27 15:04:52 +0000 |
commit | 31865920e3fe4122403ceadb7178dc226034feb3 (patch) | |
tree | e2fb30d1f1c31e0cdfa5a087683ae01300b48a9a | |
parent | 2a5f7d270b58a7ec0ada33df62e4dc64afd3becd (diff) |
Add qHash overloads to QGeoShape hierarchy
This patch adds qHash overloads to QGeoShape hierarchy, allowing to use
the classes as keys in QHash.
Note that the actual qHash overload is required only for the base type.
All the derived classes are correctly hashed using the virtual method
in private d_ptr.
Task-number: QTBUG-95163
Change-Id: I186f9d396e698187ebf0363d96c19e324db10905
Reviewed-by: Alex Blasche <alexander.blasche@qt.io>
(cherry picked from commit cc6d520ee633d15b18724e3b7e6ecff25570dd0d)
Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org>
-rw-r--r-- | src/positioning/qgeocircle.cpp | 5 | ||||
-rw-r--r-- | src/positioning/qgeocircle_p.h | 2 | ||||
-rw-r--r-- | src/positioning/qgeopath.cpp | 6 | ||||
-rw-r--r-- | src/positioning/qgeopath_p.h | 1 | ||||
-rw-r--r-- | src/positioning/qgeopolygon.cpp | 7 | ||||
-rw-r--r-- | src/positioning/qgeopolygon_p.h | 1 | ||||
-rw-r--r-- | src/positioning/qgeorectangle.cpp | 5 | ||||
-rw-r--r-- | src/positioning/qgeorectangle_p.h | 2 | ||||
-rw-r--r-- | src/positioning/qgeoshape.cpp | 15 | ||||
-rw-r--r-- | src/positioning/qgeoshape.h | 3 | ||||
-rw-r--r-- | src/positioning/qgeoshape_p.h | 2 | ||||
-rw-r--r-- | tests/auto/qgeocircle/tst_qgeocircle.cpp | 20 | ||||
-rw-r--r-- | tests/auto/qgeopath/tst_qgeopath.cpp | 20 | ||||
-rw-r--r-- | tests/auto/qgeopolygon/tst_qgeopolygon.cpp | 23 | ||||
-rw-r--r-- | tests/auto/qgeorectangle/tst_qgeorectangle.cpp | 20 | ||||
-rw-r--r-- | tests/auto/qgeoshape/tst_qgeoshape.cpp | 38 |
16 files changed, 170 insertions, 0 deletions
diff --git a/src/positioning/qgeocircle.cpp b/src/positioning/qgeocircle.cpp index f1ad77d7..195736e5 100644 --- a/src/positioning/qgeocircle.cpp +++ b/src/positioning/qgeocircle.cpp @@ -483,4 +483,9 @@ bool QGeoCirclePrivate::operator==(const QGeoShapePrivate &other) const return m_radius == otherCircle.m_radius && m_center == otherCircle.m_center; } +size_t QGeoCirclePrivate::hash(size_t seed) const +{ + return qHashMulti(seed, m_center, m_radius); +} + QT_END_NAMESPACE diff --git a/src/positioning/qgeocircle_p.h b/src/positioning/qgeocircle_p.h index 5e957f6f..65f1d9d1 100644 --- a/src/positioning/qgeocircle_p.h +++ b/src/positioning/qgeocircle_p.h @@ -84,6 +84,8 @@ public: bool operator==(const QGeoShapePrivate &other) const override; + size_t hash(size_t seed) const override; + QGeoCoordinate m_center; qreal m_radius; QGeoRectangle m_bbox; diff --git a/src/positioning/qgeopath.cpp b/src/positioning/qgeopath.cpp index 36c537c7..9f327bd8 100644 --- a/src/positioning/qgeopath.cpp +++ b/src/positioning/qgeopath.cpp @@ -609,6 +609,12 @@ QGeoRectangle QGeoPathPrivate::boundingGeoRectangle() const return m_bbox; } +size_t QGeoPathPrivate::hash(size_t seed) const +{ + const size_t res = qHashRange(m_path.cbegin(), m_path.cend(), seed); + return qHashMulti(seed, res, m_width); +} + void QGeoPathPrivate::setPath(const QList<QGeoCoordinate> &path) { for (const QGeoCoordinate &c: path) diff --git a/src/positioning/qgeopath_p.h b/src/positioning/qgeopath_p.h index 3b7a1777..64abb621 100644 --- a/src/positioning/qgeopath_p.h +++ b/src/positioning/qgeopath_p.h @@ -184,6 +184,7 @@ public: virtual bool operator==(const QGeoShapePrivate &other) const override; virtual bool contains(const QGeoCoordinate &coordinate) const override; virtual QGeoRectangle boundingGeoRectangle() const override; + size_t hash(size_t seed) const override; // QGeoPathPrivate API virtual const QList<QGeoCoordinate> &path() const; diff --git a/src/positioning/qgeopolygon.cpp b/src/positioning/qgeopolygon.cpp index 71ee2578..073b5b30 100644 --- a/src/positioning/qgeopolygon.cpp +++ b/src/positioning/qgeopolygon.cpp @@ -558,6 +558,13 @@ bool QGeoPolygonPrivate::operator==(const QGeoShapePrivate &other) const return m_path == otherPath.m_path && m_holesList == otherPath.m_holesList; } +size_t QGeoPolygonPrivate::hash(size_t seed) const +{ + const size_t pointsHash = qHashRange(m_path.cbegin(), m_path.cend(), seed); + const size_t holesHash = qHashRange(m_holesList.cbegin(), m_holesList.cend(), seed); + return qHashMulti(seed, pointsHash, holesHash); +} + void QGeoPolygonPrivate::addHole(const QList<QGeoCoordinate> &holePath) { for (const QGeoCoordinate &holeVertex: holePath) diff --git a/src/positioning/qgeopolygon_p.h b/src/positioning/qgeopolygon_p.h index 199a97f7..718f2ddd 100644 --- a/src/positioning/qgeopolygon_p.h +++ b/src/positioning/qgeopolygon_p.h @@ -70,6 +70,7 @@ public: virtual bool contains(const QGeoCoordinate &coordinate) const override; virtual void translate(double degreesLatitude, double degreesLongitude) override; virtual bool operator==(const QGeoShapePrivate &other) const override; + size_t hash(size_t seed) const override; // QGeoPath API virtual void markDirty() override; diff --git a/src/positioning/qgeorectangle.cpp b/src/positioning/qgeorectangle.cpp index c276b40e..24ec22a3 100644 --- a/src/positioning/qgeorectangle.cpp +++ b/src/positioning/qgeorectangle.cpp @@ -1036,5 +1036,10 @@ bool QGeoRectanglePrivate::operator==(const QGeoShapePrivate &other) const return topLeft == otherBox.topLeft && bottomRight == otherBox.bottomRight; } +size_t QGeoRectanglePrivate::hash(size_t seed) const +{ + return qHashMulti(seed, topLeft, bottomRight); +} + QT_END_NAMESPACE diff --git a/src/positioning/qgeorectangle_p.h b/src/positioning/qgeorectangle_p.h index 632fdaa4..79a267f5 100644 --- a/src/positioning/qgeorectangle_p.h +++ b/src/positioning/qgeorectangle_p.h @@ -78,6 +78,8 @@ public: bool operator==(const QGeoShapePrivate &other) const override; + size_t hash(size_t seed) const override; + QGeoCoordinate topLeft; QGeoCoordinate bottomRight; }; diff --git a/src/positioning/qgeoshape.cpp b/src/positioning/qgeoshape.cpp index 58df873b..7ab32b60 100644 --- a/src/positioning/qgeoshape.cpp +++ b/src/positioning/qgeoshape.cpp @@ -429,6 +429,21 @@ QDataStream &QGeoShape::dataStreamIn(QDataStream &stream, QGeoShape &shape) } #endif +/*! + \relates QGeoShape + + Returns the hash value for the \a shape, using \a seed for the + calculation. +*/ +size_t qHash(const QGeoShape &shape, size_t seed) noexcept +{ + if (shape.d_ptr) + return shape.d_ptr->hash(seed); + else + return qHashMulti(seed, shape.type()); +} + QT_END_NAMESPACE #include "moc_qgeoshape.cpp" + diff --git a/src/positioning/qgeoshape.h b/src/positioning/qgeoshape.h index ffabf4dc..f2a9166c 100644 --- a/src/positioning/qgeoshape.h +++ b/src/positioning/qgeoshape.h @@ -119,8 +119,11 @@ private: static QDataStream &dataStreamOut(QDataStream &stream, const QGeoShape &shape); static QDataStream &dataStreamIn(QDataStream &stream, QGeoShape &shape); #endif + friend Q_POSITIONING_EXPORT size_t qHash(const QGeoShape &key, size_t seed) noexcept; }; +Q_POSITIONING_EXPORT size_t qHash(const QGeoShape &shape, size_t seed = 0) noexcept; + Q_DECLARE_TYPEINFO(QGeoShape, Q_RELOCATABLE_TYPE); QT_END_NAMESPACE diff --git a/src/positioning/qgeoshape_p.h b/src/positioning/qgeoshape_p.h index fcc8f8b6..94551c89 100644 --- a/src/positioning/qgeoshape_p.h +++ b/src/positioning/qgeoshape_p.h @@ -75,6 +75,8 @@ public: virtual bool operator==(const QGeoShapePrivate &other) const; + virtual size_t hash(size_t seed) const = 0; + QGeoShape::ShapeType type; }; diff --git a/tests/auto/qgeocircle/tst_qgeocircle.cpp b/tests/auto/qgeocircle/tst_qgeocircle.cpp index 8777e7d9..f3ff436f 100644 --- a/tests/auto/qgeocircle/tst_qgeocircle.cpp +++ b/tests/auto/qgeocircle/tst_qgeocircle.cpp @@ -71,6 +71,8 @@ private slots: void boxComparison(); void boxComparison_data(); + + void hashing(); }; void tst_QGeoCircle::defaultConstructor() @@ -449,5 +451,23 @@ void tst_QGeoCircle::boxComparison() QCOMPARE((circle != box), !equal); } +void tst_QGeoCircle::hashing() +{ + const QGeoCircle circle(QGeoCoordinate(1, 1), 10); + const size_t circleHash = qHash(circle); + + QGeoCircle otherCenterCircle = circle; + otherCenterCircle.setCenter(QGeoCoordinate(1, 2)); + QVERIFY(qHash(otherCenterCircle) != circleHash); + + QGeoCircle otherRadiusCircle = circle; + otherRadiusCircle.setRadius(100); + QVERIFY(qHash(otherRadiusCircle) != circleHash); + + // Do not assign, so that they do not share same d_ptr + QGeoCircle similarCircle(QGeoCoordinate(1, 1), 10); + QCOMPARE(qHash(similarCircle), circleHash); +} + QTEST_MAIN(tst_QGeoCircle) #include "tst_qgeocircle.moc" diff --git a/tests/auto/qgeopath/tst_qgeopath.cpp b/tests/auto/qgeopath/tst_qgeopath.cpp index 4d71130c..ccaef0d7 100644 --- a/tests/auto/qgeopath/tst_qgeopath.cpp +++ b/tests/auto/qgeopath/tst_qgeopath.cpp @@ -60,6 +60,8 @@ private slots: void boundingGeoRectangle_data(); void boundingGeoRectangle(); + + void hashing(); }; void tst_QGeoPath::defaultConstructor() @@ -368,5 +370,23 @@ void tst_QGeoPath::boundingGeoRectangle() QCOMPARE(box.contains(probe), result); } +void tst_QGeoPath::hashing() +{ + const QGeoPath path({ QGeoCoordinate(1, 1), QGeoCoordinate(1, 2), QGeoCoordinate(2, 5) }, 1.0); + const size_t pathHash = qHash(path); + + QGeoPath otherCoordsPath = path; + otherCoordsPath.addCoordinate(QGeoCoordinate(3, 5)); + QVERIFY(qHash(otherCoordsPath) != pathHash); + + QGeoPath otherWidthPath = path; + otherWidthPath.setWidth(1.5); + QVERIFY(qHash(otherWidthPath) != pathHash); + + // Do not assign, so that they do not share same d_ptr + QGeoPath similarPath({ QGeoCoordinate(1, 1), QGeoCoordinate(1, 2), QGeoCoordinate(2, 5) }, 1.0); + QCOMPARE(qHash(similarPath), pathHash); +} + QTEST_MAIN(tst_QGeoPath) #include "tst_qgeopath.moc" diff --git a/tests/auto/qgeopolygon/tst_qgeopolygon.cpp b/tests/auto/qgeopolygon/tst_qgeopolygon.cpp index 1f2b015a..8a8a8fd7 100644 --- a/tests/auto/qgeopolygon/tst_qgeopolygon.cpp +++ b/tests/auto/qgeopolygon/tst_qgeopolygon.cpp @@ -59,6 +59,8 @@ private slots: void boundingGeoRectangle_data(); void boundingGeoRectangle(); + + void hashing(); }; void tst_QGeoPolygon::defaultConstructor() @@ -355,5 +357,26 @@ void tst_QGeoPolygon::boundingGeoRectangle() QCOMPARE(box.contains(probe), result); } +void tst_QGeoPolygon::hashing() +{ + const QGeoPolygon polygon({ QGeoCoordinate(1, 1), QGeoCoordinate(2, 2), + QGeoCoordinate(3, 0) }); + const size_t polygonHash = qHash(polygon); + + QGeoPolygon otherCoordsPolygon = polygon; + otherCoordsPolygon.addCoordinate(QGeoCoordinate(4, 1)); + QVERIFY(qHash(otherCoordsPolygon) != polygonHash); + + QGeoPolygon otherHolesPolygon = polygon; + otherHolesPolygon.addHole({ QGeoCoordinate(1.1, 1), QGeoCoordinate(2, 1.8), + QGeoCoordinate(2, 1) }); + QVERIFY(qHash(otherHolesPolygon) != polygonHash); + + // Do not assign, so that they do not share same d_ptr + QGeoPolygon similarPolygon({ QGeoCoordinate(1, 1), QGeoCoordinate(2, 2), + QGeoCoordinate(3, 0) }); + QCOMPARE(qHash(similarPolygon), polygonHash); +} + QTEST_MAIN(tst_QGeoPolygon) #include "tst_qgeopolygon.moc" diff --git a/tests/auto/qgeorectangle/tst_qgeorectangle.cpp b/tests/auto/qgeorectangle/tst_qgeorectangle.cpp index 5163460c..696ac6b1 100644 --- a/tests/auto/qgeorectangle/tst_qgeorectangle.cpp +++ b/tests/auto/qgeorectangle/tst_qgeorectangle.cpp @@ -94,6 +94,8 @@ private slots: void circleComparison(); void circleComparison_data(); + + void hashing(); }; void tst_QGeoRectangle::default_constructor() @@ -2389,6 +2391,24 @@ void tst_QGeoRectangle::circleComparison() QCOMPARE((box != circle), !equal); } +void tst_QGeoRectangle::hashing() +{ + const QGeoRectangle rectangle(QGeoCoordinate(10.0, 0.0), QGeoCoordinate(0.0, 10.0)); + const size_t rectangleHash = qHash(rectangle); + + QGeoRectangle otherTopLeftRectangle = rectangle; + otherTopLeftRectangle.setTopLeft(QGeoCoordinate(20.0, 0.0)); + QVERIFY(qHash(otherTopLeftRectangle) != rectangleHash); + + QGeoRectangle otherBottomRightRectangle = rectangle; + otherBottomRightRectangle.setBottomRight(QGeoCoordinate(0.0, 5.0)); + QVERIFY(qHash(otherBottomRightRectangle) != rectangleHash); + + // Do not assign, so that they do not share same d_ptr + QGeoRectangle similarRectangle(QGeoCoordinate(10.0, 0.0), QGeoCoordinate(0.0, 10.0)); + QCOMPARE(qHash(similarRectangle), rectangleHash); +} + QTEST_MAIN(tst_QGeoRectangle) #include "tst_qgeorectangle.moc" diff --git a/tests/auto/qgeoshape/tst_qgeoshape.cpp b/tests/auto/qgeoshape/tst_qgeoshape.cpp index d1d10e3a..d7badb0f 100644 --- a/tests/auto/qgeoshape/tst_qgeoshape.cpp +++ b/tests/auto/qgeoshape/tst_qgeoshape.cpp @@ -58,6 +58,7 @@ private slots: void debug(); void conversions(); void serialization(); + void hashing(); }; void tst_qgeoshape::testArea() @@ -201,5 +202,42 @@ void tst_qgeoshape::serialization() } } +void tst_qgeoshape::hashing() +{ + const size_t defaultShapeHash = qHash(QGeoShape()); + + const QGeoCircle circle(QGeoCoordinate(1, 2), 10); + const QGeoShape circleShape = circle; + const size_t circleShapeHash = qHash(circleShape); + QVERIFY(defaultShapeHash != circleShapeHash); + QCOMPARE(qHash(circle), circleShapeHash); + + const QGeoRectangle rectangle(QGeoCoordinate(30, 160), QGeoCoordinate(-30, 170)); + const QGeoShape rectangleShape = rectangle; + const size_t rectangleShapeHash = qHash(rectangleShape); + QVERIFY(defaultShapeHash != rectangleShapeHash); + QVERIFY(circleShapeHash != rectangleShapeHash); + QCOMPARE(qHash(rectangle), rectangleShapeHash); + + const QGeoPolygon polygon({ QGeoCoordinate(30, 160), QGeoCoordinate(0, 170), + QGeoCoordinate(-30, 160) }); + const QGeoShape polygonShape = polygon; + const size_t polygonShapeHash = qHash(polygonShape); + QVERIFY(defaultShapeHash != polygonShapeHash); + QVERIFY(circleShapeHash != polygonShapeHash); + QVERIFY(rectangleShapeHash != polygonShapeHash); + QCOMPARE(qHash(polygon), polygonShapeHash); + + const QGeoPath path({ QGeoCoordinate(30, 160), QGeoCoordinate(0, 170), + QGeoCoordinate(-30, 180) }, 0.5); + const QGeoShape pathShape = path; + const size_t pathShapeHash = qHash(pathShape); + QVERIFY(defaultShapeHash != pathShapeHash); + QVERIFY(circleShapeHash != pathShapeHash); + QVERIFY(rectangleShapeHash != pathShapeHash); + QVERIFY(polygonShapeHash != pathShapeHash); + QCOMPARE(qHash(path), pathShapeHash); +} + QTEST_MAIN(tst_qgeoshape) #include "tst_qgeoshape.moc" |