summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThiago Marcos P. Santos <tmpsantos@gmail.com>2017-02-14 16:05:15 +0200
committerPaolo Angelelli <paolo.angelelli@qt.io>2017-02-17 17:06:22 +0000
commit85c5a6f68a801250bf40eba9546bbd342633327d (patch)
treead2d7f06202333b99c3d33ba0a4d224fa439daf1
parent6e5eead48216dc0dceb94235436133e47563b553 (diff)
downloadqtlocation-85c5a6f68a801250bf40eba9546bbd342633327d.tar.gz
Fix support for MapParameters on Mapbox GL plugin
Mapbox GL plugin can now accept MapParameters, such as MapParameters used for the Mapbox runtime style API, allowing runtime changes on the map, not restricted only to style, but also adding new geometries and features. Change-Id: If0394bd044a2d3058fe5480966880a1055614ea2 Reviewed-by: Paolo Angelelli <paolo.angelelli@qt.io>
-rw-r--r--src/location/declarativemaps/qdeclarativegeomap.cpp4
-rw-r--r--src/location/declarativemaps/qdeclarativegeomap_p.h4
-rw-r--r--src/location/maps/qgeomap.cpp4
-rw-r--r--src/location/maps/qgeomap_p_p.h3
-rw-r--r--src/plugins/geoservices/mapboxgl/mapboxgl.pro3
-rw-r--r--src/plugins/geoservices/mapboxgl/qgeomapmapboxgl.cpp383
-rw-r--r--src/plugins/geoservices/mapboxgl/qgeomapmapboxgl.h25
-rw-r--r--src/plugins/geoservices/mapboxgl/qgeomapmapboxgl_p.h105
-rw-r--r--src/plugins/geoservices/mapboxgl/qmapboxglstylechange.cpp501
-rw-r--r--src/plugins/geoservices/mapboxgl/qmapboxglstylechange_p.h188
10 files changed, 880 insertions, 340 deletions
diff --git a/src/location/declarativemaps/qdeclarativegeomap.cpp b/src/location/declarativemaps/qdeclarativegeomap.cpp
index c32fda6a..65828581 100644
--- a/src/location/declarativemaps/qdeclarativegeomap.cpp
+++ b/src/location/declarativemaps/qdeclarativegeomap.cpp
@@ -1483,7 +1483,7 @@ void QDeclarativeGeoMap::addMapParameter(QDeclarativeGeoMapParameter *parameter)
if (m_mapParameters.contains(parameter))
return;
parameter->setParent(this);
- m_mapParameters.insert(parameter); // parameter now owned by QDeclarativeGeoMap
+ m_mapParameters.append(parameter); // parameter now owned by QDeclarativeGeoMap
if (m_map)
m_map->addParameter(parameter);
}
@@ -1505,7 +1505,7 @@ void QDeclarativeGeoMap::removeMapParameter(QDeclarativeGeoMapParameter *paramet
return;
if (m_map)
m_map->removeParameter(parameter);
- m_mapParameters.remove(parameter);
+ m_mapParameters.removeOne(parameter);
}
/*!
diff --git a/src/location/declarativemaps/qdeclarativegeomap_p.h b/src/location/declarativemaps/qdeclarativegeomap_p.h
index d7aee60f..a7519a48 100644
--- a/src/location/declarativemaps/qdeclarativegeomap_p.h
+++ b/src/location/declarativemaps/qdeclarativegeomap_p.h
@@ -55,8 +55,8 @@
#include <QtLocation/qgeoserviceprovider.h>
#include <QtLocation/private/qgeocameradata_p.h>
#include <QtQuick/QQuickItem>
+#include <QtCore/QList>
#include <QtCore/QPointer>
-#include <QtCore/QSet>
#include <QtGui/QColor>
#include <QtPositioning/qgeoshape.h>
#include <QtLocation/private/qgeomap_p.h>
@@ -257,7 +257,7 @@ private:
bool m_copyrightsVisible;
double m_maximumViewportLatitude;
bool m_initialized;
- QSet<QDeclarativeGeoMapParameter *> m_mapParameters;
+ QList<QDeclarativeGeoMapParameter *> m_mapParameters;
friend class QDeclarativeGeoMapItem;
friend class QDeclarativeGeoMapItemView;
diff --git a/src/location/maps/qgeomap.cpp b/src/location/maps/qgeomap.cpp
index 978957e7..93e4499a 100644
--- a/src/location/maps/qgeomap.cpp
+++ b/src/location/maps/qgeomap.cpp
@@ -167,7 +167,7 @@ void QGeoMap::addParameter(QGeoMapParameter *param)
{
Q_D(QGeoMap);
if (param && !d->m_mapParameters.contains(param)) {
- d->m_mapParameters.insert(param);
+ d->m_mapParameters.append(param);
d->addParameter(param);
}
}
@@ -177,7 +177,7 @@ void QGeoMap::removeParameter(QGeoMapParameter *param)
Q_D(QGeoMap);
if (param && d->m_mapParameters.contains(param)) {
d->removeParameter(param);
- d->m_mapParameters.remove(param);
+ d->m_mapParameters.removeOne(param);
}
}
diff --git a/src/location/maps/qgeomap_p_p.h b/src/location/maps/qgeomap_p_p.h
index ab603be7..4430202f 100644
--- a/src/location/maps/qgeomap_p_p.h
+++ b/src/location/maps/qgeomap_p_p.h
@@ -53,6 +53,7 @@
#include <QtLocation/private/qgeoprojection_p.h>
#include <QtCore/private/qobject_p.h>
#include <QtCore/QSize>
+#include <QtCore/QList>
#include <QtCore/QSet>
#include "qgeomap_p.h"
@@ -92,7 +93,7 @@ protected:
QPointer<QGeoMappingManagerEngine> m_engine;
QGeoCameraData m_cameraData;
QGeoMapType m_activeMapType;
- QSet<QGeoMapParameter *> m_mapParameters;
+ QList<QGeoMapParameter *> m_mapParameters;
QSet<QDeclarativeGeoMapItemBase *> m_mapItems;
};
diff --git a/src/plugins/geoservices/mapboxgl/mapboxgl.pro b/src/plugins/geoservices/mapboxgl/mapboxgl.pro
index 81dd37e2..5ef0ffb3 100644
--- a/src/plugins/geoservices/mapboxgl/mapboxgl.pro
+++ b/src/plugins/geoservices/mapboxgl/mapboxgl.pro
@@ -12,12 +12,15 @@ HEADERS += \
qgeoserviceproviderpluginmapboxgl.h \
qgeomappingmanagerenginemapboxgl.h \
qgeomapmapboxgl.h \
+ qgeomapmapboxgl_p.h \
+ qmapboxglstylechange_p.h \
qsgmapboxglnode.h
SOURCES += \
qgeoserviceproviderpluginmapboxgl.cpp \
qgeomappingmanagerenginemapboxgl.cpp \
qgeomapmapboxgl.cpp \
+ qmapboxglstylechange.cpp \
qsgmapboxglnode.cpp
RESOURCES += mapboxgl.qrc
diff --git a/src/plugins/geoservices/mapboxgl/qgeomapmapboxgl.cpp b/src/plugins/geoservices/mapboxgl/qgeomapmapboxgl.cpp
index eab7b88a..ea4209e8 100644
--- a/src/plugins/geoservices/mapboxgl/qgeomapmapboxgl.cpp
+++ b/src/plugins/geoservices/mapboxgl/qgeomapmapboxgl.cpp
@@ -36,23 +36,21 @@
****************************************************************************/
#include "qgeomapmapboxgl.h"
+#include "qgeomapmapboxgl_p.h"
#include "qsgmapboxglnode.h"
+#include "qmapboxglstylechange_p.h"
#include <QtCore/QByteArray>
#include <QtCore/QCoreApplication>
-#include <QtCore/QTimer>
#include <QtGui/QOpenGLContext>
#include <QtGui/QOpenGLFramebufferObject>
-#include <QtLocation/private/qgeomap_p_p.h>
-#include <QtLocation/private/qgeoprojection_p.h>
-#include <QtLocation/private/qdeclarativegeomapitembase_p.h>
-#include <QtLocation/private/qdeclarativerectanglemapitem_p.h>
#include <QtLocation/private/qdeclarativecirclemapitem_p.h>
+#include <QtLocation/private/qdeclarativegeomapitembase_p.h>
#include <QtLocation/private/qdeclarativepolygonmapitem_p.h>
#include <QtLocation/private/qdeclarativepolylinemapitem_p.h>
-
-#include "qgeopath.h"
-
+#include <QtLocation/private/qdeclarativerectanglemapitem_p.h>
+#include <QtLocation/private/qgeomapparameter_p.h>
+#include <QtLocation/private/qgeoprojection_p.h>
#include <QtQuick/QQuickWindow>
#include <QtQuick/QSGImageNode>
#include <QtQuick/private/qsgtexture_p.h>
@@ -78,103 +76,8 @@ static double zoomLevelFrom256(double zoomLevelFor256, double tileSize)
return std::log(std::pow(2.0, zoomLevelFor256) * 256.0 / tileSize) * invLog2;
}
-QString getId(QDeclarativeGeoMapItemBase *mapItem) {
- return QString::number(quint64(mapItem));
-}
-
-QMapbox::Feature fromMapRectangle(QDeclarativeRectangleMapItem *mapItem)
-{
- const QGeoRectangle *rect = static_cast<const QGeoRectangle *>(&mapItem->geoShape());
- QMapbox::Coordinate bottomLeft { rect->bottomLeft().latitude(), rect->bottomLeft().longitude() };
- QMapbox::Coordinate bottomRight { rect->bottomRight().latitude(), rect->bottomRight().longitude() };
- QMapbox::Coordinate topLeft { rect->topLeft().latitude(), rect->topLeft().longitude() };
- QMapbox::Coordinate topRight { rect->topRight().latitude(), rect->topRight().longitude() };
- QMapbox::CoordinatesCollections geometry { { { bottomLeft, bottomRight, topRight, topLeft, bottomLeft } } };
-
- return QMapbox::Feature(QMapbox::Feature::PolygonType, geometry, {}, getId(mapItem));
-}
-
-QMapbox::Feature fromMapPolygon(QDeclarativePolygonMapItem *mapItem)
-{
- const QGeoPath *path = static_cast<const QGeoPath *>(&mapItem->geoShape());
- QMapbox::Coordinates coordinates;
- for (const QGeoCoordinate &coordinate : path->path()) {
- coordinates << QMapbox::Coordinate { coordinate.latitude(), coordinate.longitude() };
- }
- coordinates.append(coordinates.first());
- QMapbox::CoordinatesCollections geometry { { coordinates } };
-
- return QMapbox::Feature(QMapbox::Feature::PolygonType, geometry, {}, getId(mapItem));
-}
-
-QMapbox::Feature fromMapPolyline(QDeclarativePolylineMapItem *mapItem)
-{
- const QGeoPath *path = static_cast<const QGeoPath *>(&mapItem->geoShape());
- QMapbox::Coordinates coordinates;
- for (const QGeoCoordinate &coordinate : path->path()) {
- coordinates << QMapbox::Coordinate { coordinate.latitude(), coordinate.longitude() };
- }
- QMapbox::CoordinatesCollections geometry { { coordinates } };
-
- return QMapbox::Feature(QMapbox::Feature::LineStringType, geometry, {}, getId(mapItem));
-}
-
} // namespace
-class QGeoMapMapboxGLPrivate : public QGeoMapPrivate
-{
- Q_DECLARE_PUBLIC(QGeoMapMapboxGL)
-
-public:
- QGeoMapMapboxGLPrivate(QGeoMappingManagerEngineMapboxGL *engine);
-
- ~QGeoMapMapboxGLPrivate();
-
- QSGNode *updateSceneGraph(QSGNode *oldNode, QQuickWindow *window);
-
- QGeoMap::ItemTypes supportedMapItemTypes() const Q_DECL_OVERRIDE;
- void addMapItem(QDeclarativeGeoMapItemBase *item) Q_DECL_OVERRIDE;
- void removeMapItem(QDeclarativeGeoMapItemBase *item) Q_DECL_OVERRIDE;
-
- /* Data members */
- enum SyncState : int {
- NoSync = 0,
- ViewportSync = 1 << 0,
- CameraDataSync = 1 << 1,
- MapTypeSync = 1 << 2
- };
- Q_DECLARE_FLAGS(SyncStates, SyncState);
-
- QMapboxGLSettings m_settings;
- bool m_useFBO = true;
- bool m_developmentMode = false;
-
- QTimer m_refresh;
- bool m_shouldRefresh = true;
- bool m_warned = false;
- bool m_styleLoaded = false;
-
- QList<QDeclarativeGeoMapItemBase *> m_managedMapItems;
- QList<QDeclarativeGeoMapItemBase *> m_mapItemsToAdd;
- QList<QDeclarativeGeoMapItemBase *> m_mapItemsToRemove;
-
- QHash<QString, QPair<QString, QVariant>> m_paintProperties;
- QHash<QString, QPair<QString, QVariant>> m_layoutProperties;
- QList<QMapbox::Feature> m_sources;
-
- SyncStates m_syncState = NoSync;
-
-protected:
- void changeViewportSize(const QSize &size) Q_DECL_OVERRIDE;
- void changeCameraData(const QGeoCameraData &oldCameraData) Q_DECL_OVERRIDE;
- void changeActiveMapType(const QGeoMapType mapType) Q_DECL_OVERRIDE;
-
-private:
- Q_DISABLE_COPY(QGeoMapMapboxGLPrivate)
-};
-
-Q_DECLARE_OPERATORS_FOR_FLAGS(QGeoMapMapboxGLPrivate::SyncStates)
-
QGeoMapMapboxGLPrivate::QGeoMapMapboxGLPrivate(QGeoMappingManagerEngineMapboxGL *engine)
: QGeoMapPrivate(engine, new QGeoProjectionWebMercator)
{
@@ -223,103 +126,6 @@ QSGNode *QGeoMapMapboxGLPrivate::updateSceneGraph(QSGNode *node, QQuickWindow *w
map->setStyleUrl(m_activeMapType.name());
}
- if (m_styleLoaded) {
- for (QDeclarativeGeoMapItemBase *mapItem : m_mapItemsToRemove) {
- const QString id = getId(mapItem);
- if (map->layerExists(id)) {
- map->removeLayer(id);
- }
- if (map->sourceExists(id)) {
- map->removeSource(id);
- }
- m_mapItemsToAdd.removeAll(mapItem);
- }
- m_mapItemsToRemove.clear();
-
- auto addSourceAndLayer = [&](const QMapbox::Feature &feature) {
- const QString id = feature.id.toString();
- Q_ASSERT(!map->sourceExists(id));
- Q_ASSERT(!map->layerExists(id));
-
- QVariantMap source;
- source["type"] = QStringLiteral("geojson");
- source["data"] = QVariant::fromValue<QMapbox::Feature>(feature);
- map->addSource(id, source);
-
- QVariantMap layer;
- layer["id"] = feature.id;
- switch (feature.type) {
- case QMapbox::Feature::PointType:
- layer["type"] = QStringLiteral("circle");
- break;
- case QMapbox::Feature::LineStringType:
- layer["type"] = QStringLiteral("line");
- break;
- case QMapbox::Feature::PolygonType:
- layer["type"] = QStringLiteral("fill");
- break;
- }
- layer["source"] = feature.id;
- map->addLayer(layer);
- };
-
- for (QDeclarativeGeoMapItemBase *item : m_mapItemsToAdd) {
- const QString id = getId(item);
-
- switch (item->itemType()) {
- case QGeoMap::MapRectangle: {
- QDeclarativeRectangleMapItem *mapItem = static_cast<QDeclarativeRectangleMapItem *>(item);
- addSourceAndLayer(fromMapRectangle(mapItem));
- map->setPaintProperty(id, "fill-opacity", mapItem->mapItemOpacity());
- map->setPaintProperty(id, "fill-color", mapItem->color());
- map->setPaintProperty(id, "fill-outline-color", mapItem->border()->color());
- } break;
- case QGeoMap::MapPolygon: {
- QDeclarativePolygonMapItem *mapItem = static_cast<QDeclarativePolygonMapItem *>(item);
- addSourceAndLayer(fromMapPolygon(mapItem));
- map->setPaintProperty(id, "fill-opacity", mapItem->mapItemOpacity());
- map->setPaintProperty(id, "fill-color", mapItem->color());
- map->setPaintProperty(id, "fill-outline-color", mapItem->border()->color());
- } break;
- case QGeoMap::MapPolyline: {
- QDeclarativePolylineMapItem *mapItem = static_cast<QDeclarativePolylineMapItem *>(item);
- addSourceAndLayer(fromMapPolyline(mapItem));
- map->setPaintProperty(id, "line-opacity", mapItem->mapItemOpacity());
- map->setPaintProperty(id, "line-color", mapItem->line()->color());
- map->setPaintProperty(id, "line-width", mapItem->line()->width());
- } break;
- default:
- qWarning() << "Unsupported QGeoMap item type: " << item->itemType();
- break;
- }
- }
- m_mapItemsToAdd.clear();
-
- for (const QMapbox::Feature &feature : m_sources) {
- const QString id = feature.id.toString();
-
- Q_ASSERT(map->sourceExists(id));
-
- QVariantMap source;
- source["type"] = QStringLiteral("geojson");
- source["data"] = QVariant::fromValue<QMapbox::Feature>(feature);
- map->updateSource(id, source);
- }
- m_sources.clear();
-
- auto paintPropertiesIterator = m_paintProperties.constBegin();
- while (paintPropertiesIterator != m_paintProperties.constEnd()) {
- map->setPaintProperty(paintPropertiesIterator.key(), paintPropertiesIterator.value().first, paintPropertiesIterator.value().second);
- }
- m_paintProperties.clear();
-
- auto layoutPropertiesIterator = m_layoutProperties.constBegin();
- while (layoutPropertiesIterator != m_layoutProperties.constEnd()) {
- map->setLayoutProperty(layoutPropertiesIterator.key(), layoutPropertiesIterator.value().first, layoutPropertiesIterator.value().second);
- }
- m_layoutProperties.clear();
- }
-
if (m_syncState & CameraDataSync) {
map->setZoom(zoomLevelFrom256(m_cameraData.zoomLevel() , MBGL_TILE_SIZE));
map->setBearing(m_cameraData.bearing());
@@ -337,6 +143,10 @@ QSGNode *QGeoMapMapboxGLPrivate::updateSceneGraph(QSGNode *node, QQuickWindow *w
}
}
+ if (m_styleLoaded) {
+ syncStyleChanges(map);
+ }
+
if (m_useFBO) {
static_cast<QSGMapboxGLTextureNode *>(node)->render(window);
}
@@ -346,6 +156,21 @@ QSGNode *QGeoMapMapboxGLPrivate::updateSceneGraph(QSGNode *node, QQuickWindow *w
return node;
}
+void QGeoMapMapboxGLPrivate::addParameter(QGeoMapParameter *param)
+{
+ Q_Q(QGeoMapMapboxGL);
+
+ QObject::connect(param, &QGeoMapParameter::propertyUpdated, q,
+ &QGeoMapMapboxGL::onParameterPropertyUpdated);
+}
+
+void QGeoMapMapboxGLPrivate::removeParameter(QGeoMapParameter *param)
+{
+ Q_Q(QGeoMapMapboxGL);
+
+ q->disconnect(param);
+}
+
QGeoMap::ItemTypes QGeoMapMapboxGLPrivate::supportedMapItemTypes() const
{
// TODO https://bugreports.qt.io/browse/QTBUG-58869
@@ -364,31 +189,30 @@ void QGeoMapMapboxGLPrivate::addMapItem(QDeclarativeGeoMapItemBase *item)
return;
case QGeoMap::MapRectangle: {
QDeclarativeRectangleMapItem *mapItem = qobject_cast<QDeclarativeRectangleMapItem *>(item);
- QObject::connect(mapItem, &QDeclarativeRectangleMapItem::bottomRightChanged, q, &QGeoMapMapboxGL::onMapRectangleGeometryChanged);
- QObject::connect(mapItem, &QDeclarativeRectangleMapItem::topLeftChanged, q, &QGeoMapMapboxGL::onMapRectangleGeometryChanged);
- QObject::connect(mapItem, &QDeclarativeRectangleMapItem::colorChanged, q, &QGeoMapMapboxGL::onMapRectangleColorChanged);
- QObject::connect(mapItem->border(), &QDeclarativeMapLineProperties::colorChanged, q, &QGeoMapMapboxGL::onMapRectangleBorderColorChanged);
- QObject::connect(mapItem->border(), &QDeclarativeMapLineProperties::widthChanged, q, &QGeoMapMapboxGL::onMapRectangleBorderWidthChanged);
+ QObject::connect(mapItem, &QDeclarativeRectangleMapItem::bottomRightChanged, q, &QGeoMapMapboxGL::onMapItemGeometryChanged);
+ QObject::connect(mapItem, &QDeclarativeRectangleMapItem::topLeftChanged, q, &QGeoMapMapboxGL::onMapItemGeometryChanged);
+ QObject::connect(mapItem, &QDeclarativeRectangleMapItem::colorChanged, q, &QGeoMapMapboxGL::onMapItemPropertyChanged);
+ QObject::connect(mapItem->border(), &QDeclarativeMapLineProperties::colorChanged, q, &QGeoMapMapboxGL::onMapItemSubPropertyChanged);
+ QObject::connect(mapItem->border(), &QDeclarativeMapLineProperties::widthChanged, q, &QGeoMapMapboxGL::onMapItemUnsupportedPropertyChanged);
} break;
case QGeoMap::MapPolygon: {
QDeclarativePolygonMapItem *mapItem = qobject_cast<QDeclarativePolygonMapItem *>(item);
- QObject::connect(mapItem, &QDeclarativePolygonMapItem::pathChanged, q, &QGeoMapMapboxGL::onMapPolygonGeometryChanged);
- QObject::connect(mapItem, &QDeclarativePolygonMapItem::colorChanged, q, &QGeoMapMapboxGL::onMapPolygonColorChanged);
- QObject::connect(mapItem->border(), &QDeclarativeMapLineProperties::colorChanged, q, &QGeoMapMapboxGL::onMapPolygonBorderColorChanged);
- QObject::connect(mapItem->border(), &QDeclarativeMapLineProperties::widthChanged, q, &QGeoMapMapboxGL::onMapPolygonBorderWidthChanged);
+ QObject::connect(mapItem, &QDeclarativePolygonMapItem::pathChanged, q, &QGeoMapMapboxGL::onMapItemGeometryChanged);
+ QObject::connect(mapItem, &QDeclarativePolygonMapItem::colorChanged, q, &QGeoMapMapboxGL::onMapItemGeometryChanged);
+ QObject::connect(mapItem->border(), &QDeclarativeMapLineProperties::colorChanged, q, &QGeoMapMapboxGL::onMapItemSubPropertyChanged);
+ QObject::connect(mapItem->border(), &QDeclarativeMapLineProperties::widthChanged, q, &QGeoMapMapboxGL::onMapItemUnsupportedPropertyChanged);
} break;
case QGeoMap::MapPolyline: {
QDeclarativePolylineMapItem *mapItem = qobject_cast<QDeclarativePolylineMapItem *>(item);
- QObject::connect(mapItem, &QDeclarativePolylineMapItem::pathChanged, q, &QGeoMapMapboxGL::onMapPolylineGeometryChanged);
- QObject::connect(mapItem->line(), &QDeclarativeMapLineProperties::colorChanged, q, &QGeoMapMapboxGL::onMapPolylineLineColorChanged);
- QObject::connect(mapItem->line(), &QDeclarativeMapLineProperties::widthChanged, q, &QGeoMapMapboxGL::onMapPolylineLineWidthChanged);
+ QObject::connect(mapItem, &QDeclarativePolylineMapItem::pathChanged, q, &QGeoMapMapboxGL::onMapItemGeometryChanged);
+ QObject::connect(mapItem->line(), &QDeclarativeMapLineProperties::colorChanged, q, &QGeoMapMapboxGL::onMapItemSubPropertyChanged);
+ QObject::connect(mapItem->line(), &QDeclarativeMapLineProperties::widthChanged, q, &QGeoMapMapboxGL::onMapItemSubPropertyChanged);
} break;
}
- QObject::connect(item, &QDeclarativeGeoMapItemBase::mapItemOpacityChanged, q, &QGeoMapMapboxGL::onMapItemOpacityChanged);
+ QObject::connect(item, &QDeclarativeGeoMapItemBase::mapItemOpacityChanged, q, &QGeoMapMapboxGL::onMapItemPropertyChanged);
- m_mapItemsToAdd.append(item);
- m_managedMapItems.append(item);
+ m_styleChanges << QMapboxGLStyleChange::addMapItem(item);
emit q->sgNodeChanged();
}
@@ -412,13 +236,11 @@ void QGeoMapMapboxGLPrivate::removeMapItem(QDeclarativeGeoMapItemBase *item)
case QGeoMap::MapPolyline:
q->disconnect(static_cast<QDeclarativePolylineMapItem *>(item)->line());
break;
- break;
}
q->disconnect(item);
- m_mapItemsToRemove.append(item);
- m_managedMapItems.removeAll(item);
+ m_styleChanges << QMapboxGLStyleChange::removeMapItem(item);
emit q->sgNodeChanged();
}
@@ -447,6 +269,15 @@ void QGeoMapMapboxGLPrivate::changeActiveMapType(const QGeoMapType)
emit q->sgNodeChanged();
}
+void QGeoMapMapboxGLPrivate::syncStyleChanges(QMapboxGL *map)
+{
+ for (const auto& change : m_styleChanges) {
+ change->apply(map);
+ }
+
+ m_styleChanges.clear();
+}
+
/*
* QGeoMapMapboxGL implementation
*/
@@ -502,137 +333,57 @@ void QGeoMapMapboxGL::onMapChanged(QMapboxGL::MapChange change)
d->m_styleLoaded = true;
} else if (change == QMapboxGL::MapChangeWillStartLoadingMap) {
d->m_styleLoaded = false;
- d->m_mapItemsToAdd.clear();
- d->m_mapItemsToAdd.append(d->m_managedMapItems);
- }
-}
-
-// QDeclarativeGeoMapItemBase
-
-void QGeoMapMapboxGL::onMapItemOpacityChanged()
-{
- Q_D(QGeoMapMapboxGL);
+ d->m_styleChanges.clear();
- QDeclarativeGeoMapItemBase *mapItem = static_cast<QDeclarativeGeoMapItemBase *>(sender());
- const QString id = getId(mapItem);
+ for (QGeoMapParameter *param : d->m_mapParameters)
+ d->m_styleChanges << QMapboxGLStyleChange::addMapParameter(param);
- switch (mapItem->itemType()) {
- case QGeoMap::MapRectangle:
- case QGeoMap::MapPolygon:
- d->m_paintProperties.insertMulti(id, { QStringLiteral("fill-opacity"), mapItem->mapItemOpacity() });
- break;
- case QGeoMap::MapPolyline:
- d->m_paintProperties.insertMulti(id, { QStringLiteral("line-opacity"), mapItem->mapItemOpacity() });
- break;
- default:
- qWarning() << "Unsupported QGeoMap item type: " << mapItem->itemType();
- return;
+ for (QDeclarativeGeoMapItemBase *item : d->m_mapItems)
+ d->m_styleChanges << QMapboxGLStyleChange::addMapItem(item);
}
-
- emit sgNodeChanged();
-}
-
-// QDeclarativeRectangleMapItem
-
-void QGeoMapMapboxGL::onMapRectangleGeometryChanged()
-{
- Q_D(QGeoMapMapboxGL);
-
- d->m_sources.append(fromMapRectangle(qobject_cast<QDeclarativeRectangleMapItem *>(sender())));
-
- emit sgNodeChanged();
}
-void QGeoMapMapboxGL::onMapRectangleColorChanged()
+void QGeoMapMapboxGL::onMapItemPropertyChanged()
{
Q_D(QGeoMapMapboxGL);
- QDeclarativeRectangleMapItem *mapItem = qobject_cast<QDeclarativeRectangleMapItem *>(sender());
- d->m_paintProperties.insertMulti(getId(mapItem), { QStringLiteral("fill-color"), mapItem->color() });
+ QDeclarativeGeoMapItemBase *item = static_cast<QDeclarativeGeoMapItemBase *>(sender());
+ d->m_styleChanges << QMapboxGLStyleSetPaintProperty::fromMapItem(item);
emit sgNodeChanged();
}
-void QGeoMapMapboxGL::onMapRectangleBorderColorChanged()
+void QGeoMapMapboxGL::onMapItemSubPropertyChanged()
{
Q_D(QGeoMapMapboxGL);
- QDeclarativeRectangleMapItem *mapItem = qobject_cast<QDeclarativeRectangleMapItem *>(sender()->parent());
- d->m_paintProperties.insertMulti(getId(mapItem), { QStringLiteral("fill-outline-color"), mapItem->border()->color() });
+ QDeclarativeGeoMapItemBase *item = static_cast<QDeclarativeGeoMapItemBase *>(sender()->parent());
+ d->m_styleChanges << QMapboxGLStyleSetPaintProperty::fromMapItem(item);
emit sgNodeChanged();
}
-void QGeoMapMapboxGL::onMapRectangleBorderWidthChanged()
+void QGeoMapMapboxGL::onMapItemUnsupportedPropertyChanged()
{
// TODO https://bugreports.qt.io/browse/QTBUG-58872
- qWarning() << "MapRectangle border color currently not supported in Mapbox GL native.";
-}
-
-// QDeclarativePolygonMapItem
-
-void QGeoMapMapboxGL::onMapPolygonGeometryChanged()
-{
- Q_D(QGeoMapMapboxGL);
-
- d->m_sources.append(fromMapPolygon(qobject_cast<QDeclarativePolygonMapItem *>(sender())));
-
- emit sgNodeChanged();
-}
-
-void QGeoMapMapboxGL::onMapPolygonColorChanged()
-{
- Q_D(QGeoMapMapboxGL);
-
- QDeclarativePolygonMapItem *mapItem = qobject_cast<QDeclarativePolygonMapItem *>(sender());
- d->m_paintProperties.insertMulti(getId(mapItem), { QStringLiteral("fill-color"), mapItem->color() });
-
- emit sgNodeChanged();
-}
-
-void QGeoMapMapboxGL::onMapPolygonBorderColorChanged()
-{
- Q_D(QGeoMapMapboxGL);
-
- QDeclarativePolygonMapItem *mapItem = qobject_cast<QDeclarativePolygonMapItem *>(sender()->parent());
- d->m_paintProperties.insertMulti(getId(mapItem), { QStringLiteral("fill-outline-color"), mapItem->border()->color() });
-
- emit sgNodeChanged();
-}
-
-void QGeoMapMapboxGL::onMapPolygonBorderWidthChanged()
-{
- // TODO https://bugreports.qt.io/browse/QTBUG-58872
- qWarning() << "MapPolygon border color currently not supported in Mapbox GL native.";
-}
-
-// QDeclarativePolylineMapItem
-
-void QGeoMapMapboxGL::onMapPolylineGeometryChanged()
-{
- Q_D(QGeoMapMapboxGL);
-
- d->m_sources.append(fromMapPolyline(qobject_cast<QDeclarativePolylineMapItem *>(sender())));
-
- emit sgNodeChanged();
+ qWarning() << "Unsupported property for managed Map item";
}
-void QGeoMapMapboxGL::onMapPolylineLineColorChanged()
+void QGeoMapMapboxGL::onMapItemGeometryChanged()
{
Q_D(QGeoMapMapboxGL);
- QDeclarativePolylineMapItem *mapItem = qobject_cast<QDeclarativePolylineMapItem *>(sender()->parent());
- d->m_paintProperties.insertMulti(getId(mapItem), { QStringLiteral("line-color"), mapItem->line()->color() });
+ QDeclarativeGeoMapItemBase *item = static_cast<QDeclarativeGeoMapItemBase *>(sender());
+ d->m_styleChanges << QMapboxGLStyleAddSource::fromMapItem(item);
emit sgNodeChanged();
}
-void QGeoMapMapboxGL::onMapPolylineLineWidthChanged()
+void QGeoMapMapboxGL::onParameterPropertyUpdated(QGeoMapParameter *param, const char *)
{
Q_D(QGeoMapMapboxGL);
- QDeclarativePolylineMapItem *mapItem = qobject_cast<QDeclarativePolylineMapItem *>(sender()->parent());
- d->m_paintProperties.insertMulti(getId(mapItem), { QStringLiteral("line-width"), mapItem->line()->width() });
+ d->m_styleChanges.append(QMapboxGLStyleChange::addMapParameter(param));
emit sgNodeChanged();
}
diff --git a/src/plugins/geoservices/mapboxgl/qgeomapmapboxgl.h b/src/plugins/geoservices/mapboxgl/qgeomapmapboxgl.h
index c43a1e28..56b97e99 100644
--- a/src/plugins/geoservices/mapboxgl/qgeomapmapboxgl.h
+++ b/src/plugins/geoservices/mapboxgl/qgeomapmapboxgl.h
@@ -40,8 +40,10 @@
#include "qgeomappingmanagerenginemapboxgl.h"
#include <QtLocation/private/qgeomap_p.h>
+#include <QtLocation/private/qgeomapparameter_p.h>
class QGeoMapMapboxGLPrivate;
+
class QGeoMapMapboxGL : public QGeoMap
{
Q_OBJECT
@@ -60,24 +62,13 @@ private Q_SLOTS:
void onMapChanged(QMapboxGL::MapChange);
// QDeclarativeGeoMapItemBase
- void onMapItemOpacityChanged();
-
- // QDeclarativeRectangleMapItem
- void onMapRectangleGeometryChanged();
- void onMapRectangleColorChanged();
- void onMapRectangleBorderColorChanged();
- void onMapRectangleBorderWidthChanged();
-
- // QDeclarativePolygonMapItem
- void onMapPolygonGeometryChanged();
- void onMapPolygonColorChanged();
- void onMapPolygonBorderColorChanged();
- void onMapPolygonBorderWidthChanged();
+ void onMapItemPropertyChanged();
+ void onMapItemSubPropertyChanged();
+ void onMapItemUnsupportedPropertyChanged();
+ void onMapItemGeometryChanged();
- // QDeclarativePolylineMapItem
- void onMapPolylineGeometryChanged();
- void onMapPolylineLineColorChanged();
- void onMapPolylineLineWidthChanged();
+ // QGeoMapParameter
+ void onParameterPropertyUpdated(QGeoMapParameter *param, const char *propertyName);
public Q_SLOTS:
void copyrightsChanged(const QString &copyrightsHtml);
diff --git a/src/plugins/geoservices/mapboxgl/qgeomapmapboxgl_p.h b/src/plugins/geoservices/mapboxgl/qgeomapmapboxgl_p.h
new file mode 100644
index 00000000..b6527c01
--- /dev/null
+++ b/src/plugins/geoservices/mapboxgl/qgeomapmapboxgl_p.h
@@ -0,0 +1,105 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Copyright (C) 2017 Mapbox, Inc.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the QtLocation module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL3$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPLv3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or later as published by the Free
+** Software Foundation and appearing in the file LICENSE.GPL included in
+** the packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QGEOMAPMAPBOXGL_P_H
+#define QGEOMAPMAPBOXGL_P_H
+
+#include <QtCore/QHash>
+#include <QtCore/QList>
+#include <QtCore/QSharedPointer>
+#include <QtCore/QTimer>
+#include <QtCore/QVariant>
+#include <QtLocation/private/qgeomap_p_p.h>
+#include <QtLocation/private/qgeomapparameter_p.h>
+
+class QMapboxGL;
+class QMapboxGLStyleChange;
+
+class QGeoMapMapboxGLPrivate : public QGeoMapPrivate
+{
+ Q_DECLARE_PUBLIC(QGeoMapMapboxGL)
+
+public:
+ QGeoMapMapboxGLPrivate(QGeoMappingManagerEngineMapboxGL *engine);
+
+ ~QGeoMapMapboxGLPrivate();
+
+ QSGNode *updateSceneGraph(QSGNode *oldNode, QQuickWindow *window);
+
+ void addParameter(QGeoMapParameter *param) Q_DECL_OVERRIDE;
+ void removeParameter(QGeoMapParameter *param) Q_DECL_OVERRIDE;
+
+ QGeoMap::ItemTypes supportedMapItemTypes() const Q_DECL_OVERRIDE;
+ void addMapItem(QDeclarativeGeoMapItemBase *item) Q_DECL_OVERRIDE;
+ void removeMapItem(QDeclarativeGeoMapItemBase *item) Q_DECL_OVERRIDE;
+
+ /* Data members */
+ enum SyncState : int {
+ NoSync = 0,
+ ViewportSync = 1 << 0,
+ CameraDataSync = 1 << 1,
+ MapTypeSync = 1 << 2
+ };
+ Q_DECLARE_FLAGS(SyncStates, SyncState);
+
+ QMapboxGLSettings m_settings;
+ bool m_useFBO = true;
+ bool m_developmentMode = false;
+
+ QTimer m_refresh;
+ bool m_shouldRefresh = true;
+ bool m_warned = false;
+ bool m_styleLoaded = false;
+
+ SyncStates m_syncState = NoSync;
+
+ QList<QSharedPointer<QMapboxGLStyleChange>> m_styleChanges;
+
+protected:
+ void changeViewportSize(const QSize &size) Q_DECL_OVERRIDE;
+ void changeCameraData(const QGeoCameraData &oldCameraData) Q_DECL_OVERRIDE;
+ void changeActiveMapType(const QGeoMapType mapType) Q_DECL_OVERRIDE;
+
+private:
+ Q_DISABLE_COPY(QGeoMapMapboxGLPrivate);
+
+ void syncStyleChanges(QMapboxGL *map);
+};
+
+Q_DECLARE_OPERATORS_FOR_FLAGS(QGeoMapMapboxGLPrivate::SyncStates)
+
+#endif // QGEOMAPMAPBOXGL_P_H
diff --git a/src/plugins/geoservices/mapboxgl/qmapboxglstylechange.cpp b/src/plugins/geoservices/mapboxgl/qmapboxglstylechange.cpp
new file mode 100644
index 00000000..2d3850e1
--- /dev/null
+++ b/src/plugins/geoservices/mapboxgl/qmapboxglstylechange.cpp
@@ -0,0 +1,501 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 Mapbox, Inc.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the QtLocation module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL3$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPLv3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or later as published by the Free
+** Software Foundation and appearing in the file LICENSE.GPL included in
+** the packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qmapboxglstylechange_p.h"
+
+#include <QtCore/QDebug>
+#include <QtCore/QMetaProperty>
+#include <QtCore/QRegularExpression>
+#include <QtCore/QStringList>
+#include <QtPositioning/QGeoPath>
+#include <QtQml/QJSValue>
+
+namespace {
+
+QString formatPropertyName(QString *name)
+{
+ static const QRegularExpression camelCaseRegex(QStringLiteral("([a-z0-9])([A-Z])"));
+
+ return name->replace(camelCaseRegex, QStringLiteral("\\1-\\2")).toLower();
+}
+
+bool isImmutableProperty(const QString &name)
+{
+ return name == QStringLiteral("type") || name == QStringLiteral("layer") || name == QStringLiteral("class");
+}
+
+QString getId(QDeclarativeGeoMapItemBase *mapItem)
+{
+ return QStringLiteral("QDeclarativeGeoMapItemBase-") + QString::number(quint64(mapItem));
+}
+
+QMapbox::Feature featureFromMapRectangle(QDeclarativeRectangleMapItem *mapItem)
+{
+ const QGeoRectangle *rect = static_cast<const QGeoRectangle *>(&mapItem->geoShape());
+ QMapbox::Coordinate bottomLeft { rect->bottomLeft().latitude(), rect->bottomLeft().longitude() };
+ QMapbox::Coordinate bottomRight { rect->bottomRight().latitude(), rect->bottomRight().longitude() };
+ QMapbox::Coordinate topLeft { rect->topLeft().latitude(), rect->topLeft().longitude() };
+ QMapbox::Coordinate topRight { rect->topRight().latitude(), rect->topRight().longitude() };
+ QMapbox::CoordinatesCollections geometry { { { bottomLeft, bottomRight, topRight, topLeft, bottomLeft } } };
+
+ return QMapbox::Feature(QMapbox::Feature::PolygonType, geometry, {}, getId(mapItem));
+}
+
+QMapbox::Feature featureFromMapPolygon(QDeclarativePolygonMapItem *mapItem)
+{
+ const QGeoPath *path = static_cast<const QGeoPath *>(&mapItem->geoShape());
+ QMapbox::Coordinates coordinates;
+ for (const QGeoCoordinate &coordinate : path->path()) {
+ coordinates << QMapbox::Coordinate { coordinate.latitude(), coordinate.longitude() };
+ }
+ coordinates.append(coordinates.first());
+ QMapbox::CoordinatesCollections geometry { { coordinates } };
+
+ return QMapbox::Feature(QMapbox::Feature::PolygonType, geometry, {}, getId(mapItem));
+}
+
+QMapbox::Feature featureFromMapPolyline(QDeclarativePolylineMapItem *mapItem)
+{
+ const QGeoPath *path = static_cast<const QGeoPath *>(&mapItem->geoShape());
+ QMapbox::Coordinates coordinates;
+ for (const QGeoCoordinate &coordinate : path->path()) {
+ coordinates << QMapbox::Coordinate { coordinate.latitude(), coordinate.longitude() };
+ }
+ QMapbox::CoordinatesCollections geometry { { coordinates } };
+
+ return QMapbox::Feature(QMapbox::Feature::LineStringType, geometry, {}, getId(mapItem));
+}
+
+QMapbox::Feature featureFromMapItem(QDeclarativeGeoMapItemBase *item)
+{
+ switch (item->itemType()) {
+ case QGeoMap::MapRectangle:
+ return featureFromMapRectangle(static_cast<QDeclarativeRectangleMapItem *>(item));
+ case QGeoMap::MapPolygon:
+ return featureFromMapPolygon(static_cast<QDeclarativePolygonMapItem *>(item));
+ case QGeoMap::MapPolyline:
+ return featureFromMapPolyline(static_cast<QDeclarativePolylineMapItem *>(item));
+ default:
+ qWarning() << "Unsupported QGeoMap item type: " << item->itemType();
+ return QMapbox::Feature();
+ }
+}
+
+} // namespace
+
+
+// QMapboxGLStyleChange
+
+QList<QSharedPointer<QMapboxGLStyleChange>> QMapboxGLStyleChange::addMapParameter(QGeoMapParameter *param)
+{
+ static const QStringList acceptedParameterTypes = QStringList()
+ << QStringLiteral("paint") << QStringLiteral("layout") << QStringLiteral("filter")
+ << QStringLiteral("layer") << QStringLiteral("source") << QStringLiteral("image");
+
+ QList<QSharedPointer<QMapboxGLStyleChange>> changes;
+
+ switch (acceptedParameterTypes.indexOf(param->type())) {
+ case -1:
+ qWarning() << "Invalid value for property 'type': " + param->type();
+ break;
+ case 0: // paint
+ changes << QMapboxGLStyleSetPaintProperty::fromMapParameter(param);
+ break;
+ case 1: // layout
+ changes << QMapboxGLStyleSetLayoutProperty::fromMapParameter(param);
+ break;
+ case 2: // filter
+ changes << QMapboxGLStyleSetFilter::fromMapParameter(param);
+ break;
+ case 3: // layer
+ changes << QMapboxGLStyleAddLayer::fromMapParameter(param);
+ break;
+ case 4: // source
+ changes << QMapboxGLStyleAddSource::fromMapParameter(param);
+ break;
+ case 5: // image
+ changes << QMapboxGLStyleAddImage::fromMapParameter(param);
+ break;
+ }
+
+ return changes;
+}
+
+QList<QSharedPointer<QMapboxGLStyleChange>> QMapboxGLStyleChange::addMapItem(QDeclarativeGeoMapItemBase *item)
+{
+ QList<QSharedPointer<QMapboxGLStyleChange>> changes;
+
+ switch (item->itemType()) {
+ case QGeoMap::MapRectangle:
+ case QGeoMap::MapPolygon:
+ case QGeoMap::MapPolyline:
+ break;
+ default:
+ qWarning() << "Unsupported QGeoMap item type: " << item->itemType();
+ return changes;
+ }
+
+ QMapbox::Feature feature = featureFromMapItem(item);
+
+ changes << QMapboxGLStyleAddLayer::fromFeature(feature);
+ changes << QMapboxGLStyleAddSource::fromFeature(feature);
+ changes << QMapboxGLStyleSetPaintProperty::fromMapItem(item);
+
+ return changes;
+}
+
+QList<QSharedPointer<QMapboxGLStyleChange>> QMapboxGLStyleChange::removeMapItem(QDeclarativeGeoMapItemBase *item)
+{
+ QList<QSharedPointer<QMapboxGLStyleChange>> changes;
+
+ const QString id = getId(item);
+
+ changes << QSharedPointer<QMapboxGLStyleChange>(new QMapboxGLStyleRemoveLayer(id));
+ changes << QSharedPointer<QMapboxGLStyleChange>(new QMapboxGLStyleRemoveSource(id));
+
+ return changes;
+}
+
+// QMapboxGLStyleSetLayoutProperty
+
+void QMapboxGLStyleSetLayoutProperty::apply(QMapboxGL *map)
+{
+ map->setLayoutProperty(m_layer, m_property, m_value);
+}
+
+QList<QSharedPointer<QMapboxGLStyleChange>> QMapboxGLStyleSetLayoutProperty::fromMapParameter(QGeoMapParameter *param)
+{
+ Q_ASSERT(param->type() == "layout");
+
+ QList<QSharedPointer<QMapboxGLStyleChange>> changes;
+
+ // Offset objectName and type properties.
+ for (int i = 2; i < param->metaObject()->propertyCount(); ++i) {
+ QString name = param->metaObject()->property(i).name();
+
+ if (isImmutableProperty(name))
+ continue;
+
+ auto layout = new QMapboxGLStyleSetLayoutProperty();
+
+ layout->m_value = param->property(name.toLatin1());
+ if (layout->m_value.canConvert<QJSValue>()) {
+ layout->m_value = layout->m_value.value<QJSValue>().toVariant();
+ }
+
+ layout->m_layer = param->property("layer").toString();
+ layout->m_property = formatPropertyName(&name);
+
+ changes << QSharedPointer<QMapboxGLStyleChange>(layout);
+ }
+
+ return changes;
+}
+
+
+// QMapboxGLStyleSetPaintProperty
+
+QMapboxGLStyleSetPaintProperty::QMapboxGLStyleSetPaintProperty(const QString& layer, const QString& property, const QVariant &value)
+ : m_layer(layer), m_property(property), m_value(value)
+{
+}
+
+void QMapboxGLStyleSetPaintProperty::apply(QMapboxGL *map)
+{
+ map->setPaintProperty(m_layer, m_property, m_value, m_class);
+}
+
+QList<QSharedPointer<QMapboxGLStyleChange>> QMapboxGLStyleSetPaintProperty::fromMapParameter(QGeoMapParameter *param)
+{
+ Q_ASSERT(param->type() == "paint");
+
+ QList<QSharedPointer<QMapboxGLStyleChange>> changes;
+
+ // Offset objectName and type properties.
+ for (int i = 2; i < param->metaObject()->propertyCount(); ++i) {
+ QString name = param->metaObject()->property(i).name();
+
+ if (isImmutableProperty(name))
+ continue;
+
+ auto paint = new QMapboxGLStyleSetPaintProperty();
+
+ paint->m_value = param->property(name.toLatin1());
+ if (paint->m_value.canConvert<QJSValue>()) {
+ paint->m_value = paint->m_value.value<QJSValue>().toVariant();
+ }
+
+ paint->m_layer = param->property("layer").toString();
+ paint->m_property = formatPropertyName(&name);
+ paint->m_class = param->property("class").toString();
+
+ changes << QSharedPointer<QMapboxGLStyleChange>(paint);
+ }
+
+ return changes;
+}
+
+QList<QSharedPointer<QMapboxGLStyleChange>> QMapboxGLStyleSetPaintProperty::fromMapItem(QDeclarativeGeoMapItemBase *item)
+{
+ switch (item->itemType()) {
+ case QGeoMap::MapRectangle:
+ return fromMapItem(static_cast<QDeclarativeRectangleMapItem *>(item));
+ case QGeoMap::MapPolygon:
+ return fromMapItem(static_cast<QDeclarativePolygonMapItem *>(item));
+ case QGeoMap::MapPolyline:
+ return fromMapItem(static_cast<QDeclarativePolylineMapItem *>(item));
+ default:
+ qWarning() << "Unsupported QGeoMap item type: " << item->itemType();
+ return QList<QSharedPointer<QMapboxGLStyleChange>>();
+ }
+}
+
+QList<QSharedPointer<QMapboxGLStyleChange>> QMapboxGLStyleSetPaintProperty::fromMapItem(QDeclarativeRectangleMapItem *item)
+{
+ QList<QSharedPointer<QMapboxGLStyleChange>> changes;
+ changes.reserve(3);
+
+ const QString id = getId(item);
+
+ changes << QSharedPointer<QMapboxGLStyleChange>(
+ new QMapboxGLStyleSetPaintProperty(id, QStringLiteral("fill-opacity"), item->mapItemOpacity()));
+ changes << QSharedPointer<QMapboxGLStyleChange>(
+ new QMapboxGLStyleSetPaintProperty(id, QStringLiteral("fill-color"), item->color()));
+ changes << QSharedPointer<QMapboxGLStyleChange>(
+ new QMapboxGLStyleSetPaintProperty(id, QStringLiteral("fill-outline-color"), item->border()->color()));
+
+ return changes;
+}
+
+QList<QSharedPointer<QMapboxGLStyleChange>> QMapboxGLStyleSetPaintProperty::fromMapItem(QDeclarativePolygonMapItem *item)
+{
+ QList<QSharedPointer<QMapboxGLStyleChange>> changes;
+ changes.reserve(3);
+
+ const QString id = getId(item);
+
+ changes << QSharedPointer<QMapboxGLStyleChange>(
+ new QMapboxGLStyleSetPaintProperty(id, QStringLiteral("fill-opacity"), item->mapItemOpacity()));
+ changes << QSharedPointer<QMapboxGLStyleChange>(
+ new QMapboxGLStyleSetPaintProperty(id, QStringLiteral("fill-color"), item->color()));
+ changes << QSharedPointer<QMapboxGLStyleChange>(
+ new QMapboxGLStyleSetPaintProperty(id, QStringLiteral("fill-outline-color"), item->border()->color()));
+
+ return changes;
+}
+
+QList<QSharedPointer<QMapboxGLStyleChange>> QMapboxGLStyleSetPaintProperty::fromMapItem(QDeclarativePolylineMapItem *item)
+{
+ QList<QSharedPointer<QMapboxGLStyleChange>> changes;
+ changes.reserve(3);
+
+ const QString id = getId(item);
+
+ changes << QSharedPointer<QMapboxGLStyleChange>(
+ new QMapboxGLStyleSetPaintProperty(id, QStringLiteral("line-opacity"), item->mapItemOpacity()));
+ changes << QSharedPointer<QMapboxGLStyleChange>(
+ new QMapboxGLStyleSetPaintProperty(id, QStringLiteral("line-color"), item->line()->color()));
+ changes << QSharedPointer<QMapboxGLStyleChange>(
+ new QMapboxGLStyleSetPaintProperty(id, QStringLiteral("line-width"), item->line()->width()));
+
+ return changes;
+}
+
+// QMapboxGLStyleAddLayer
+
+void QMapboxGLStyleAddLayer::apply(QMapboxGL *map)
+{
+ map->addLayer(m_params);
+}
+
+QSharedPointer<QMapboxGLStyleChange> QMapboxGLStyleAddLayer::fromMapParameter(QGeoMapParameter *param)
+{
+ Q_ASSERT(param->type() == "layer");
+
+ auto layer = new QMapboxGLStyleAddLayer();
+ layer->m_params[QStringLiteral("id")] = param->property("name");
+ layer->m_params[QStringLiteral("source")] = param->property("source");
+ layer->m_params[QStringLiteral("type")] = param->property("layerType");
+
+ if (param->property("sourceLayer").isValid()) {
+ layer->m_params[QStringLiteral("source-layer")] = param->property("sourceLayer");
+ }
+
+ return QSharedPointer<QMapboxGLStyleChange>(layer);
+}
+
+QSharedPointer<QMapboxGLStyleChange> QMapboxGLStyleAddLayer::fromFeature(const QMapbox::Feature &feature)
+{
+ auto layer = new QMapboxGLStyleAddLayer();
+ layer->m_params[QStringLiteral("id")] = feature.id;
+ layer->m_params[QStringLiteral("source")] = feature.id;
+
+ switch (feature.type) {
+ case QMapbox::Feature::PointType:
+ layer->m_params[QStringLiteral("type")] = QStringLiteral("circle");
+ break;
+ case QMapbox::Feature::LineStringType:
+ layer->m_params[QStringLiteral("type")] = QStringLiteral("line");
+ break;
+ case QMapbox::Feature::PolygonType:
+ layer->m_params[QStringLiteral("type")] = QStringLiteral("fill");
+ break;
+ }
+
+ return QSharedPointer<QMapboxGLStyleChange>(layer);
+}
+
+
+// QMapboxGLStyleRemoveLayer
+
+void QMapboxGLStyleRemoveLayer::apply(QMapboxGL *map)
+{
+ map->removeLayer(m_id);
+}
+
+QMapboxGLStyleRemoveLayer::QMapboxGLStyleRemoveLayer(const QString &id) : m_id(id)
+{
+}
+
+
+// QMapboxGLStyleAddSource
+
+void QMapboxGLStyleAddSource::apply(QMapboxGL *map)
+{
+ map->updateSource(m_id, m_params);
+}
+
+QSharedPointer<QMapboxGLStyleChange> QMapboxGLStyleAddSource::fromMapParameter(QGeoMapParameter *param)
+{
+ Q_ASSERT(param->type() == "source");
+
+ static const QStringList acceptedSourceTypes = QStringList()
+ << QStringLiteral("vector") << QStringLiteral("raster") << QStringLiteral("geojson");
+
+ QString sourceType = param->property("sourceType").toString();
+
+ auto source = new QMapboxGLStyleAddSource();
+ source->m_id = param->property("name").toString();
+ source->m_params[QStringLiteral("type")] = sourceType;
+
+ switch (acceptedSourceTypes.indexOf(sourceType)) {
+ case -1:
+ qWarning() << "Invalid value for property 'sourceType': " + sourceType;
+ break;
+ case 0: // vector
+ case 1: // raster
+ source->m_params[QStringLiteral("url")] = param->property("url");
+ break;
+ case 2: { // geojson
+ auto data = param->property("data").toString();
+ if (data.startsWith(':')) {
+ QFile geojson(data);
+ geojson.open(QIODevice::ReadOnly);
+ source->m_params[QStringLiteral("data")] = geojson.readAll();
+ } else {
+ source->m_params[QStringLiteral("data")] = data.toUtf8();
+ }
+ } break;
+ }
+
+ return QSharedPointer<QMapboxGLStyleChange>(source);
+}
+
+QSharedPointer<QMapboxGLStyleChange> QMapboxGLStyleAddSource::fromFeature(const QMapbox::Feature &feature)
+{
+ auto source = new QMapboxGLStyleAddSource();
+
+ source->m_id = feature.id.toString();
+ source->m_params[QStringLiteral("type")] = QStringLiteral("geojson");
+ source->m_params[QStringLiteral("data")] = QVariant::fromValue<QMapbox::Feature>(feature);
+
+ return QSharedPointer<QMapboxGLStyleChange>(source);
+}
+
+QSharedPointer<QMapboxGLStyleChange> QMapboxGLStyleAddSource::fromMapItem(QDeclarativeGeoMapItemBase *item)
+{
+ return fromFeature(featureFromMapItem(item));
+}
+
+
+// QMapboxGLStyleRemoveSource
+
+void QMapboxGLStyleRemoveSource::apply(QMapboxGL *map)
+{
+ map->removeSource(m_id);
+}
+
+QMapboxGLStyleRemoveSource::QMapboxGLStyleRemoveSource(const QString &id) : m_id(id)
+{
+}
+
+
+// QMapboxGLStyleSetFilter
+
+void QMapboxGLStyleSetFilter::apply(QMapboxGL *map)
+{
+ map->setFilter(m_layer, m_filter);
+}
+
+QSharedPointer<QMapboxGLStyleChange> QMapboxGLStyleSetFilter::fromMapParameter(QGeoMapParameter *param)
+{
+ Q_ASSERT(param->type() == "filter");
+
+ auto filter = new QMapboxGLStyleSetFilter();
+ filter->m_layer = param->property("layer").toString();
+ filter->m_filter = param->property("filter");
+
+ return QSharedPointer<QMapboxGLStyleChange>(filter);
+}
+
+
+// QMapboxGLStyleAddImage
+
+void QMapboxGLStyleAddImage::apply(QMapboxGL *map)
+{
+ map->addImage(m_name, m_sprite);
+}
+
+QSharedPointer<QMapboxGLStyleChange> QMapboxGLStyleAddImage::fromMapParameter(QGeoMapParameter *param)
+{
+ Q_ASSERT(param->type() == "image");
+
+ auto image = new QMapboxGLStyleAddImage();
+ image->m_name = param->property("name").toString();
+ image->m_sprite = QImage(param->property("sprite").toString());
+
+ return QSharedPointer<QMapboxGLStyleChange>(image);
+}
diff --git a/src/plugins/geoservices/mapboxgl/qmapboxglstylechange_p.h b/src/plugins/geoservices/mapboxgl/qmapboxglstylechange_p.h
new file mode 100644
index 00000000..43b22afb
--- /dev/null
+++ b/src/plugins/geoservices/mapboxgl/qmapboxglstylechange_p.h
@@ -0,0 +1,188 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 Mapbox, Inc.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the QtLocation module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL3$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPLv3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or later as published by the Free
+** Software Foundation and appearing in the file LICENSE.GPL included in
+** the packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QQMAPBOXGLSTYLECHANGE_P_H
+#define QQMAPBOXGLSTYLECHANGE_P_H
+
+#include <QtCore/QList>
+#include <QtCore/QSharedPointer>
+#include <QtCore/QString>
+#include <QtCore/QVariant>
+#include <QtCore/QVariantMap>
+#include <QtGui/QImage>
+#include <QtLocation/private/qdeclarativecirclemapitem_p.h>
+#include <QtLocation/private/qdeclarativegeomapitembase_p.h>
+#include <QtLocation/private/qdeclarativepolygonmapitem_p.h>
+#include <QtLocation/private/qdeclarativepolylinemapitem_p.h>
+#include <QtLocation/private/qdeclarativerectanglemapitem_p.h>
+#include <QtLocation/private/qgeomapparameter_p.h>
+
+#include <QMapboxGL>
+
+class QMapboxGLStyleChange
+{
+public:
+ virtual ~QMapboxGLStyleChange() = default;
+
+ static QList<QSharedPointer<QMapboxGLStyleChange>> addMapParameter(QGeoMapParameter *);
+ static QList<QSharedPointer<QMapboxGLStyleChange>> addMapItem(QDeclarativeGeoMapItemBase *);
+ static QList<QSharedPointer<QMapboxGLStyleChange>> removeMapItem(QDeclarativeGeoMapItemBase *);
+
+ virtual void apply(QMapboxGL *map) = 0;
+};
+
+class QMapboxGLStyleSetLayoutProperty : public QMapboxGLStyleChange
+{
+public:
+ static QList<QSharedPointer<QMapboxGLStyleChange>> fromMapParameter(QGeoMapParameter *);
+
+ void apply(QMapboxGL *map) Q_DECL_OVERRIDE;
+
+private:
+ QMapboxGLStyleSetLayoutProperty() = default;
+
+ QString m_layer;
+ QString m_property;
+ QVariant m_value;
+};
+
+class QMapboxGLStyleSetPaintProperty : public QMapboxGLStyleChange
+{
+public:
+ static QList<QSharedPointer<QMapboxGLStyleChange>> fromMapParameter(QGeoMapParameter *);
+ static QList<QSharedPointer<QMapboxGLStyleChange>> fromMapItem(QDeclarativeGeoMapItemBase *);
+
+ void apply(QMapboxGL *map) Q_DECL_OVERRIDE;
+
+private:
+ static QList<QSharedPointer<QMapboxGLStyleChange>> fromMapItem(QDeclarativeRectangleMapItem *);
+ static QList<QSharedPointer<QMapboxGLStyleChange>> fromMapItem(QDeclarativePolygonMapItem *);
+ static QList<QSharedPointer<QMapboxGLStyleChange>> fromMapItem(QDeclarativePolylineMapItem *);
+
+ QMapboxGLStyleSetPaintProperty() = default;
+ QMapboxGLStyleSetPaintProperty(const QString& layer, const QString& property, const QVariant &value);
+
+ QString m_layer;
+ QString m_property;
+ QVariant m_value;
+ QString m_class;
+};
+
+class QMapboxGLStyleAddLayer : public QMapboxGLStyleChange
+{
+public:
+ static QSharedPointer<QMapboxGLStyleChange> fromMapParameter(QGeoMapParameter *);
+ static QSharedPointer<QMapboxGLStyleChange> fromFeature(const QMapbox::Feature &feature);
+
+ void apply(QMapboxGL *map) Q_DECL_OVERRIDE;
+
+private:
+ QMapboxGLStyleAddLayer() = default;
+
+ QVariantMap m_params;
+};
+
+class QMapboxGLStyleRemoveLayer : public QMapboxGLStyleChange
+{
+public:
+ explicit QMapboxGLStyleRemoveLayer(const QString &id);
+
+ void apply(QMapboxGL *map) Q_DECL_OVERRIDE;
+
+private:
+ QMapboxGLStyleRemoveLayer() = default;
+
+ QString m_id;
+};
+
+class QMapboxGLStyleAddSource : public QMapboxGLStyleChange
+{
+public:
+ static QSharedPointer<QMapboxGLStyleChange> fromMapParameter(QGeoMapParameter *);
+ static QSharedPointer<QMapboxGLStyleChange> fromFeature(const QMapbox::Feature &feature);
+ static QSharedPointer<QMapboxGLStyleChange> fromMapItem(QDeclarativeGeoMapItemBase *);
+
+ void apply(QMapboxGL *map) Q_DECL_OVERRIDE;
+
+private:
+ QMapboxGLStyleAddSource() = default;
+
+ QString m_id;
+ QVariantMap m_params;
+};
+
+class QMapboxGLStyleRemoveSource : public QMapboxGLStyleChange
+{
+public:
+ explicit QMapboxGLStyleRemoveSource(const QString &id);
+
+ void apply(QMapboxGL *map) Q_DECL_OVERRIDE;
+
+private:
+ QMapboxGLStyleRemoveSource() = default;
+
+ QString m_id;
+};
+
+class QMapboxGLStyleSetFilter : public QMapboxGLStyleChange
+{
+public:
+ static QSharedPointer<QMapboxGLStyleChange> fromMapParameter(QGeoMapParameter *);
+
+ void apply(QMapboxGL *map) Q_DECL_OVERRIDE;
+
+private:
+ QMapboxGLStyleSetFilter() = default;
+
+ QString m_layer;
+ QVariant m_filter;
+};
+
+class QMapboxGLStyleAddImage : public QMapboxGLStyleChange
+{
+public:
+ static QSharedPointer<QMapboxGLStyleChange> fromMapParameter(QGeoMapParameter *);
+
+ void apply(QMapboxGL *map) Q_DECL_OVERRIDE;
+
+private:
+ QMapboxGLStyleAddImage() = default;
+
+ QString m_name;
+ QImage m_sprite;
+};
+
+#endif // QQMAPBOXGLSTYLECHANGE_P_H