[Qt] Add a Qt wrapper aroung mbgl::Map
Signed-off-by: Bruno Abinader <bruno@mapbox.com> Signed-off-by: Thiago Marcos P. Santos <thiago@mapbox.com>
This commit is contained in:
1
platform/qt/include/QMapboxGL
Normal file
1
platform/qt/include/QMapboxGL
Normal file
@@ -0,0 +1 @@
|
||||
#include "qmapboxgl.hpp"
|
||||
111
platform/qt/include/qmapboxgl.hpp
Normal file
111
platform/qt/include/qmapboxgl.hpp
Normal file
@@ -0,0 +1,111 @@
|
||||
#ifndef QMAPBOXGL_H
|
||||
#define QMAPBOXGL_H
|
||||
|
||||
#include <QObject>
|
||||
#include <QPair>
|
||||
#include <QPointF>
|
||||
|
||||
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<double, double> 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
|
||||
314
platform/qt/src/qmapboxgl.cpp
Normal file
314
platform/qt/src/qmapboxgl.cpp
Normal file
@@ -0,0 +1,314 @@
|
||||
#include "qmapboxgl_p.hpp"
|
||||
|
||||
#include <mbgl/annotation/point_annotation.hpp>
|
||||
#include <mbgl/gl/gl.hpp>
|
||||
#include <mbgl/map/map.hpp>
|
||||
#include <mbgl/sprite/sprite_image.hpp>
|
||||
#include <mbgl/util/geo.hpp>
|
||||
#include <mbgl/util/vec.hpp>
|
||||
|
||||
#include <QCoreApplication>
|
||||
#include <QImage>
|
||||
#include <QMapboxGL>
|
||||
#include <QString>
|
||||
|
||||
#include <memory>
|
||||
|
||||
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<mbgl::Map>(*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<uint8_t[]>(swapped.byteCount());
|
||||
memcpy(img.get(), swapped.constBits(), swapped.byteCount());
|
||||
|
||||
d_ptr->mapObj->addAnnotationIcon(name.toStdString(), std::make_shared<mbgl::SpriteImage>(
|
||||
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<double> 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<mbgl::DefaultFileSource>(
|
||||
settings.cacheDatabasePath().toStdString(),
|
||||
settings.assetPath().toStdString(),
|
||||
settings.cacheDatabaseMaximumSize()))
|
||||
, mapObj(std::make_unique<mbgl::Map>(
|
||||
*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<uint16_t, 2> QMapboxGLPrivate::getSize() const
|
||||
{
|
||||
return {{ static_cast<uint16_t>(size.width()), static_cast<uint16_t>(size.height()) }};
|
||||
}
|
||||
|
||||
std::array<uint16_t, 2> 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;
|
||||
}
|
||||
}
|
||||
50
platform/qt/src/qmapboxgl_p.hpp
Normal file
50
platform/qt/src/qmapboxgl_p.hpp
Normal file
@@ -0,0 +1,50 @@
|
||||
#ifndef QMAPBOXGL_P_H
|
||||
#define QMAPBOXGL_P_H
|
||||
|
||||
#include <mbgl/map/map.hpp>
|
||||
#include <mbgl/map/view.hpp>
|
||||
#include <mbgl/storage/default_file_source.hpp>
|
||||
#include <mbgl/util/run_loop.hpp>
|
||||
|
||||
#include <QMapboxGL>
|
||||
#include <QObject>
|
||||
#include <QSize>
|
||||
|
||||
#include <memory>
|
||||
|
||||
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<uint16_t, 2> getSize() const final;
|
||||
std::array<uint16_t, 2> 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<mbgl::DefaultFileSource> fileSourceObj;
|
||||
std::unique_ptr<mbgl::Map> mapObj;
|
||||
|
||||
signals:
|
||||
void mapRegionDidChange();
|
||||
void needsRendering();
|
||||
};
|
||||
|
||||
#endif // QMAPBOXGL_P_H
|
||||
Reference in New Issue
Block a user