Qt
Internal/Contributor docs for the Qt SDK. Note: These are NOT official API docs; those are found at https://doc.qt.io/
Loading...
Searching...
No Matches
qdeclarativegeomapitembase.cpp
Go to the documentation of this file.
1// Copyright (C) 2022 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3// Qt-Security score:significant reason:default
4
7
8#include <QtQml/QQmlInfo>
9#include <QtQuick/QSGOpacityNode>
10
11#include <QtQuick/private/qquickmousearea_p.h>
12#include <QtQuick/private/qquickitem_p.h>
13#include <QtPositioning/private/qdoublevector2d_p.h>
14#include <QtLocation/private/qgeomap_p.h>
15#include <QtLocation/private/qgeoprojection_p.h>
16
17#include <QtQuickShapes/private/qquickshape_p_p.h>
18
19QT_BEGIN_NAMESPACE
20
21QDeclarativeGeoMapItemBase::QDeclarativeGeoMapItemBase(QQuickItem *parent)
22 : QQuickItem(parent)
23{
24 connect(this, &QDeclarativeGeoMapItemBase::childrenChanged,
25 this, &QDeclarativeGeoMapItemBase::afterChildrenChanged);
26 // Changing opacity on a mapItemGroup should affect also the opacity on the children.
27 // This must be notified to plugins, if they are to render the item.
28 connect(this, &QQuickItem::opacityChanged, this, &QDeclarativeGeoMapItemBase::mapItemOpacityChanged);
29}
30
31QDeclarativeGeoMapItemBase::~QDeclarativeGeoMapItemBase()
32{
33 disconnect(this, &QDeclarativeGeoMapItemBase::childrenChanged,
34 this, &QDeclarativeGeoMapItemBase::afterChildrenChanged);
35 if (quickMap_)
36 quickMap_->removeMapItem(this);
37}
38
39/*!
40 \internal
41*/
42void QDeclarativeGeoMapItemBase::afterChildrenChanged()
43{
44 const QList<QQuickItem *> kids = childItems();
45 if (kids.size() > 0) {
46 bool printedWarning = false;
47 for (auto *i : kids) {
48 if (i->flags() & QQuickItem::ItemHasContents
49 && !qobject_cast<QQuickMouseArea *>(i)
50 && i->objectName() != QStringLiteral("_qt_map_item_shape"))
51 {
52 if (!printedWarning) {
53 qmlWarning(this) << "Geographic map items do not support child items";
54 printedWarning = true;
55 }
56
57 qmlWarning(i) << "deleting this child";
58 i->deleteLater();
59 }
60 }
61 }
62}
63
64/*!
65 \internal
66*/
67void QDeclarativeGeoMapItemBase::setMap(QDeclarativeGeoMap *quickMap, QGeoMap *map)
68{
69 if (quickMap == quickMap_)
70 return;
71 if (quickMap && quickMap_)
72 return; // don't allow association to more than one map
73
74 quickMap_ = quickMap;
75 map_ = map;
76
77 if (map_ && quickMap_) {
78 // For performance reasons we're not connecting map_'s and quickMap_'s signals to this.
79 // Rather, the handling of cameraDataChanged, visibleAreaChanged, heightChanged and widthChanged is done explicitly in QDeclarativeGeoMap by directly calling methods on the items.
80 // See QTBUG-76950
81 lastMapSize_ = QSizeF(quickMap_->width(), quickMap_->height());
82 lastCameraData_ = map_->cameraData();
83 }
84}
85
86/*!
87 \internal
88*/
89void QDeclarativeGeoMapItemBase::baseCameraDataChanged(const QGeoCameraData &cameraData)
90{
91 QGeoMapViewportChangeEvent evt;
92 evt.cameraData = cameraData;
93 evt.mapSize = QSizeF(quickMap_->width(), quickMap_->height());
94
95 if (evt.mapSize != lastMapSize_)
96 evt.mapSizeChanged = true;
97
98 if (cameraData.bearing() != lastCameraData_.bearing())
99 evt.bearingChanged = true;
100 if (cameraData.center() != lastCameraData_.center())
101 evt.centerChanged = true;
102 if (cameraData.roll() != lastCameraData_.roll())
103 evt.rollChanged = true;
104 if (cameraData.tilt() != lastCameraData_.tilt())
105 evt.tiltChanged = true;
106 if (cameraData.zoomLevel() != lastCameraData_.zoomLevel())
107 evt.zoomLevelChanged = true;
108
109 lastMapSize_ = evt.mapSize;
110 lastCameraData_ = cameraData;
111
112 afterViewportChanged(evt);
113}
114
115void QDeclarativeGeoMapItemBase::visibleAreaChanged()
116{
117 QGeoMapViewportChangeEvent evt;
118 evt.mapSize = QSizeF(quickMap_->width(), quickMap_->height());
119 afterViewportChanged(evt);
120}
121
122/*!
123 \internal
124*/
125void QDeclarativeGeoMapItemBase::setPositionOnMap(const QGeoCoordinate &coordinate, const QPointF &offset)
126{
127 if (!map_ || !quickMap_)
128 return;
129
130 QDoubleVector2D pos;
131 if (map()->geoProjection().projectionType() == QGeoProjection::ProjectionWebMercator) {
132 const QGeoProjectionWebMercator &p = static_cast<const QGeoProjectionWebMercator&>(map()->geoProjection());
133 QDoubleVector2D wrappedProjection = p.geoToWrappedMapProjection(coordinate);
134 if (!p.isProjectable(wrappedProjection))
135 return;
136 pos = p.wrappedMapProjectionToItemPosition(wrappedProjection);
137 } else {
138 pos = map()->geoProjection().coordinateToItemPosition(coordinate, false);
139 if (qIsNaN(pos.x()))
140 return;
141 }
142
143 QPointF topLeft = pos.toPointF() - offset;
144
145 setPosition(topLeft);
146}
147
148bool QDeclarativeGeoMapItemBase::autoFadeIn() const
149{
150 return m_autoFadeIn;
151}
152
153static const double opacityRampMin = 1.5;
154static const double opacityRampMax = 2.5;
155
156void QDeclarativeGeoMapItemBase::setAutoFadeIn(bool fadeIn)
157{
158 if (fadeIn == m_autoFadeIn)
159 return;
160 m_autoFadeIn = fadeIn;
161 if (quickMap_ && quickMap_->zoomLevel() < opacityRampMax)
162 polishAndUpdate();
163}
164
165QLocation::ReferenceSurface QDeclarativeGeoMapItemBase::referenceSurface() const
166{
167 return m_referenceSurface;
168}
169
170void QDeclarativeGeoMapItemBase::setReferenceSurface(QLocation::ReferenceSurface referenceSurface)
171{
172 if (referenceSurface == m_referenceSurface)
173 return;
174 m_referenceSurface = referenceSurface;
175 emit referenceSurfaceChanged();
176 updatePolish();
177}
178
179int QDeclarativeGeoMapItemBase::lodThreshold() const
180{
181 return m_lodThreshold;
182}
183
184void QDeclarativeGeoMapItemBase::setLodThreshold(int lt)
185{
186 if (lt == m_lodThreshold)
187 return;
188 m_lodThreshold = lt;
189 update();
190}
191
192/*!
193 \internal
194
195 This returns the zoom level to be used when requesting the LOD.
196 Essentially it clamps to m_lodThreshold, and if above, it selects
197 a ZL higher than the maximum LODable level.
198*/
199unsigned int QDeclarativeGeoMapItemBase::zoomForLOD(int zoom) const
200{
201 if (zoom >= m_lodThreshold)
202 return 30; // some arbitrarily large zoom
203 return uint(zoom);
204}
205
206/*!
207 \internal
208*/
209float QDeclarativeGeoMapItemBase::zoomLevelOpacity() const
210{
211 if (!m_autoFadeIn) // Consider skipping the opacity node instead.
212 return 1.0;
213 else if (quickMap_->zoomLevel() > opacityRampMax)
214 return 1.0;
215 else if (quickMap_->zoomLevel() > opacityRampMin)
216 return quickMap_->zoomLevel() - opacityRampMin;
217 else
218 return 0.0;
219}
220
221void QDeclarativeGeoMapItemBase::setShapeTriangulationScale(QQuickShape *shape, qreal maxCoord) const
222{
223 const qreal zoom = qMax(0.01, quickMap_->zoomLevel());
224 qreal scale = 1 / zoom;
225
226 // cater also for QTriangulator's 65536 coordinate limit due to the fixed point math
227 qint64 coord = qint64(maxCoord);
228 const qint64 COORD_LIMIT = (1 << 21) / 32; // 65536 (where 32 is Q_FIXED_POINT_SCALE)
229 while (coord > COORD_LIMIT) {
230 coord /= COORD_LIMIT;
231 scale /= COORD_LIMIT;
232 }
233
234 QQuickShapePrivate::get(shape)->triangulationScale = scale;
235}
236
237/*!
238 \internal
239*/
240QSGNode *QDeclarativeGeoMapItemBase::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *pd)
241{
242 if (!map_ || !quickMap_ || map_->supportedMapItemTypes() & itemType()) {
243 if (oldNode)
244 delete oldNode;
245 oldNode = nullptr;
246 return nullptr;
247 }
248
249 QSGOpacityNode *opn = static_cast<QSGOpacityNode *>(oldNode);
250 if (!opn)
251 opn = new QSGOpacityNode();
252
253 opn->setOpacity(zoomLevelOpacity());
254
255 QSGNode *oldN = opn->childCount() ? opn->firstChild() : 0;
256 opn->removeAllChildNodes();
257 if (opn->opacity() > 0.0) {
258 QSGNode *n = this->updateMapItemPaintNode(oldN, pd);
259 if (n)
260 opn->appendChildNode(n);
261 } else {
262 delete oldN;
263 }
264
265 return opn;
266}
267
268/*!
269 \internal
270*/
271QSGNode *QDeclarativeGeoMapItemBase::updateMapItemPaintNode(QSGNode *oldNode, UpdatePaintNodeData *)
272{
273 delete oldNode;
274 return nullptr;
275}
276
277/*!
278 \internal
279
280 The actual combined opacity of the item. Needed by custom renderer to look like
281 the scene-graph one.
282*/
283qreal QDeclarativeGeoMapItemBase::mapItemOpacity() const
284{
285 if (parentGroup_)
286 return parentGroup_->mapItemOpacity() * opacity();
287 return opacity();
288}
289
290void QDeclarativeGeoMapItemBase::setParentGroup(QDeclarativeGeoMapItemGroup &parentGroup)
291{
292 parentGroup_ = &parentGroup;
293 if (parentGroup_) {
294 connect(parentGroup_, &QDeclarativeGeoMapItemGroup::mapItemOpacityChanged,
295 this, &QDeclarativeGeoMapItemBase::mapItemOpacityChanged);
296 }
297}
298
299bool QDeclarativeGeoMapItemBase::isPolishScheduled() const
300{
301 return QQuickItemPrivate::get(this)->polishScheduled;
302}
303
304void QDeclarativeGeoMapItemBase::polishAndUpdate()
305{
306 polish();
307 update();
308}
309
310QT_END_NAMESPACE
static const double opacityRampMin
static const double opacityRampMax