Skip to content

Commit

Permalink
Improve GeoJSON and image source handling (#164)
Browse files Browse the repository at this point in the history
  • Loading branch information
ntadej authored Sep 6, 2024
1 parent f04dedd commit b2b74d6
Show file tree
Hide file tree
Showing 16 changed files with 293 additions and 12 deletions.
2 changes: 2 additions & 0 deletions src/core/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ set(MLNQtCore_Headers

style/style_parameter.hpp
style/filter_parameter.hpp
style/image_parameter.hpp
style/layer_parameter.hpp
style/source_parameter.hpp
)
Expand Down Expand Up @@ -68,6 +69,7 @@ target_sources(

style/style_parameter.cpp
style/filter_parameter.cpp
style/image_parameter.cpp
style/layer_parameter.cpp
style/source_parameter.cpp

Expand Down
61 changes: 61 additions & 0 deletions src/core/style/image_parameter.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
// Copyright (C) 2023 MapLibre contributors

// SPDX-License-Identifier: BSD-2-Clause

#include "image_parameter.hpp"

#include "style_parameter.hpp"

namespace QMapLibre {

/*!
\class ImageParameter
\brief A helper utility to manage image sources.
\ingroup QMapLibre
\headerfile image_parameter.hpp <QMapLibre/ImageParameter>
*/

/*!
\brief Default constructor
*/
ImageParameter::ImageParameter(QObject *parent)
: StyleParameter(parent) {}

ImageParameter::~ImageParameter() = default;

/*!
\fn void ImageParameter::sourceUpdated()
\brief Signal emitted when the image source is updated.
*/

/*!
\brief Get the image source.
\return image source as \c QString.
*/
QString ImageParameter::source() const {
return m_source;
}

/*!
\brief Set the image source.
\param source image source to set.
\ref sourceUpdated() signal is emitted when the image source is updated.
*/
void ImageParameter::setSource(const QString &source) {
if (m_source == source) {
return;
}

m_source = source;

Q_EMIT sourceUpdated();
}

/*!
\var ImageParameter::m_source
\brief image source
*/

} // namespace QMapLibre
37 changes: 37 additions & 0 deletions src/core/style/image_parameter.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
// Copyright (C) 2023 MapLibre contributors

// SPDX-License-Identifier: BSD-2-Clause

#ifndef QMAPLIBRE_IMAGE_PARAMETER_H
#define QMAPLIBRE_IMAGE_PARAMETER_H

#include "style_parameter.hpp"

#include <QMapLibre/Export>

#include <QtCore/QObject>
#include <QtCore/QString>

namespace QMapLibre {

class Q_MAPLIBRE_CORE_EXPORT ImageParameter : public StyleParameter {
Q_OBJECT
public:
explicit ImageParameter(QObject *parent = nullptr);
~ImageParameter() override;

[[nodiscard]] QString source() const;
void setSource(const QString &source);

Q_SIGNALS:
void sourceUpdated();

protected:
QString m_source;

Q_DISABLE_COPY(ImageParameter)
};

} // namespace QMapLibre

#endif // QMAPLIBRE_IMAGE_PARAMETER_H
18 changes: 13 additions & 5 deletions src/core/style/image_style_change.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,17 @@ namespace QMapLibre {
/*! \cond PRIVATE */

// StyleAddImage
StyleAddImage::StyleAddImage(const StyleParameter *parameter)
: m_id(parameter->property("id").toString()),
m_sprite(QImage(parameter->property("sprite").toString())) {}
StyleAddImage::StyleAddImage(QString id, const QString &spriteUrl)
: m_id(std::move(id)),
m_sprite(QImage(spriteUrl)) {}

StyleAddImage::StyleAddImage(QString id, QImage sprite)
: m_id(std::move(id)),
m_sprite(std::move(sprite)) {}

StyleAddImage::StyleAddImage(const ImageParameter *parameter)
: m_id(parameter->styleId()),
m_sprite(QImage(parameter->source())) {}

void StyleAddImage::apply(Map *map) {
if (map == nullptr) {
Expand All @@ -27,8 +35,8 @@ void StyleAddImage::apply(Map *map) {
StyleRemoveImage::StyleRemoveImage(QString id)
: m_id(std::move(id)) {}

StyleRemoveImage::StyleRemoveImage(const StyleParameter *parameter)
: m_id(parameter->property("id").toString()) {}
StyleRemoveImage::StyleRemoveImage(const ImageParameter *parameter)
: m_id(parameter->styleId()) {}

void StyleRemoveImage::apply(Map *map) {
if (map == nullptr) {
Expand Down
8 changes: 5 additions & 3 deletions src/core/style/image_style_change_p.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@
#pragma once

#include "export_core.hpp"
#include "image_parameter.hpp"
#include "style_change_p.hpp"
#include "style_parameter.hpp"

#include <QtGui/QImage>

Expand All @@ -16,7 +16,9 @@ class Map;

class Q_MAPLIBRE_CORE_EXPORT StyleAddImage : public StyleChange {
public:
explicit StyleAddImage(const StyleParameter *parameter);
explicit StyleAddImage(QString id, const QString &spriteUrl);
explicit StyleAddImage(QString id, QImage sprite);
explicit StyleAddImage(const ImageParameter *parameter);

void apply(Map *map) override;

Expand All @@ -28,7 +30,7 @@ class Q_MAPLIBRE_CORE_EXPORT StyleAddImage : public StyleChange {
class Q_MAPLIBRE_CORE_EXPORT StyleRemoveImage : public StyleChange {
public:
explicit StyleRemoveImage(QString id);
explicit StyleRemoveImage(const StyleParameter *parameter);
explicit StyleRemoveImage(const ImageParameter *parameter);

void apply(Map *map) override;

Expand Down
3 changes: 1 addition & 2 deletions src/core/style/source_style_change.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@

#include "source_style_change_p.hpp"
#include "style/source_parameter.hpp"
#include "style/style_parameter.hpp"

#include <QMapLibre/Map>

Expand Down Expand Up @@ -50,7 +49,7 @@ StyleAddSource::StyleAddSource(const SourceParameter *parameter)
}
break;
case 3: { // geojson
const QString data = parameter->property("data").toString();
const QString data = parameter->parsedProperty("data").toString();
if (data.startsWith(':')) {
QFile geojson(data);
geojson.open(QIODevice::ReadOnly);
Expand Down
13 changes: 13 additions & 0 deletions src/core/style/style_change.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

// SPDX-License-Identifier: BSD-2-Clause

#include "image_style_change_p.hpp"
#include "layer_style_change_p.hpp"
#include "source_style_change_p.hpp"
#include "style_change_p.hpp"
Expand Down Expand Up @@ -49,6 +50,12 @@ std::vector<std::unique_ptr<StyleChange>> StyleChange::addParameter(const StyleP
return changes;
}

const auto *imageParameter = qobject_cast<const ImageParameter *>(parameter);
if (imageParameter != nullptr) {
changes.push_back(std::make_unique<StyleAddImage>(imageParameter));
return changes;
}

const auto *filterParameter = qobject_cast<const FilterParameter *>(parameter);
if (filterParameter != nullptr) {
changes.push_back(std::make_unique<StyleSetFilter>(filterParameter));
Expand All @@ -73,6 +80,12 @@ std::vector<std::unique_ptr<StyleChange>> StyleChange::removeParameter(const Sty
return changes;
}

const auto *imageParameter = qobject_cast<const ImageParameter *>(parameter);
if (imageParameter != nullptr) {
changes.push_back(std::make_unique<StyleRemoveImage>(imageParameter));
return changes;
}

const auto *filterParameter = qobject_cast<const FilterParameter *>(parameter);
if (filterParameter != nullptr) {
changes.push_back(std::make_unique<StyleSetFilter>(filterParameter->styleId(), QVariantList()));
Expand Down
15 changes: 14 additions & 1 deletion src/core/style/style_parameter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,8 @@ namespace QMapLibre {
\ingroup QMapLibre
Should usually not be used directly, but rather through one of its subclasses
such as \ref SourceParameter or \ref LayerParameter.
such as \ref SourceParameter, \ref LayerParameter, \ref ImageParameter
or \ref FilterParameter.
*/

/*!
Expand Down Expand Up @@ -51,6 +52,18 @@ bool StyleParameter::operator==(const StyleParameter &other) const {
\return \c true if the style parameter is ready, \c false otherwise.
*/

/*!
\brief Get the property value
\param propertyName Name of the property to get.
\return Property value as \c QVariant or invalid \c QVariant if the property does not exist.
By default this directly reads the property value from the object.
It can be reimplemented from subclasses to provide custom parsing.
*/
QVariant StyleParameter::parsedProperty(const char *propertyName) const {
return property(propertyName);
}

/*!
\brief Check for property existence.
\param propertyName Name of the property to check.
Expand Down
1 change: 1 addition & 0 deletions src/core/style/style_parameter.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ class Q_MAPLIBRE_CORE_EXPORT StyleParameter : public QObject {

[[nodiscard]] inline bool isReady() const { return m_ready; };

[[nodiscard]] virtual QVariant parsedProperty(const char *propertyName) const;
bool hasProperty(const char *propertyName) const;
void updateProperty(const char *propertyName, const QVariant &value);

Expand Down
1 change: 1 addition & 0 deletions src/location/plugins/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,7 @@ set(Plugin_Sources
declarative_style.cpp declarative_style.hpp
declarative_style_parameter.hpp
declarative_filter_parameter.cpp declarative_filter_parameter.hpp
declarative_image_parameter.cpp declarative_image_parameter.hpp
declarative_layer_parameter.cpp declarative_layer_parameter.hpp
declarative_source_parameter.cpp declarative_source_parameter.hpp

Expand Down
12 changes: 12 additions & 0 deletions src/location/plugins/declarative_image_parameter.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
// Copyright (C) 2023 MapLibre contributors

// SPDX-License-Identifier: BSD-2-Clause

#include "declarative_image_parameter.hpp"

namespace QMapLibre {

DeclarativeImageParameter::DeclarativeImageParameter(QObject *parent)
: ImageParameter(parent) {}

} // namespace QMapLibre
36 changes: 36 additions & 0 deletions src/location/plugins/declarative_image_parameter.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
// Copyright (C) 2023 MapLibre contributors

// SPDX-License-Identifier: BSD-2-Clause

#pragma once

#include "declarative_style_parameter.hpp"

#include <QMapLibre/ImageParameter>

#include <QtQml/QQmlEngine>
#include <QtQml/QQmlParserStatus>

namespace QMapLibre {

class DeclarativeImageParameter : public ImageParameter, public QQmlParserStatus {
Q_OBJECT
QML_NAMED_ELEMENT(ImageParameter)
#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
QML_ADDED_IN_VERSION(3, 0)
#endif
Q_INTERFACES(QQmlParserStatus)
// from base class
Q_PROPERTY(QString styleId READ styleId WRITE setStyleId)
Q_PROPERTY(QString source READ source WRITE setSource NOTIFY sourceUpdated)
// this type must not declare any additional properties
public:
explicit DeclarativeImageParameter(QObject *parent = nullptr);
~DeclarativeImageParameter() override = default;

private:
// QQmlParserStatus implementation
MLN_DECLARATIVE_PARSER(DeclarativeImageParameter)
};

} // namespace QMapLibre
24 changes: 24 additions & 0 deletions src/location/plugins/declarative_source_parameter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,33 @@

#include "declarative_source_parameter.hpp"

#include <QtCore/QJsonDocument>

namespace QMapLibre {

DeclarativeSourceParameter::DeclarativeSourceParameter(QObject *parent)
: SourceParameter(parent) {}

QVariant DeclarativeSourceParameter::parsedProperty(const char *propertyName) const {
if (!hasProperty(propertyName)) {
return StyleParameter::parsedProperty(propertyName);
}

#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
if (property(propertyName).typeId() < QMetaType::User) {
#else
if (property(propertyName).type() < QVariant::UserType) {
#endif
return StyleParameter::parsedProperty(propertyName);
}

// explicitly handle only "data" for now
if (qstrcmp(propertyName, "data") != 0) {
return StyleParameter::parsedProperty(propertyName);
}

// convert QJSValue to JSON string
return QJsonDocument::fromVariant(property(propertyName).value<QJSValue>().toVariant()).toJson();
}

} // namespace QMapLibre
2 changes: 2 additions & 0 deletions src/location/plugins/declarative_source_parameter.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@ class DeclarativeSourceParameter : public SourceParameter, public QQmlParserStat
explicit DeclarativeSourceParameter(QObject *parent = nullptr);
~DeclarativeSourceParameter() override = default;

[[nodiscard]] QVariant parsedProperty(const char *propertyName) const override;

private:
// QQmlParserStatus implementation
MLN_DECLARATIVE_PARSER(DeclarativeSourceParameter)
Expand Down
6 changes: 6 additions & 0 deletions test/qml/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
if(COMMAND qt_add_executable)
qt_add_executable(test_mln_qml test_qml.cpp)

qt_add_resources(test_mln_qml test_fixtures
PREFIX "/"
BASE "../../vendor/maplibre-native/metrics/integration/sprites"
FILES "../../vendor/maplibre-native/metrics/integration/sprites/1x.png"
)
else()
add_executable(test_mln_qml test_qml.cpp)
endif()
Expand Down
Loading

0 comments on commit b2b74d6

Please sign in to comment.