1/****************************************************************************
2**
3** Copyright (C) 2017 Mapbox, Inc.
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#include "qmapboxglstylechange_p.h"
38
39#include <QtCore/QDebug>
40#include <QtCore/QMetaProperty>
41#include <QtCore/QRegularExpression>
42#include <QtCore/QStringList>
43#include <QtPositioning/QGeoPath>
44#include <QtPositioning/QGeoPolygon>
45#include <QtQml/QJSValue>
46#include <QtLocation/private/qdeclarativecirclemapitem_p_p.h>
47
48namespace {
49
50QByteArray formatPropertyName(const QByteArray &name)
51{
52 QString nameAsString = QString::fromLatin1(str: name);
53 static const QRegularExpression camelCaseRegex(QStringLiteral("([a-z0-9])([A-Z])"));
54 return nameAsString.replace(re: camelCaseRegex, QStringLiteral("\\1-\\2")).toLower().toLatin1();
55}
56
57bool isImmutableProperty(const QByteArray &name)
58{
59 return name == QStringLiteral("type") || name == QStringLiteral("layer");
60}
61
62QString getId(QDeclarativeGeoMapItemBase *mapItem)
63{
64 return QStringLiteral("QtLocation-") +
65 ((mapItem->objectName().isEmpty()) ? QString::number(quint64(mapItem)) : mapItem->objectName());
66}
67
68// Mapbox GL supports geometry segments that spans above 180 degrees in
69// longitude. To keep visual expectations in parity with Qt, we need to adapt
70// the coordinates to always use the shortest path when in ambiguity.
71static bool geoRectangleCrossesDateLine(const QGeoRectangle &rect) {
72 return rect.topLeft().longitude() > rect.bottomRight().longitude();
73}
74
75QMapbox::Feature featureFromMapRectangle(QDeclarativeRectangleMapItem *mapItem)
76{
77 const QGeoRectangle *rect = static_cast<const QGeoRectangle *>(&mapItem->geoShape());
78 QMapbox::Coordinate bottomLeft { rect->bottomLeft().latitude(), rect->bottomLeft().longitude() };
79 QMapbox::Coordinate topLeft { rect->topLeft().latitude(), rect->topLeft().longitude() };
80 QMapbox::Coordinate bottomRight { rect->bottomRight().latitude(), rect->bottomRight().longitude() };
81 QMapbox::Coordinate topRight { rect->topRight().latitude(), rect->topRight().longitude() };
82 if (geoRectangleCrossesDateLine(rect: *rect)) {
83 bottomRight.second += 360.0;
84 topRight.second += 360.0;
85 }
86 QMapbox::CoordinatesCollections geometry { { { bottomLeft, bottomRight, topRight, topLeft, bottomLeft } } };
87
88 return QMapbox::Feature(QMapbox::Feature::PolygonType, geometry, {}, getId(mapItem));
89}
90
91QMapbox::Feature featureFromMapCircle(QDeclarativeCircleMapItem *mapItem)
92{
93 static const int circleSamples = 128;
94 const QGeoProjectionWebMercator &p = static_cast<const QGeoProjectionWebMercator&>(mapItem->map()->geoProjection());
95 QList<QGeoCoordinate> path;
96 QGeoCoordinate leftBound;
97 QDeclarativeCircleMapItemPrivateCPU::calculatePeripheralPoints(path, center: mapItem->center(), distance: mapItem->radius(), steps: circleSamples, leftBound);
98 QList<QDoubleVector2D> pathProjected;
99 for (const QGeoCoordinate &c : qAsConst(t&: path))
100 pathProjected << p.geoToMapProjection(coordinate: c);
101 if (QDeclarativeCircleMapItemPrivateCPU::crossEarthPole(center: mapItem->center(), distance: mapItem->radius()))
102 QDeclarativeCircleMapItemPrivateCPU::preserveCircleGeometry(path&: pathProjected, center: mapItem->center(), distance: mapItem->radius(), p);
103 path.clear();
104 for (const QDoubleVector2D &c : qAsConst(t&: pathProjected))
105 path << p.mapProjectionToGeo(projection: c);
106
107
108 QMapbox::Coordinates coordinates;
109 for (const QGeoCoordinate &coordinate : path) {
110 coordinates << QMapbox::Coordinate { coordinate.latitude(), coordinate.longitude() };
111 }
112 coordinates.append(t: coordinates.first()); // closing the path
113 QMapbox::CoordinatesCollections geometry { { coordinates } };
114 return QMapbox::Feature(QMapbox::Feature::PolygonType, geometry, {}, getId(mapItem));
115}
116
117static QMapbox::Coordinates qgeocoordinate2mapboxcoordinate(const QList<QGeoCoordinate> &crds, const bool crossesDateline, bool closed = false)
118{
119 QMapbox::Coordinates coordinates;
120 for (const QGeoCoordinate &coordinate : crds) {
121 if (!coordinates.empty() && crossesDateline && qAbs(t: coordinate.longitude() - coordinates.last().second) > 180.0) {
122 coordinates << QMapbox::Coordinate { coordinate.latitude(), coordinate.longitude() + (coordinate.longitude() >= 0 ? -360.0 : 360.0) };
123 } else {
124 coordinates << QMapbox::Coordinate { coordinate.latitude(), coordinate.longitude() };
125 }
126 }
127 if (closed && !coordinates.empty() && coordinates.last() != coordinates.first())
128 coordinates.append(t: coordinates.first()); // closing the path
129 return coordinates;
130}
131
132QMapbox::Feature featureFromMapPolygon(QDeclarativePolygonMapItem *mapItem)
133{
134 const QGeoPolygon *polygon = static_cast<const QGeoPolygon *>(&mapItem->geoShape());
135 const bool crossesDateline = geoRectangleCrossesDateLine(rect: polygon->boundingGeoRectangle());
136 QMapbox::CoordinatesCollections geometry;
137 QMapbox::CoordinatesCollection poly;
138 QMapbox::Coordinates coordinates = qgeocoordinate2mapboxcoordinate(crds: polygon->path(), crossesDateline, closed: true);
139 poly.push_back(t: coordinates);
140 for (int i = 0; i < polygon->holesCount(); ++i) {
141 coordinates = qgeocoordinate2mapboxcoordinate(crds: polygon->holePath(index: i), crossesDateline, closed: true);
142 poly.push_back(t: coordinates);
143 }
144
145 geometry.push_back(t: poly);
146 return QMapbox::Feature(QMapbox::Feature::PolygonType, geometry, {}, getId(mapItem));
147}
148
149QMapbox::Feature featureFromMapPolyline(QDeclarativePolylineMapItem *mapItem)
150{
151 const QGeoPath *path = static_cast<const QGeoPath *>(&mapItem->geoShape());
152 QMapbox::Coordinates coordinates;
153 const bool crossesDateline = geoRectangleCrossesDateLine(rect: path->boundingGeoRectangle());
154 for (const QGeoCoordinate &coordinate : path->path()) {
155 if (!coordinates.empty() && crossesDateline && qAbs(t: coordinate.longitude() - coordinates.last().second) > 180.0) {
156 coordinates << QMapbox::Coordinate { coordinate.latitude(), coordinate.longitude() + (coordinate.longitude() >= 0 ? -360.0 : 360.0) };
157 } else {
158 coordinates << QMapbox::Coordinate { coordinate.latitude(), coordinate.longitude() };
159 }
160 }
161 QMapbox::CoordinatesCollections geometry { { coordinates } };
162
163 return QMapbox::Feature(QMapbox::Feature::LineStringType, geometry, {}, getId(mapItem));
164}
165
166QMapbox::Feature featureFromMapItem(QDeclarativeGeoMapItemBase *item)
167{
168 switch (item->itemType()) {
169 case QGeoMap::MapRectangle:
170 return featureFromMapRectangle(mapItem: static_cast<QDeclarativeRectangleMapItem *>(item));
171 case QGeoMap::MapCircle:
172 return featureFromMapCircle(mapItem: static_cast<QDeclarativeCircleMapItem *>(item));
173 case QGeoMap::MapPolygon:
174 return featureFromMapPolygon(mapItem: static_cast<QDeclarativePolygonMapItem *>(item));
175 case QGeoMap::MapPolyline:
176 return featureFromMapPolyline(mapItem: static_cast<QDeclarativePolylineMapItem *>(item));
177 default:
178 qWarning() << "Unsupported QGeoMap item type: " << item->itemType();
179 return QMapbox::Feature();
180 }
181}
182
183QList<QByteArray> getAllPropertyNamesList(QObject *object)
184{
185 const QMetaObject *metaObject = object->metaObject();
186 QList<QByteArray> propertyNames(object->dynamicPropertyNames());
187 for (int i = metaObject->propertyOffset(); i < metaObject->propertyCount(); ++i) {
188 propertyNames.append(t: metaObject->property(index: i).name());
189 }
190 return propertyNames;
191}
192
193} // namespace
194
195
196// QMapboxGLStyleChange
197
198QList<QSharedPointer<QMapboxGLStyleChange>> QMapboxGLStyleChange::addMapParameter(QGeoMapParameter *param)
199{
200 static const QStringList acceptedParameterTypes = QStringList()
201 << QStringLiteral("paint") << QStringLiteral("layout") << QStringLiteral("filter")
202 << QStringLiteral("layer") << QStringLiteral("source") << QStringLiteral("image");
203
204 QList<QSharedPointer<QMapboxGLStyleChange>> changes;
205
206 switch (acceptedParameterTypes.indexOf(t: param->type())) {
207 case -1:
208 qWarning() << "Invalid value for property 'type': " + param->type();
209 break;
210 case 0: // paint
211 changes << QMapboxGLStyleSetPaintProperty::fromMapParameter(param);
212 break;
213 case 1: // layout
214 changes << QMapboxGLStyleSetLayoutProperty::fromMapParameter(param);
215 break;
216 case 2: // filter
217 changes << QMapboxGLStyleSetFilter::fromMapParameter(param);
218 break;
219 case 3: // layer
220 changes << QMapboxGLStyleAddLayer::fromMapParameter(param);
221 break;
222 case 4: // source
223 changes << QMapboxGLStyleAddSource::fromMapParameter(param);
224 break;
225 case 5: // image
226 changes << QMapboxGLStyleAddImage::fromMapParameter(param);
227 break;
228 }
229
230 return changes;
231}
232
233QList<QSharedPointer<QMapboxGLStyleChange>> QMapboxGLStyleChange::addMapItem(QDeclarativeGeoMapItemBase *item, const QString &before)
234{
235 QList<QSharedPointer<QMapboxGLStyleChange>> changes;
236
237 switch (item->itemType()) {
238 case QGeoMap::MapRectangle:
239 case QGeoMap::MapCircle:
240 case QGeoMap::MapPolygon:
241 case QGeoMap::MapPolyline:
242 break;
243 default:
244 qWarning() << "Unsupported QGeoMap item type: " << item->itemType();
245 return changes;
246 }
247
248 QMapbox::Feature feature = featureFromMapItem(item);
249
250 changes << QMapboxGLStyleAddLayer::fromFeature(feature, before);
251 changes << QMapboxGLStyleAddSource::fromFeature(feature);
252 changes << QMapboxGLStyleSetPaintProperty::fromMapItem(item);
253 changes << QMapboxGLStyleSetLayoutProperty::fromMapItem(item);
254
255 return changes;
256}
257
258QList<QSharedPointer<QMapboxGLStyleChange>> QMapboxGLStyleChange::removeMapParameter(QGeoMapParameter *param)
259{
260 static const QStringList acceptedParameterTypes = QStringList()
261 << QStringLiteral("paint") << QStringLiteral("layout") << QStringLiteral("filter")
262 << QStringLiteral("layer") << QStringLiteral("source") << QStringLiteral("image");
263
264 QList<QSharedPointer<QMapboxGLStyleChange>> changes;
265
266 switch (acceptedParameterTypes.indexOf(t: param->type())) {
267 case -1:
268 qWarning() << "Invalid value for property 'type': " + param->type();
269 break;
270 case 0: // paint
271 case 1: // layout
272 case 2: // filter
273 break;
274 case 3: // layer
275 changes << QSharedPointer<QMapboxGLStyleChange>(new QMapboxGLStyleRemoveLayer(param->property(name: "name").toString()));
276 break;
277 case 4: // source
278 changes << QSharedPointer<QMapboxGLStyleChange>(new QMapboxGLStyleRemoveSource(param->property(name: "name").toString()));
279 break;
280 case 5: // image
281 break;
282 }
283
284 return changes;
285}
286
287QList<QSharedPointer<QMapboxGLStyleChange>> QMapboxGLStyleChange::removeMapItem(QDeclarativeGeoMapItemBase *item)
288{
289 QList<QSharedPointer<QMapboxGLStyleChange>> changes;
290
291 const QString id = getId(mapItem: item);
292
293 changes << QSharedPointer<QMapboxGLStyleChange>(new QMapboxGLStyleRemoveLayer(id));
294 changes << QSharedPointer<QMapboxGLStyleChange>(new QMapboxGLStyleRemoveSource(id));
295
296 return changes;
297}
298
299// QMapboxGLStyleSetLayoutProperty
300
301void QMapboxGLStyleSetLayoutProperty::apply(QMapboxGL *map)
302{
303 map->setLayoutProperty(layer: m_layer, property: m_property, value: m_value);
304}
305
306QList<QSharedPointer<QMapboxGLStyleChange>> QMapboxGLStyleSetLayoutProperty::fromMapParameter(QGeoMapParameter *param)
307{
308 Q_ASSERT(param->type() == "layout");
309
310 QList<QSharedPointer<QMapboxGLStyleChange>> changes;
311
312 QList<QByteArray> propertyNames = getAllPropertyNamesList(object: param);
313 for (const QByteArray &propertyName : propertyNames) {
314 if (isImmutableProperty(name: propertyName))
315 continue;
316
317 auto layout = new QMapboxGLStyleSetLayoutProperty();
318
319 layout->m_value = param->property(name: propertyName);
320 if (layout->m_value.canConvert<QJSValue>()) {
321 layout->m_value = layout->m_value.value<QJSValue>().toVariant();
322 }
323
324 layout->m_layer = param->property(name: "layer").toString();
325 layout->m_property = formatPropertyName(name: propertyName);
326
327 changes << QSharedPointer<QMapboxGLStyleChange>(layout);
328 }
329
330 return changes;
331}
332
333QList<QSharedPointer<QMapboxGLStyleChange>> QMapboxGLStyleSetLayoutProperty::fromMapItem(QDeclarativeGeoMapItemBase *item)
334{
335 QList<QSharedPointer<QMapboxGLStyleChange>> changes;
336
337 switch (item->itemType()) {
338 case QGeoMap::MapPolyline:
339 changes = fromMapItem(static_cast<QDeclarativePolylineMapItem *>(item));
340 default:
341 break;
342 }
343
344 changes << QSharedPointer<QMapboxGLStyleChange>(
345 new QMapboxGLStyleSetLayoutProperty(getId(mapItem: item), QStringLiteral("visibility"),
346 item->isVisible() ? QStringLiteral("visible") : QStringLiteral("none")));
347
348 return changes;
349}
350
351QList<QSharedPointer<QMapboxGLStyleChange>> QMapboxGLStyleSetLayoutProperty::fromMapItem(QDeclarativePolylineMapItem *item)
352{
353 QList<QSharedPointer<QMapboxGLStyleChange>> changes;
354 changes.reserve(alloc: 2);
355
356 const QString id = getId(mapItem: item);
357
358 changes << QSharedPointer<QMapboxGLStyleChange>(
359 new QMapboxGLStyleSetLayoutProperty(id, QStringLiteral("line-cap"), QStringLiteral("square")));
360 changes << QSharedPointer<QMapboxGLStyleChange>(
361 new QMapboxGLStyleSetLayoutProperty(id, QStringLiteral("line-join"), QStringLiteral("bevel")));
362
363 return changes;
364}
365
366QMapboxGLStyleSetLayoutProperty::QMapboxGLStyleSetLayoutProperty(const QString& layer, const QString& property, const QVariant &value)
367 : m_layer(layer), m_property(property), m_value(value)
368{
369}
370
371// QMapboxGLStyleSetPaintProperty
372
373QMapboxGLStyleSetPaintProperty::QMapboxGLStyleSetPaintProperty(const QString& layer, const QString& property, const QVariant &value)
374 : m_layer(layer), m_property(property), m_value(value)
375{
376}
377
378void QMapboxGLStyleSetPaintProperty::apply(QMapboxGL *map)
379{
380 map->setPaintProperty(layer: m_layer, property: m_property, value: m_value);
381}
382
383QList<QSharedPointer<QMapboxGLStyleChange>> QMapboxGLStyleSetPaintProperty::fromMapParameter(QGeoMapParameter *param)
384{
385 Q_ASSERT(param->type() == "paint");
386
387 QList<QSharedPointer<QMapboxGLStyleChange>> changes;
388
389 QList<QByteArray> propertyNames = getAllPropertyNamesList(object: param);
390 for (const QByteArray &propertyName : propertyNames) {
391 if (isImmutableProperty(name: propertyName))
392 continue;
393
394 auto paint = new QMapboxGLStyleSetPaintProperty();
395
396 paint->m_value = param->property(name: propertyName);
397 if (paint->m_value.canConvert<QJSValue>()) {
398 paint->m_value = paint->m_value.value<QJSValue>().toVariant();
399 }
400
401 paint->m_layer = param->property(name: "layer").toString();
402 paint->m_property = formatPropertyName(name: propertyName);
403
404 changes << QSharedPointer<QMapboxGLStyleChange>(paint);
405 }
406
407 return changes;
408}
409
410QList<QSharedPointer<QMapboxGLStyleChange>> QMapboxGLStyleSetPaintProperty::fromMapItem(QDeclarativeGeoMapItemBase *item)
411{
412 switch (item->itemType()) {
413 case QGeoMap::MapRectangle:
414 return fromMapItem(static_cast<QDeclarativeRectangleMapItem *>(item));
415 case QGeoMap::MapCircle:
416 return fromMapItem(static_cast<QDeclarativeCircleMapItem *>(item));
417 case QGeoMap::MapPolygon:
418 return fromMapItem(static_cast<QDeclarativePolygonMapItem *>(item));
419 case QGeoMap::MapPolyline:
420 return fromMapItem(static_cast<QDeclarativePolylineMapItem *>(item));
421 default:
422 qWarning() << "Unsupported QGeoMap item type: " << item->itemType();
423 return QList<QSharedPointer<QMapboxGLStyleChange>>();
424 }
425}
426
427QList<QSharedPointer<QMapboxGLStyleChange>> QMapboxGLStyleSetPaintProperty::fromMapItem(QDeclarativeRectangleMapItem *item)
428{
429 QList<QSharedPointer<QMapboxGLStyleChange>> changes;
430 changes.reserve(alloc: 3);
431
432 const QString id = getId(mapItem: item);
433
434 changes << QSharedPointer<QMapboxGLStyleChange>(
435 new QMapboxGLStyleSetPaintProperty(id, QStringLiteral("fill-opacity"), item->color().alphaF() * item->mapItemOpacity()));
436 changes << QSharedPointer<QMapboxGLStyleChange>(
437 new QMapboxGLStyleSetPaintProperty(id, QStringLiteral("fill-color"), item->color()));
438 changes << QSharedPointer<QMapboxGLStyleChange>(
439 new QMapboxGLStyleSetPaintProperty(id, QStringLiteral("fill-outline-color"), item->border()->color()));
440
441 return changes;
442}
443
444QList<QSharedPointer<QMapboxGLStyleChange>> QMapboxGLStyleSetPaintProperty::fromMapItem(QDeclarativeCircleMapItem *item)
445{
446 QList<QSharedPointer<QMapboxGLStyleChange>> changes;
447 changes.reserve(alloc: 3);
448
449 const QString id = getId(mapItem: item);
450
451 changes << QSharedPointer<QMapboxGLStyleChange>(
452 new QMapboxGLStyleSetPaintProperty(id, QStringLiteral("fill-opacity"), item->color().alphaF() * item->mapItemOpacity()));
453 changes << QSharedPointer<QMapboxGLStyleChange>(
454 new QMapboxGLStyleSetPaintProperty(id, QStringLiteral("fill-color"), item->color()));
455 changes << QSharedPointer<QMapboxGLStyleChange>(
456 new QMapboxGLStyleSetPaintProperty(id, QStringLiteral("fill-outline-color"), item->border()->color()));
457
458 return changes;
459}
460
461QList<QSharedPointer<QMapboxGLStyleChange>> QMapboxGLStyleSetPaintProperty::fromMapItem(QDeclarativePolygonMapItem *item)
462{
463 QList<QSharedPointer<QMapboxGLStyleChange>> changes;
464 changes.reserve(alloc: 3);
465
466 const QString id = getId(mapItem: item);
467
468 changes << QSharedPointer<QMapboxGLStyleChange>(
469 new QMapboxGLStyleSetPaintProperty(id, QStringLiteral("fill-opacity"), item->color().alphaF() * item->mapItemOpacity()));
470 changes << QSharedPointer<QMapboxGLStyleChange>(
471 new QMapboxGLStyleSetPaintProperty(id, QStringLiteral("fill-color"), item->color()));
472 changes << QSharedPointer<QMapboxGLStyleChange>(
473 new QMapboxGLStyleSetPaintProperty(id, QStringLiteral("fill-outline-color"), item->border()->color()));
474
475 return changes;
476}
477
478QList<QSharedPointer<QMapboxGLStyleChange>> QMapboxGLStyleSetPaintProperty::fromMapItem(QDeclarativePolylineMapItem *item)
479{
480 QList<QSharedPointer<QMapboxGLStyleChange>> changes;
481 changes.reserve(alloc: 3);
482
483 const QString id = getId(mapItem: item);
484
485 changes << QSharedPointer<QMapboxGLStyleChange>(
486 new QMapboxGLStyleSetPaintProperty(id, QStringLiteral("line-opacity"), item->line()->color().alphaF() * item->mapItemOpacity()));
487 changes << QSharedPointer<QMapboxGLStyleChange>(
488 new QMapboxGLStyleSetPaintProperty(id, QStringLiteral("line-color"), item->line()->color()));
489 changes << QSharedPointer<QMapboxGLStyleChange>(
490 new QMapboxGLStyleSetPaintProperty(id, QStringLiteral("line-width"), item->line()->width()));
491
492 return changes;
493}
494
495// QMapboxGLStyleAddLayer
496
497void QMapboxGLStyleAddLayer::apply(QMapboxGL *map)
498{
499 map->addLayer(params: m_params, before: m_before);
500}
501
502QSharedPointer<QMapboxGLStyleChange> QMapboxGLStyleAddLayer::fromMapParameter(QGeoMapParameter *param)
503{
504 Q_ASSERT(param->type() == "layer");
505
506 auto layer = new QMapboxGLStyleAddLayer();
507
508 static const QStringList layerProperties = QStringList()
509 << QStringLiteral("name") << QStringLiteral("layerType") << QStringLiteral("before");
510
511 QList<QByteArray> propertyNames = getAllPropertyNamesList(object: param);
512 for (const QByteArray &propertyName : propertyNames) {
513 if (isImmutableProperty(name: propertyName))
514 continue;
515
516 const QVariant value = param->property(name: propertyName);
517
518 switch (layerProperties.indexOf(t: propertyName)) {
519 case -1:
520 layer->m_params[formatPropertyName(name: propertyName)] = value;
521 break;
522 case 0: // name
523 layer->m_params[QStringLiteral("id")] = value;
524 break;
525 case 1: // layerType
526 layer->m_params[QStringLiteral("type")] = value;
527 break;
528 case 2: // before
529 layer->m_before = value.toString();
530 break;
531 }
532 }
533
534 return QSharedPointer<QMapboxGLStyleChange>(layer);
535}
536
537QSharedPointer<QMapboxGLStyleChange> QMapboxGLStyleAddLayer::fromFeature(const QMapbox::Feature &feature, const QString &before)
538{
539 auto layer = new QMapboxGLStyleAddLayer();
540 layer->m_params[QStringLiteral("id")] = feature.id;
541 layer->m_params[QStringLiteral("source")] = feature.id;
542
543 switch (feature.type) {
544 case QMapbox::Feature::PointType:
545 layer->m_params[QStringLiteral("type")] = QStringLiteral("circle");
546 break;
547 case QMapbox::Feature::LineStringType:
548 layer->m_params[QStringLiteral("type")] = QStringLiteral("line");
549 break;
550 case QMapbox::Feature::PolygonType:
551 layer->m_params[QStringLiteral("type")] = QStringLiteral("fill");
552 break;
553 }
554
555 layer->m_before = before;
556
557 return QSharedPointer<QMapboxGLStyleChange>(layer);
558}
559
560
561// QMapboxGLStyleRemoveLayer
562
563void QMapboxGLStyleRemoveLayer::apply(QMapboxGL *map)
564{
565 map->removeLayer(id: m_id);
566}
567
568QMapboxGLStyleRemoveLayer::QMapboxGLStyleRemoveLayer(const QString &id) : m_id(id)
569{
570}
571
572
573// QMapboxGLStyleAddSource
574
575void QMapboxGLStyleAddSource::apply(QMapboxGL *map)
576{
577 map->updateSource(sourceID: m_id, params: m_params);
578}
579
580QSharedPointer<QMapboxGLStyleChange> QMapboxGLStyleAddSource::fromMapParameter(QGeoMapParameter *param)
581{
582 Q_ASSERT(param->type() == "source");
583
584 static const QStringList acceptedSourceTypes = QStringList()
585 << QStringLiteral("vector") << QStringLiteral("raster") << QStringLiteral("raster-dem") << QStringLiteral("geojson") << QStringLiteral("image");
586
587 QString sourceType = param->property(name: "sourceType").toString();
588
589 auto source = new QMapboxGLStyleAddSource();
590 source->m_id = param->property(name: "name").toString();
591 source->m_params[QStringLiteral("type")] = sourceType;
592
593 switch (acceptedSourceTypes.indexOf(t: sourceType)) {
594 case -1:
595 qWarning() << "Invalid value for property 'sourceType': " + sourceType;
596 break;
597 case 0: // vector
598 case 1: // raster
599 case 2: // raster-dem
600 source->m_params[QStringLiteral("url")] = param->property(name: "url");
601 break;
602 case 3: { // geojson
603 auto data = param->property(name: "data").toString();
604 if (data.startsWith(c: ':')) {
605 QFile geojson(data);
606 geojson.open(flags: QIODevice::ReadOnly);
607 source->m_params[QStringLiteral("data")] = geojson.readAll();
608 } else {
609 source->m_params[QStringLiteral("data")] = data.toUtf8();
610 }
611 } break;
612 case 4: { // image
613 source->m_params[QStringLiteral("url")] = param->property(name: "url");
614 source->m_params[QStringLiteral("coordinates")] = param->property(name: "coordinates");
615 } break;
616 }
617
618 return QSharedPointer<QMapboxGLStyleChange>(source);
619}
620
621QSharedPointer<QMapboxGLStyleChange> QMapboxGLStyleAddSource::fromFeature(const QMapbox::Feature &feature)
622{
623 auto source = new QMapboxGLStyleAddSource();
624
625 source->m_id = feature.id.toString();
626 source->m_params[QStringLiteral("type")] = QStringLiteral("geojson");
627 source->m_params[QStringLiteral("data")] = QVariant::fromValue<QMapbox::Feature>(value: feature);
628
629 return QSharedPointer<QMapboxGLStyleChange>(source);
630}
631
632QSharedPointer<QMapboxGLStyleChange> QMapboxGLStyleAddSource::fromMapItem(QDeclarativeGeoMapItemBase *item)
633{
634 return fromFeature(feature: featureFromMapItem(item));
635}
636
637
638// QMapboxGLStyleRemoveSource
639
640void QMapboxGLStyleRemoveSource::apply(QMapboxGL *map)
641{
642 map->removeSource(sourceID: m_id);
643}
644
645QMapboxGLStyleRemoveSource::QMapboxGLStyleRemoveSource(const QString &id) : m_id(id)
646{
647}
648
649
650// QMapboxGLStyleSetFilter
651
652void QMapboxGLStyleSetFilter::apply(QMapboxGL *map)
653{
654 map->setFilter(layer: m_layer, filter: m_filter);
655}
656
657QSharedPointer<QMapboxGLStyleChange> QMapboxGLStyleSetFilter::fromMapParameter(QGeoMapParameter *param)
658{
659 Q_ASSERT(param->type() == "filter");
660
661 auto filter = new QMapboxGLStyleSetFilter();
662 filter->m_layer = param->property(name: "layer").toString();
663 filter->m_filter = param->property(name: "filter");
664
665 return QSharedPointer<QMapboxGLStyleChange>(filter);
666}
667
668
669// QMapboxGLStyleAddImage
670
671void QMapboxGLStyleAddImage::apply(QMapboxGL *map)
672{
673 map->addImage(name: m_name, sprite: m_sprite);
674}
675
676QSharedPointer<QMapboxGLStyleChange> QMapboxGLStyleAddImage::fromMapParameter(QGeoMapParameter *param)
677{
678 Q_ASSERT(param->type() == "image");
679
680 auto image = new QMapboxGLStyleAddImage();
681 image->m_name = param->property(name: "name").toString();
682 image->m_sprite = QImage(param->property(name: "sprite").toString());
683
684 return QSharedPointer<QMapboxGLStyleChange>(image);
685}
686

source code of qtlocation/src/plugins/geoservices/mapboxgl/qmapboxglstylechange.cpp