summaryrefslogtreecommitdiff
path: root/platform/qt/src
diff options
context:
space:
mode:
authorSudarsana Babu Nagineni <sudarsana.babu@mapbox.com>2018-07-30 15:30:57 +0300
committerSudarsana Babu Nagineni <sudarsana.babu@mapbox.com>2018-08-06 16:55:30 +0300
commit0130c58fdd74edbbfe668f3125a9377554d7d605 (patch)
tree6be1c1d25d146e9273f04f40f2283e18048c17ac /platform/qt/src
parent7373abef92ed4911b91f9fca3d97784ed0d9e02e (diff)
downloadqtlocation-mapboxgl-0130c58fdd74edbbfe668f3125a9377554d7d605.tar.gz
Bump Mapbox GL Native
Bump version. mapbox-gl-native @ 377a6e42d687c419e6ae1012b8626336f5dfc1b6
Diffstat (limited to 'platform/qt/src')
-rw-r--r--platform/qt/src/qmapboxgl.cpp108
-rw-r--r--platform/qt/src/qmapboxgl_map_renderer.cpp67
-rw-r--r--platform/qt/src/qmapboxgl_map_renderer.hpp11
-rw-r--r--platform/qt/src/qmapboxgl_scheduler.cpp38
-rw-r--r--platform/qt/src/qmapboxgl_scheduler.hpp34
-rw-r--r--platform/qt/src/qt_geojson.cpp7
-rw-r--r--platform/qt/src/sqlite3.cpp107
7 files changed, 275 insertions, 97 deletions
diff --git a/platform/qt/src/qmapboxgl.cpp b/platform/qt/src/qmapboxgl.cpp
index 8c3355dc09..09479581bb 100644
--- a/platform/qt/src/qmapboxgl.cpp
+++ b/platform/qt/src/qmapboxgl.cpp
@@ -55,6 +55,10 @@
#include <QString>
#include <QStringList>
#include <QThreadStorage>
+#include <QVariant>
+#include <QVariantList>
+#include <QVariantMap>
+#include <QColor>
#include <memory>
@@ -703,7 +707,7 @@ double QMapboxGL::scale() const
void QMapboxGL::setScale(double scale_, const QPointF &center)
{
- d_ptr->mapObj->setZoom(mbgl::util::log2(scale_), mbgl::ScreenCoordinate { center.x(), center.y() });
+ d_ptr->mapObj->setZoom(::log2(scale_), mbgl::ScreenCoordinate { center.x(), center.y() });
}
/*!
@@ -1111,7 +1115,7 @@ void QMapboxGL::moveBy(const QPointF &offset)
can be used for implementing a pinch gesture.
*/
void QMapboxGL::scaleBy(double scale_, const QPointF &center) {
- d_ptr->mapObj->setZoom(d_ptr->mapObj->getZoom() + mbgl::util::log2(scale_), mbgl::ScreenCoordinate { center.x(), center.y() });
+ d_ptr->mapObj->setZoom(d_ptr->mapObj->getZoom() + ::log2(scale_), mbgl::ScreenCoordinate { center.x(), center.y() });
}
/*!
@@ -1466,6 +1470,23 @@ void QMapboxGL::removeLayer(const QString& id)
}
/*!
+ List of all existing layer ids from the current style.
+*/
+QList<QString> QMapboxGL::layerIds() const
+{
+ const auto &layers = d_ptr->mapObj->getStyle().getLayers();
+
+ QList<QString> layerIds;
+ layerIds.reserve(layers.size());
+
+ for (const mbgl::style::Layer *layer : layers) {
+ layerIds.append(QString::fromStdString(layer->getID()));
+ }
+
+ return layerIds;
+}
+
+/*!
Adds the \a image with the identifier \a id that can be used
later by a symbol layer.
@@ -1492,7 +1513,7 @@ void QMapboxGL::removeImage(const QString &id)
/*!
Adds a \a filter to a style \a layer using the format described in the \l
- {https://www.mapbox.com/mapbox-gl-style-spec/#types-filter}{Mapbox style specification}.
+ {https://www.mapbox.com/mapbox-gl-js/style-spec/#other-filter}{Mapbox style specification}.
Given a layer \c marker from an arbitrary GeoJSON source containing features of type \b
"Point" and \b "LineString", this example shows how to make sure the layer will only tag
@@ -1500,14 +1521,14 @@ void QMapboxGL::removeImage(const QString &id)
\code
QVariantList filterExpression;
- filterExpression.append("==");
- filterExpression.append("$type");
- filterExpression.append("Point");
+ filterExpression.push_back(QLatin1String("=="));
+ filterExpression.push_back(QLatin1String("$type"));
+ filterExpression.push_back(QLatin1String("Point"));
QVariantList filter;
- filter.append(filterExpression);
+ filter.push_back(filterExpression);
- map->setFilter("marker", filter);
+ map->setFilter(QLatin1String("marker"), filter);
\endcode
*/
void QMapboxGL::setFilter(const QString& layer, const QVariant& filter)
@@ -1555,6 +1576,77 @@ void QMapboxGL::setFilter(const QString& layer, const QVariant& filter)
qWarning() << "Layer doesn't support filters";
}
+QVariant QVariantFromValue(const mbgl::Value &value) {
+ return value.match(
+ [](const mbgl::NullValue) {
+ return QVariant();
+ }, [](const bool value_) {
+ return QVariant(value_);
+ }, [](const float value_) {
+ return QVariant(value_);
+ }, [](const int64_t value_) {
+ return QVariant(static_cast<qlonglong>(value_));
+ }, [](const double value_) {
+ return QVariant(value_);
+ }, [](const std::string &value_) {
+ return QVariant(value_.c_str());
+ }, [](const mbgl::Color &value_) {
+ return QColor(value_.r, value_.g, value_.b, value_.a);
+ }, [&](const std::vector<mbgl::Value> &vector) {
+ QVariantList list;
+ list.reserve(vector.size());
+ for (const auto &value_ : vector) {
+ list.push_back(QVariantFromValue(value_));
+ }
+ return list;
+ }, [&](const std::unordered_map<std::string, mbgl::Value> &map) {
+ QVariantMap varMap;
+ for (auto &item : map) {
+ varMap.insert(item.first.c_str(), QVariantFromValue(item.second));
+ }
+ return varMap;
+ }, [](const auto &) {
+ return QVariant();
+ });
+}
+
+/*!
+ Returns the current \a expression-based filter value applied to a style
+ \layer, if any.
+
+ Filter value types are described in the {https://www.mapbox.com/mapbox-gl-js/style-spec/#types}{Mapbox style specification}.
+*/
+QVariant QMapboxGL::getFilter(const QString &layer) const {
+ using namespace mbgl::style;
+ using namespace mbgl::style::conversion;
+
+ Layer* layer_ = d_ptr->mapObj->getStyle().getLayer(layer.toStdString());
+ if (!layer_) {
+ qWarning() << "Layer not found:" << layer;
+ return QVariant();
+ }
+
+ Filter filter_;
+
+ if (layer_->is<FillLayer>()) {
+ filter_ = layer_->as<FillLayer>()->getFilter();
+ } else if (layer_->is<LineLayer>()) {
+ filter_ = layer_->as<LineLayer>()->getFilter();
+ } else if (layer_->is<SymbolLayer>()) {
+ filter_ = layer_->as<SymbolLayer>()->getFilter();
+ } else if (layer_->is<CircleLayer>()) {
+ filter_ = layer_->as<CircleLayer>()->getFilter();
+ } else if (layer_->is<FillExtrusionLayer>()) {
+ filter_ = layer_->as<FillExtrusionLayer>()->getFilter();
+ } else {
+ qWarning() << "Layer doesn't support filters";
+ return QVariant();
+ }
+
+ auto serialized = filter_.serialize();
+ return QVariantFromValue(serialized);
+}
+
/*!
Creates the infrastructure needed for rendering the map. It
should be called before any call to render().
diff --git a/platform/qt/src/qmapboxgl_map_renderer.cpp b/platform/qt/src/qmapboxgl_map_renderer.cpp
index 7a9d1f6f78..acc4194498 100644
--- a/platform/qt/src/qmapboxgl_map_renderer.cpp
+++ b/platform/qt/src/qmapboxgl_map_renderer.cpp
@@ -1,12 +1,47 @@
#include "qmapboxgl_map_renderer.hpp"
+#include "qmapboxgl_scheduler.hpp"
+#include <QThreadStorage>
#include <QtGlobal>
+static bool needsToForceScheduler() {
+ static QThreadStorage<bool> force;
+
+ if (!force.hasLocalData()) {
+ force.setLocalData(mbgl::Scheduler::GetCurrent() == nullptr);
+ }
+
+ return force.localData();
+};
+
+static auto *getScheduler() {
+ static QThreadStorage<std::shared_ptr<QMapboxGLScheduler>> scheduler;
+
+ if (!scheduler.hasLocalData()) {
+ scheduler.setLocalData(std::make_shared<QMapboxGLScheduler>());
+ }
+
+ return scheduler.localData().get();
+};
+
QMapboxGLMapRenderer::QMapboxGLMapRenderer(qreal pixelRatio,
mbgl::DefaultFileSource &fs, mbgl::ThreadPool &tp, QMapboxGLSettings::GLContextMode mode)
: m_renderer(std::make_unique<mbgl::Renderer>(m_backend, pixelRatio, fs, tp, static_cast<mbgl::GLContextMode>(mode)))
- , m_threadWithScheduler(Scheduler::GetCurrent() != nullptr)
+ , m_forceScheduler(needsToForceScheduler())
{
+ // If we don't have a Scheduler on this thread, which
+ // is usually the case for render threads, use a shared
+ // dummy scheduler that needs to be explicitly forced to
+ // process events.
+ if (m_forceScheduler) {
+ auto scheduler = getScheduler();
+
+ if (mbgl::Scheduler::GetCurrent() == nullptr) {
+ mbgl::Scheduler::SetCurrent(scheduler);
+ }
+
+ connect(scheduler, SIGNAL(needsProcessing()), this, SIGNAL(needsRendering()));
+ }
}
QMapboxGLMapRenderer::~QMapboxGLMapRenderer()
@@ -14,16 +49,6 @@ QMapboxGLMapRenderer::~QMapboxGLMapRenderer()
MBGL_VERIFY_THREAD(tid);
}
-void QMapboxGLMapRenderer::schedule(std::weak_ptr<mbgl::Mailbox> mailbox)
-{
- std::lock_guard<std::mutex> lock(m_taskQueueMutex);
- m_taskQueue.push(mailbox);
-
- // Need to force the main thread to wake
- // up this thread and process the events.
- emit needsRendering();
-}
-
void QMapboxGLMapRenderer::updateParameters(std::shared_ptr<mbgl::UpdateParameters> newParameters)
{
std::lock_guard<std::mutex> lock(m_updateMutex);
@@ -57,26 +82,10 @@ void QMapboxGLMapRenderer::render()
// The OpenGL implementation automatically enables the OpenGL context for us.
mbgl::BackendScope scope(m_backend, mbgl::BackendScope::ScopeType::Implicit);
- // If we don't have a Scheduler on this thread, which
- // is usually the case for render threads, use this
- // object as scheduler.
- if (!m_threadWithScheduler) {
- Scheduler::SetCurrent(this);
- }
-
m_renderer->render(*params);
- if (!m_threadWithScheduler) {
- std::queue<std::weak_ptr<mbgl::Mailbox>> taskQueue;
- {
- std::unique_lock<std::mutex> lock(m_taskQueueMutex);
- std::swap(taskQueue, m_taskQueue);
- }
-
- while (!taskQueue.empty()) {
- mbgl::Mailbox::maybeReceive(taskQueue.front());
- taskQueue.pop();
- }
+ if (m_forceScheduler) {
+ getScheduler()->processEvents();
}
}
diff --git a/platform/qt/src/qmapboxgl_map_renderer.hpp b/platform/qt/src/qmapboxgl_map_renderer.hpp
index adba11de51..0b17542e2f 100644
--- a/platform/qt/src/qmapboxgl_map_renderer.hpp
+++ b/platform/qt/src/qmapboxgl_map_renderer.hpp
@@ -14,7 +14,6 @@
#include <memory>
#include <mutex>
-#include <queue>
namespace mbgl {
class Renderer;
@@ -23,7 +22,7 @@ class UpdateParameters;
class QMapboxGLRendererBackend;
-class QMapboxGLMapRenderer : public QObject, public mbgl::Scheduler
+class QMapboxGLMapRenderer : public QObject
{
Q_OBJECT
@@ -32,9 +31,6 @@ public:
mbgl::ThreadPool &, QMapboxGLSettings::GLContextMode);
virtual ~QMapboxGLMapRenderer();
- // mbgl::Scheduler implementation.
- void schedule(std::weak_ptr<mbgl::Mailbox> scheduled) final;
-
void render();
void updateFramebuffer(quint32 fbo, const mbgl::Size &size);
void setObserver(std::shared_ptr<mbgl::RendererObserver>);
@@ -56,8 +52,5 @@ private:
QMapboxGLRendererBackend m_backend;
std::unique_ptr<mbgl::Renderer> m_renderer;
- std::mutex m_taskQueueMutex;
- std::queue<std::weak_ptr<mbgl::Mailbox>> m_taskQueue;
-
- bool m_threadWithScheduler;
+ bool m_forceScheduler;
};
diff --git a/platform/qt/src/qmapboxgl_scheduler.cpp b/platform/qt/src/qmapboxgl_scheduler.cpp
new file mode 100644
index 0000000000..e2d39703ee
--- /dev/null
+++ b/platform/qt/src/qmapboxgl_scheduler.cpp
@@ -0,0 +1,38 @@
+#include "qmapboxgl_scheduler.hpp"
+
+#include <mbgl/util/util.hpp>
+
+#include <cassert>
+
+QMapboxGLScheduler::QMapboxGLScheduler()
+{
+}
+
+QMapboxGLScheduler::~QMapboxGLScheduler()
+{
+ MBGL_VERIFY_THREAD(tid);
+}
+
+void QMapboxGLScheduler::schedule(std::weak_ptr<mbgl::Mailbox> mailbox)
+{
+ std::lock_guard<std::mutex> lock(m_taskQueueMutex);
+ m_taskQueue.push(mailbox);
+
+ // Need to force the main thread to wake
+ // up this thread and process the events.
+ emit needsProcessing();
+}
+
+void QMapboxGLScheduler::processEvents()
+{
+ std::queue<std::weak_ptr<mbgl::Mailbox>> taskQueue;
+ {
+ std::unique_lock<std::mutex> lock(m_taskQueueMutex);
+ std::swap(taskQueue, m_taskQueue);
+ }
+
+ while (!taskQueue.empty()) {
+ mbgl::Mailbox::maybeReceive(taskQueue.front());
+ taskQueue.pop();
+ }
+}
diff --git a/platform/qt/src/qmapboxgl_scheduler.hpp b/platform/qt/src/qmapboxgl_scheduler.hpp
new file mode 100644
index 0000000000..68636d0d11
--- /dev/null
+++ b/platform/qt/src/qmapboxgl_scheduler.hpp
@@ -0,0 +1,34 @@
+#pragma once
+
+#include <mbgl/actor/mailbox.hpp>
+#include <mbgl/actor/scheduler.hpp>
+#include <mbgl/util/util.hpp>
+
+#include <QObject>
+
+#include <memory>
+#include <mutex>
+#include <queue>
+
+class QMapboxGLScheduler : public QObject, public mbgl::Scheduler
+{
+ Q_OBJECT
+
+public:
+ QMapboxGLScheduler();
+ virtual ~QMapboxGLScheduler();
+
+ // mbgl::Scheduler implementation.
+ void schedule(std::weak_ptr<mbgl::Mailbox> scheduled) final;
+
+ void processEvents();
+
+signals:
+ void needsProcessing();
+
+private:
+ MBGL_STORE_THREAD(tid);
+
+ std::mutex m_taskQueueMutex;
+ std::queue<std::weak_ptr<mbgl::Mailbox>> m_taskQueue;
+};
diff --git a/platform/qt/src/qt_geojson.cpp b/platform/qt/src/qt_geojson.cpp
index 80377de64d..9d0a3e96eb 100644
--- a/platform/qt/src/qt_geojson.cpp
+++ b/platform/qt/src/qt_geojson.cpp
@@ -72,10 +72,8 @@ mbgl::Value asMapboxGLPropertyValue(const QVariant &value) {
auto valueMap = [](const QVariantMap &map) {
std::unordered_map<std::string, mbgl::Value> mbglMap;
mbglMap.reserve(map.size());
- auto it = map.constBegin();
- while (it != map.constEnd()) {
+ for (auto it = map.constBegin(); it != map.constEnd(); ++it) {
mbglMap.emplace(std::make_pair(it.key().toStdString(), asMapboxGLPropertyValue(it.value())));
- ++it;
}
return mbglMap;
};
@@ -132,8 +130,7 @@ mbgl::FeatureIdentifier asMapboxGLFeatureIdentifier(const QVariant &id) {
mbgl::Feature asMapboxGLFeature(const QMapbox::Feature &feature) {
mbgl::PropertyMap properties;
properties.reserve(feature.properties.size());
- auto it = feature.properties.constBegin();
- while (it != feature.properties.constEnd()) {
+ for (auto it = feature.properties.constBegin(); it != feature.properties.constEnd(); ++it) {
properties.emplace(std::make_pair(it.key().toStdString(), asMapboxGLPropertyValue(it.value())));
}
diff --git a/platform/qt/src/sqlite3.cpp b/platform/qt/src/sqlite3.cpp
index 4bcaea0e31..2ca09fd3ad 100644
--- a/platform/qt/src/sqlite3.cpp
+++ b/platform/qt/src/sqlite3.cpp
@@ -52,15 +52,6 @@ void checkDatabaseError(const QSqlDatabase &db) {
}
}
-void checkDatabaseOpenError(const QSqlDatabase &db) {
- // Assume every error when opening the data as CANTOPEN. Qt
- // always returns -1 for `nativeErrorCode()` on database errors.
- QSqlError lastError = db.lastError();
- if (lastError.type() != QSqlError::NoError) {
- throw Exception { ResultCode::CantOpen, "Error opening the database." };
- }
-}
-
namespace {
QString incrementCounter() {
static QAtomicInt count = 0;
@@ -70,32 +61,9 @@ namespace {
class DatabaseImpl {
public:
- DatabaseImpl(const char* filename, int flags)
- : connectionName(QString::number(uint64_t(QThread::currentThread())) + incrementCounter())
+ DatabaseImpl(QString connectionName_)
+ : connectionName(std::move(connectionName_))
{
- if (!QSqlDatabase::drivers().contains("QSQLITE")) {
- throw Exception { ResultCode::CantOpen, "SQLite driver not found." };
- }
-
- assert(!QSqlDatabase::contains(connectionName));
- auto db = QSqlDatabase::addDatabase("QSQLITE", connectionName);
-
- QString connectOptions = db.connectOptions();
- if (flags & OpenFlag::ReadOnly) {
- if (!connectOptions.isEmpty()) connectOptions.append(';');
- connectOptions.append("QSQLITE_OPEN_READONLY");
- }
- if (flags & OpenFlag::SharedCache) {
- if (!connectOptions.isEmpty()) connectOptions.append(';');
- connectOptions.append("QSQLITE_ENABLE_SHARED_CACHE");
- }
-
- db.setConnectOptions(connectOptions);
- db.setDatabaseName(QString(filename));
-
- if (!db.open()) {
- checkDatabaseOpenError(db);
- }
}
~DatabaseImpl() {
@@ -104,6 +72,9 @@ public:
checkDatabaseError(db);
}
+ void setBusyTimeout(std::chrono::milliseconds timeout);
+ void exec(const std::string& sql);
+
QString connectionName;
};
@@ -127,12 +98,47 @@ public:
template <typename T>
using optional = std::experimental::optional<T>;
+mapbox::util::variant<Database, Exception> Database::tryOpen(const std::string &filename, int flags) {
+ if (!QSqlDatabase::drivers().contains("QSQLITE")) {
+ return Exception { ResultCode::CantOpen, "SQLite driver not found." };
+ }
-Database::Database(const std::string& file, int flags)
- : impl(std::make_unique<DatabaseImpl>(file.c_str(), flags)) {
- assert(impl);
+ QString connectionName = QString::number(uint64_t(QThread::currentThread())) + incrementCounter();
+
+ assert(!QSqlDatabase::contains(connectionName));
+ auto db = QSqlDatabase::addDatabase("QSQLITE", connectionName);
+
+ QString connectOptions = db.connectOptions();
+ if (flags & OpenFlag::ReadOnly) {
+ if (!connectOptions.isEmpty()) connectOptions.append(';');
+ connectOptions.append("QSQLITE_OPEN_READONLY");
+ }
+
+ db.setConnectOptions(connectOptions);
+ db.setDatabaseName(QString(filename.c_str()));
+
+ if (!db.open()) {
+ // Assume every error when opening the data as CANTOPEN. Qt
+ // always returns -1 for `nativeErrorCode()` on database errors.
+ return Exception { ResultCode::CantOpen, "Error opening the database." };
+ }
+
+ return Database(std::make_unique<DatabaseImpl>(connectionName));
}
+Database Database::open(const std::string &filename, int flags) {
+ auto result = tryOpen(filename, flags);
+ if (result.is<Exception>()) {
+ throw result.get<Exception>();
+ } else {
+ return std::move(result.get<Database>());
+ }
+}
+
+Database::Database(std::unique_ptr<DatabaseImpl> impl_)
+ : impl(std::move(impl_))
+{}
+
Database::Database(Database &&other)
: impl(std::move(other.impl)) {
assert(impl);
@@ -149,12 +155,15 @@ Database::~Database() {
void Database::setBusyTimeout(std::chrono::milliseconds timeout) {
assert(impl);
+ impl->setBusyTimeout(timeout);
+}
+void DatabaseImpl::setBusyTimeout(std::chrono::milliseconds timeout) {
// std::chrono::milliseconds.count() is a long and Qt will cast
// internally to int, so we need to make sure the limits apply.
std::string timeoutStr = mbgl::util::toString(timeout.count() & INT_MAX);
- auto db = QSqlDatabase::database(impl->connectionName);
+ auto db = QSqlDatabase::database(connectionName);
QString connectOptions = db.connectOptions();
if (connectOptions.isEmpty()) {
if (!connectOptions.isEmpty()) connectOptions.append(';');
@@ -165,19 +174,25 @@ void Database::setBusyTimeout(std::chrono::milliseconds timeout) {
}
db.setConnectOptions(connectOptions);
if (!db.open()) {
- checkDatabaseOpenError(db);
+ // Assume every error when opening the data as CANTOPEN. Qt
+ // always returns -1 for `nativeErrorCode()` on database errors.
+ throw Exception { ResultCode::CantOpen, "Error opening the database." };
}
}
void Database::exec(const std::string &sql) {
assert(impl);
+ impl->exec(sql);
+}
+
+void DatabaseImpl::exec(const std::string& sql) {
QStringList statements = QString::fromStdString(sql).split(';', QString::SkipEmptyParts);
statements.removeAll("\n");
for (QString statement : statements) {
if (!statement.endsWith(';')) {
statement.append(';');
}
- QSqlQuery query(QSqlDatabase::database(impl->connectionName));
+ QSqlQuery query(QSqlDatabase::database(connectionName));
query.prepare(statement);
if (!query.exec()) {
@@ -424,16 +439,16 @@ uint64_t Query::changes() const {
}
Transaction::Transaction(Database& db_, Mode mode)
- : db(db_) {
+ : dbImpl(*db_.impl) {
switch (mode) {
case Deferred:
- db.exec("BEGIN DEFERRED TRANSACTION");
+ dbImpl.exec("BEGIN DEFERRED TRANSACTION");
break;
case Immediate:
- db.exec("BEGIN IMMEDIATE TRANSACTION");
+ dbImpl.exec("BEGIN IMMEDIATE TRANSACTION");
break;
case Exclusive:
- db.exec("BEGIN EXCLUSIVE TRANSACTION");
+ dbImpl.exec("BEGIN EXCLUSIVE TRANSACTION");
break;
}
}
@@ -450,12 +465,12 @@ Transaction::~Transaction() {
void Transaction::commit() {
needRollback = false;
- db.exec("COMMIT TRANSACTION");
+ dbImpl.exec("COMMIT TRANSACTION");
}
void Transaction::rollback() {
needRollback = false;
- db.exec("ROLLBACK TRANSACTION");
+ dbImpl.exec("ROLLBACK TRANSACTION");
}
} // namespace sqlite