summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIvan Solovev <ivan.solovev@qt.io>2021-07-26 15:19:56 +0200
committerQt Cherry-pick Bot <cherrypick_bot@qt-project.org>2021-07-27 15:04:52 +0000
commit31865920e3fe4122403ceadb7178dc226034feb3 (patch)
treee2fb30d1f1c31e0cdfa5a087683ae01300b48a9a
parent2a5f7d270b58a7ec0ada33df62e4dc64afd3becd (diff)
downloadqtlocation-31865920e3fe4122403ceadb7178dc226034feb3.tar.gz
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.cpp5
-rw-r--r--src/positioning/qgeocircle_p.h2
-rw-r--r--src/positioning/qgeopath.cpp6
-rw-r--r--src/positioning/qgeopath_p.h1
-rw-r--r--src/positioning/qgeopolygon.cpp7
-rw-r--r--src/positioning/qgeopolygon_p.h1
-rw-r--r--src/positioning/qgeorectangle.cpp5
-rw-r--r--src/positioning/qgeorectangle_p.h2
-rw-r--r--src/positioning/qgeoshape.cpp15
-rw-r--r--src/positioning/qgeoshape.h3
-rw-r--r--src/positioning/qgeoshape_p.h2
-rw-r--r--tests/auto/qgeocircle/tst_qgeocircle.cpp20
-rw-r--r--tests/auto/qgeopath/tst_qgeopath.cpp20
-rw-r--r--tests/auto/qgeopolygon/tst_qgeopolygon.cpp23
-rw-r--r--tests/auto/qgeorectangle/tst_qgeorectangle.cpp20
-rw-r--r--tests/auto/qgeoshape/tst_qgeoshape.cpp38
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"