From 854b3bc39b2a84656ca2c120865bf926d7a4b47d Mon Sep 17 00:00:00 2001 From: "Thiago Marcos P. Santos" Date: Wed, 22 Jul 2015 14:12:34 +0300 Subject: [Qt] Add a Qt wrapper aroung mbgl::Map Signed-off-by: Bruno Abinader Signed-off-by: Thiago Marcos P. Santos --- platform/qt/include/QMapboxGL | 1 + platform/qt/include/qmapboxgl.hpp | 111 ++++++++++++++ platform/qt/src/qmapboxgl.cpp | 314 ++++++++++++++++++++++++++++++++++++++ platform/qt/src/qmapboxgl_p.hpp | 50 ++++++ 4 files changed, 476 insertions(+) create mode 100644 platform/qt/include/QMapboxGL create mode 100644 platform/qt/include/qmapboxgl.hpp create mode 100644 platform/qt/src/qmapboxgl.cpp create mode 100644 platform/qt/src/qmapboxgl_p.hpp diff --git a/platform/qt/include/QMapboxGL b/platform/qt/include/QMapboxGL new file mode 100644 index 0000000000..15b55a9abe --- /dev/null +++ b/platform/qt/include/QMapboxGL @@ -0,0 +1 @@ +#include "qmapboxgl.hpp" diff --git a/platform/qt/include/qmapboxgl.hpp b/platform/qt/include/qmapboxgl.hpp new file mode 100644 index 0000000000..09537963c0 --- /dev/null +++ b/platform/qt/include/qmapboxgl.hpp @@ -0,0 +1,111 @@ +#ifndef QMAPBOXGL_H +#define QMAPBOXGL_H + +#include +#include +#include + +class QImage; +class QSize; +class QString; + +class QMapboxGLPrivate; + +// This header follows the Qt coding style: https://wiki.qt.io/Qt_Coding_Style + +class Q_DECL_EXPORT QMapboxGLSettings +{ +public: + QMapboxGLSettings(); + + unsigned cacheDatabaseMaximumSize() const; + void setCacheDatabaseMaximumSize(unsigned); + + QString cacheDatabasePath() const; + void setCacheDatabasePath(const QString &); + + QString assetPath() const; + void setAssetPath(const QString &); + + QString accessToken() const; + void setAccessToken(const QString &); + +private: + unsigned m_cacheMaximumSize; + QString m_cacheDatabasePath; + QString m_assetPath; + QString m_accessToken; +}; + +class Q_DECL_EXPORT QMapboxGL : public QObject +{ + Q_OBJECT + Q_PROPERTY(double latitude READ latitude WRITE setLatitude) + Q_PROPERTY(double longitude READ longitude WRITE setLongitude) + Q_PROPERTY(double zoom READ zoom WRITE setZoom) + Q_PROPERTY(double bearing READ bearing WRITE setBearing) + +public: + typedef QPair Coordinate; + + QMapboxGL(QObject *parent = 0, const QMapboxGLSettings& = QMapboxGLSettings()); + virtual ~QMapboxGL(); + + void setStyleJSON(const QString &); + void setStyleURL(const QString &); + + double latitude() const; + void setLatitude(double latitude); + + double longitude() const; + void setLongitude(double longitude); + + double zoom() const; + void setZoom(double zoom, int milliseconds = 0); + + double minimumZoom() const; + double maximumZoom() const; + + double bearing() const; + void setBearing(double degrees, int milliseconds = 0); + void setBearing(double degrees, const QPointF ¢er); + + double pitch() const; + void setPitch(double pitch, int milliseconds = 0); + + Coordinate coordinate() const; + void setCoordinate(const Coordinate &, int milliseconds = 0); + void setCoordinateZoom(const Coordinate &, double zoom, int milliseconds = 0); + + void setGestureInProgress(bool inProgress); + + bool isRotating() const; + bool isScaling() const; + bool isPanning() const; + bool isFullyLoaded() const; + + void moveBy(const QPointF &offset); + void scaleBy(double scale, const QPointF ¢er = QPointF(), int milliseconds = 0); + void rotateBy(const QPointF &first, const QPointF &second); + + void resize(const QSize &size); + + void addAnnotationIcon(const QString &name, const QImage &sprite); + + QPointF pixelForCoordinate(const Coordinate &) const; + Coordinate coordinateForPixel(const QPointF &) const; + +public slots: + void render(); + +signals: + void needsRendering(); + void mapRegionDidChange(); + +private: + Q_DISABLE_COPY(QMapboxGL) + + QMapboxGLPrivate *d_ptr; +}; + +#endif // QMAPBOXGL_H diff --git a/platform/qt/src/qmapboxgl.cpp b/platform/qt/src/qmapboxgl.cpp new file mode 100644 index 0000000000..e648354e54 --- /dev/null +++ b/platform/qt/src/qmapboxgl.cpp @@ -0,0 +1,314 @@ +#include "qmapboxgl_p.hpp" + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include + +QMapboxGLSettings::QMapboxGLSettings() + : m_cacheMaximumSize(mbgl::util::DEFAULT_MAX_CACHE_SIZE) + , m_cacheDatabasePath(":memory:") + , m_assetPath(QCoreApplication::applicationDirPath()) +{ +} + +unsigned QMapboxGLSettings::cacheDatabaseMaximumSize() const +{ + return m_cacheMaximumSize; +} + +void QMapboxGLSettings::setCacheDatabaseMaximumSize(unsigned size) +{ + m_cacheMaximumSize = size; +} + +QString QMapboxGLSettings::cacheDatabasePath() const +{ + return m_cacheDatabasePath; +} + +void QMapboxGLSettings::setCacheDatabasePath(const QString &path) +{ + m_cacheDatabasePath = path; +} + +QString QMapboxGLSettings::assetPath() const +{ + return m_assetPath; +} + +void QMapboxGLSettings::setAssetPath(const QString &path) +{ + m_assetPath = path; +} + +QString QMapboxGLSettings::accessToken() const { + return m_accessToken; +} + +void QMapboxGLSettings::setAccessToken(const QString &token) +{ + m_accessToken = token; +} + +QMapboxGL::QMapboxGL(QObject *parent_, const QMapboxGLSettings &settings) + : QObject(parent_) + , d_ptr(new QMapboxGLPrivate(this, settings)) +{ + d_ptr->fileSourceObj->setAccessToken(settings.accessToken().toStdString()); + + d_ptr->mapObj = std::make_unique(*d_ptr, *d_ptr->fileSourceObj, + mbgl::MapMode::Continuous, mbgl::GLContextMode::Shared); +} + +QMapboxGL::~QMapboxGL() +{ + delete d_ptr; +} + +void QMapboxGL::setStyleJSON(const QString &style) +{ + d_ptr->mapObj->setStyleJSON(style.toUtf8().constData()); +} + +void QMapboxGL::setStyleURL(const QString &url) +{ + d_ptr->mapObj->setStyleURL(url.toUtf8().constData()); +} + +double QMapboxGL::latitude() const +{ + return d_ptr->mapObj->getLatLng().latitude; +} + +void QMapboxGL::setLatitude(double latitude_) +{ + d_ptr->mapObj->setLatLng(mbgl::LatLng { latitude_, longitude() }); +} + +double QMapboxGL::longitude() const +{ + return d_ptr->mapObj->getLatLng().longitude; +} + +void QMapboxGL::setLongitude(double longitude_) +{ + d_ptr->mapObj->setLatLng(mbgl::LatLng { latitude(), longitude_ }); +} + +double QMapboxGL::zoom() const +{ + return d_ptr->mapObj->getZoom(); +} + +void QMapboxGL::setZoom(double zoom_, int milliseconds) +{ + d_ptr->mapObj->setZoom(zoom_, std::chrono::milliseconds(milliseconds)); +} + +double QMapboxGL::minimumZoom() const +{ + return d_ptr->mapObj->getMinZoom(); +} + +double QMapboxGL::maximumZoom() const +{ + return d_ptr->mapObj->getMaxZoom(); +} + +QMapboxGL::Coordinate QMapboxGL::coordinate() const +{ + const mbgl::LatLng& latLng = d_ptr->mapObj->getLatLng(); + return Coordinate(latLng.latitude, latLng.longitude); +} + +void QMapboxGL::setCoordinate(const Coordinate &coordinate_, int milliseconds) +{ + d_ptr->mapObj->setLatLng( + mbgl::LatLng { coordinate_.first, coordinate_.second }, + std::chrono::milliseconds(milliseconds)); +} + +void QMapboxGL::setCoordinateZoom(const Coordinate &coordinate_, double zoom_, int milliseconds) +{ + d_ptr->mapObj->setLatLngZoom( + mbgl::LatLng { coordinate_.first, coordinate_.second }, zoom_, + std::chrono::milliseconds(milliseconds)); +} + +double QMapboxGL::bearing() const +{ + return d_ptr->mapObj->getBearing(); +} + +void QMapboxGL::setBearing(double degrees, int milliseconds) +{ + d_ptr->mapObj->setBearing(degrees, std::chrono::milliseconds(milliseconds)); +} + +void QMapboxGL::setBearing(double degrees, const QPointF ¢er) +{ + d_ptr->mapObj->setBearing(degrees, mbgl::ScreenCoordinate { center.x(), center.y() }); +} + +double QMapboxGL::pitch() const +{ + return d_ptr->mapObj->getPitch(); +} + +void QMapboxGL::setPitch(double pitch_, int milliseconds) +{ + d_ptr->mapObj->setPitch(pitch_, std::chrono::milliseconds(milliseconds)); +} + +void QMapboxGL::setGestureInProgress(bool inProgress) +{ + d_ptr->mapObj->setGestureInProgress(inProgress); +} + +bool QMapboxGL::isRotating() const +{ + return d_ptr->mapObj->isRotating(); +} + +bool QMapboxGL::isScaling() const +{ + return d_ptr->mapObj->isScaling(); +} + +bool QMapboxGL::isPanning() const +{ + return d_ptr->mapObj->isPanning(); +} + +bool QMapboxGL::isFullyLoaded() const +{ + return d_ptr->mapObj->isFullyLoaded(); +} + +void QMapboxGL::moveBy(const QPointF &offset) +{ + d_ptr->mapObj->moveBy(mbgl::ScreenCoordinate { offset.x(), offset.y() }); +} + +void QMapboxGL::scaleBy(double scale_, const QPointF ¢er, int milliseconds) { + d_ptr->mapObj->scaleBy( + scale_, mbgl::ScreenCoordinate { center.x(), center.y() }, + std::chrono::milliseconds(milliseconds)); +} + +void QMapboxGL::rotateBy(const QPointF &first, const QPointF &second) +{ + d_ptr->mapObj->rotateBy( + mbgl::ScreenCoordinate { first.x(), first.y() }, + mbgl::ScreenCoordinate { second.x(), second.y() }); +} + +void QMapboxGL::resize(const QSize& size) +{ + if (d_ptr->size == size) return; + + d_ptr->size = size; + d_ptr->mapObj->update(mbgl::Update::Dimensions); +} + +void QMapboxGL::addAnnotationIcon(const QString &name, const QImage &sprite) +{ + if (sprite.isNull()) return; + + const QImage swapped = sprite + .rgbSwapped() + .convertToFormat(QImage::Format_ARGB32_Premultiplied); + + auto img = std::make_unique(swapped.byteCount()); + memcpy(img.get(), swapped.constBits(), swapped.byteCount()); + + d_ptr->mapObj->addAnnotationIcon(name.toStdString(), std::make_shared( + mbgl::PremultipliedImage { size_t(swapped.width()), size_t(swapped.height()), std::move(img) }, 1.0)); +} + +QPointF QMapboxGL::pixelForCoordinate(const Coordinate &coordinate_) const +{ + const mbgl::vec2 pixel = + d_ptr->mapObj->pixelForLatLng(mbgl::LatLng { coordinate_.first, coordinate_.second }); + + return QPointF(pixel.x, pixel.y); +} + +QMapboxGL::Coordinate QMapboxGL::coordinateForPixel(const QPointF &pixel) const +{ + const mbgl::LatLng latLng = + d_ptr->mapObj->latLngForPixel(mbgl::ScreenCoordinate { pixel.x(), pixel.y() }); + + return Coordinate(latLng.latitude, latLng.longitude); +} + +void QMapboxGL::render() +{ + d_ptr->mapObj->render(); +} + +QMapboxGLPrivate::QMapboxGLPrivate(QMapboxGL *q, const QMapboxGLSettings &settings) + : QObject(q) + , size(0, 0) + , q_ptr(q) + , fileSourceObj(std::make_unique( + settings.cacheDatabasePath().toStdString(), + settings.assetPath().toStdString(), + settings.cacheDatabaseMaximumSize())) + , mapObj(std::make_unique( + *this, *fileSourceObj, + mbgl::MapMode::Continuous, + mbgl::GLContextMode::Shared)) +{ + connect(this, SIGNAL(needsRendering()), q_ptr, SIGNAL(needsRendering())); + connect(this, SIGNAL(mapRegionDidChange()), q_ptr, SIGNAL(mapRegionDidChange())); +} + +QMapboxGLPrivate::~QMapboxGLPrivate() +{ +} + +float QMapboxGLPrivate::getPixelRatio() const +{ + // FIXME: Should handle pixel ratio. + return 1.0; +} + +std::array QMapboxGLPrivate::getSize() const +{ + return {{ static_cast(size.width()), static_cast(size.height()) }}; +} + +std::array QMapboxGLPrivate::getFramebufferSize() const +{ + return getSize(); +} + +void QMapboxGLPrivate::invalidate() +{ + emit needsRendering(); +} + +void QMapboxGLPrivate::notifyMapChange(mbgl::MapChange change) +{ + // Map thread. + switch (change) { + case mbgl::MapChangeRegionDidChange: + case mbgl::MapChangeRegionDidChangeAnimated: + case mbgl::MapChangeRegionIsChanging: + emit mapRegionDidChange(); + break; + default: + break; + } +} diff --git a/platform/qt/src/qmapboxgl_p.hpp b/platform/qt/src/qmapboxgl_p.hpp new file mode 100644 index 0000000000..4b2b5b5252 --- /dev/null +++ b/platform/qt/src/qmapboxgl_p.hpp @@ -0,0 +1,50 @@ +#ifndef QMAPBOXGL_P_H +#define QMAPBOXGL_P_H + +#include +#include +#include +#include + +#include +#include +#include + +#include + +class QMapboxGL; +class QMapboxGLSettings; + +class QMapboxGLPrivate : public QObject, public mbgl::View +{ + Q_OBJECT + +public: + explicit QMapboxGLPrivate(QMapboxGL *q, const QMapboxGLSettings &); + virtual ~QMapboxGLPrivate(); + + // mbgl::View implementation. + float getPixelRatio() const final; + std::array getSize() const final; + std::array getFramebufferSize() const final; + + void activate() final {} + void deactivate() final {} + void invalidate() final; + void notifyMapChange(mbgl::MapChange change) final; + + QSize size; + + QMapboxGL *q_ptr = nullptr; + + mbgl::util::RunLoop loop; + + std::unique_ptr fileSourceObj; + std::unique_ptr mapObj; + +signals: + void mapRegionDidChange(); + void needsRendering(); +}; + +#endif // QMAPBOXGL_P_H -- cgit v1.2.1