diff options
Diffstat (limited to 'platform/qt')
-rw-r--r-- | platform/qt/README.md | 4 | ||||
-rw-r--r-- | platform/qt/config.qdocconf | 2 | ||||
-rw-r--r-- | platform/qt/include/qmapboxgl.hpp | 9 | ||||
-rw-r--r-- | platform/qt/src/qmapbox.cpp | 14 | ||||
-rw-r--r-- | platform/qt/src/qmapboxgl.cpp | 25 | ||||
-rw-r--r-- | platform/qt/src/qmapboxgl_map_observer.cpp | 29 | ||||
-rw-r--r-- | platform/qt/src/qmapboxgl_map_observer.hpp | 1 | ||||
-rw-r--r-- | platform/qt/src/sqlite3.cpp | 213 |
8 files changed, 178 insertions, 119 deletions
diff --git a/platform/qt/README.md b/platform/qt/README.md index 4d2d887828..018f8823b6 100644 --- a/platform/qt/README.md +++ b/platform/qt/README.md @@ -1,4 +1,4 @@ -# Mapbox Qt SDK +# Mapbox Maps SDK for Qt [![Circle CI build status](https://circleci.com/gh/mapbox/mapbox-gl-native.svg?style=shield)](https://circleci.com/gh/mapbox/workflows/mapbox-gl-native/tree/master) [![AppVeyor CI build status](https://ci.appveyor.com/api/projects/status/3q12kbcooc6df8uc?svg=true)](https://ci.appveyor.com/project/Mapbox/mapbox-gl-native) @@ -9,7 +9,7 @@ available in the Qt SDK since Qt 5.9. Use the [Qt bugtracker](https://bugreports to the plugin and this GitHub repository for bugs related to Mapbox GL Native and the Qt bindings. You should build this repository if you want to develop/contribute using the low level Qt C++ bindings or -want to contribute to the Mapbox GL Native projectusing the Qt port for debugging. +want to contribute to the Mapbox GL Native project using the Qt port for debugging. See the Mapbox Qt landing page for more details: https://www.mapbox.com/qt/ diff --git a/platform/qt/config.qdocconf b/platform/qt/config.qdocconf index d6f0edbd32..9d3b8a7ef4 100644 --- a/platform/qt/config.qdocconf +++ b/platform/qt/config.qdocconf @@ -7,7 +7,7 @@ include($QT_INSTALL_DOCS/global/qt-html-templates-online.qdocconf) Cpp.ignoretokens = Q_MAPBOXGL_EXPORT project = QMapboxGL -description = Mapbox Qt SDK +description = Mapbox Maps SDK for Qt language = Cpp outputdir = docs diff --git a/platform/qt/include/qmapboxgl.hpp b/platform/qt/include/qmapboxgl.hpp index 70fe270902..79eb672d1f 100644 --- a/platform/qt/include/qmapboxgl.hpp +++ b/platform/qt/include/qmapboxgl.hpp @@ -128,6 +128,13 @@ public: MapChangeSourceDidChange }; + enum MapLoadingFailure { + StyleParseFailure, + StyleLoadFailure, + NotFoundFailure, + UnknownFailure + }; + // Determines the orientation of the map. enum NorthOrientation { NorthUpwards, // Default @@ -248,6 +255,7 @@ public slots: signals: void needsRendering(); void mapChanged(QMapboxGL::MapChange); + void mapLoadingFailed(QMapboxGL::MapLoadingFailure, const QString &reason); void copyrightsChanged(const QString ©rightsHtml); void staticRenderFinished(const QString &error); @@ -259,5 +267,6 @@ private: }; Q_DECLARE_METATYPE(QMapboxGL::MapChange); +Q_DECLARE_METATYPE(QMapboxGL::MapLoadingFailure); #endif // QMAPBOXGL_H diff --git a/platform/qt/src/qmapbox.cpp b/platform/qt/src/qmapbox.cpp index 87a9358772..2180f22d07 100644 --- a/platform/qt/src/qmapbox.cpp +++ b/platform/qt/src/qmapbox.cpp @@ -24,7 +24,7 @@ namespace QMapbox { /*! \namespace QMapbox - \inmodule Mapbox Qt SDK + \inmodule Mapbox Maps SDK for Qt Contains miscellaneous Mapbox bindings used throughout QMapboxGL. */ @@ -74,7 +74,7 @@ namespace QMapbox { /*! \class QMapbox::Feature - \inmodule Mapbox Qt SDK + \inmodule Mapbox Maps SDK for Qt Represents \l {https://www.mapbox.com/help/define-features/}{map features} via its \a type (PointType, LineStringType or PolygonType), \a geometry, \a @@ -94,7 +94,7 @@ namespace QMapbox { /*! \class QMapbox::ShapeAnnotationGeometry - \inmodule Mapbox Qt SDK + \inmodule Mapbox Maps SDK for Qt Represents a shape annotation geometry. */ @@ -113,7 +113,7 @@ namespace QMapbox { /*! \class QMapbox::SymbolAnnotation - \inmodule Mapbox Qt SDK + \inmodule Mapbox Maps SDK for Qt A symbol annotation comprises of its geometry and an icon identifier. */ @@ -121,7 +121,7 @@ namespace QMapbox { /*! \class QMapbox::LineAnnotation - \inmodule Mapbox Qt SDK + \inmodule Mapbox Maps SDK for Qt Represents a line annotation object, along with its properties. @@ -131,7 +131,7 @@ namespace QMapbox { /*! \class QMapbox::FillAnnotation - \inmodule Mapbox Qt SDK + \inmodule Mapbox Maps SDK for Qt Represents a fill annotation object, along with its properties. @@ -177,7 +177,7 @@ namespace QMapbox { /*! \class QMapbox::CustomLayerRenderParameters - \inmodule Mapbox Qt SDK + \inmodule Mapbox Maps SDK for Qt QMapbox::CustomLayerRenderParameters provides the data passed on each render pass for a custom layer. diff --git a/platform/qt/src/qmapboxgl.cpp b/platform/qt/src/qmapboxgl.cpp index 2e736c0aa2..e2c1b31eea 100644 --- a/platform/qt/src/qmapboxgl.cpp +++ b/platform/qt/src/qmapboxgl.cpp @@ -136,7 +136,7 @@ std::unique_ptr<mbgl::style::Image> toStyleImage(const QString &id, const QImage \class QMapboxGLSettings \brief The QMapboxGLSettings class stores the initial configuration for QMapboxGL. - \inmodule Mapbox Qt SDK + \inmodule Mapbox Maps SDK for Qt QMapboxGLSettings is used to configure QMapboxGL at the moment of its creation. Once created, the QMapboxGLSettings of a QMapboxGL can no longer be changed. @@ -454,7 +454,7 @@ void QMapboxGLSettings::setResourceTransform(const std::function<std::string(con \class QMapboxGL \brief The QMapboxGL class is a Qt wrapper for the Mapbox GL Native engine. - \inmodule Mapbox Qt SDK + \inmodule Mapbox Maps SDK for Qt QMapboxGL is a Qt friendly version the Mapbox GL Native engine using Qt types and deep integration with Qt event loop. QMapboxGL relies as much as possible @@ -518,6 +518,19 @@ void QMapboxGLSettings::setResourceTransform(const std::function<std::string(con */ /*! + \enum QMapboxGL::MapLoadingFailure + + This enum represents map loading failure type. + + \value StyleParseFailure Failure to parse the style. + \value StyleLoadFailure Failure to load the style data. + \value NotFoundFailure Failure to obtain style resource file. + \value UnknownFailure Unknown map loading failure. + + \sa mapLoadingFailed() +*/ + +/*! \enum QMapboxGL::NorthOrientation This enum sets the orientation of the north bearing. It will directly affect bearing when @@ -1636,6 +1649,13 @@ void QMapboxGL::connectionEstablished() */ /*! + \fn void QMapboxGL::mapLoadingFailed(QMapboxGL::MapLoadingFailure type, const QString &description) + + This signal is emitted when a map loading failure happens. Details of the + failures are provided, including its \a type and textual \a description. +*/ + +/*! \fn void QMapboxGL::copyrightsChanged(const QString ©rightsHtml); This signal is emitted when the copyrights of the current content of the map @@ -1672,6 +1692,7 @@ QMapboxGLPrivate::QMapboxGLPrivate(QMapboxGL *q, const QMapboxGLSettings &settin qRegisterMetaType<QMapboxGL::MapChange>("QMapboxGL::MapChange"); connect(m_mapObserver.get(), SIGNAL(mapChanged(QMapboxGL::MapChange)), q, SIGNAL(mapChanged(QMapboxGL::MapChange))); + connect(m_mapObserver.get(), SIGNAL(mapLoadingFailed(QMapboxGL::MapLoadingFailure,QString)), q, SIGNAL(mapLoadingFailed(QMapboxGL::MapLoadingFailure,QString))); connect(m_mapObserver.get(), SIGNAL(copyrightsChanged(QString)), q, SIGNAL(copyrightsChanged(QString))); // Setup the Map object diff --git a/platform/qt/src/qmapboxgl_map_observer.cpp b/platform/qt/src/qmapboxgl_map_observer.cpp index e180ed8fda..44cb8c41d5 100644 --- a/platform/qt/src/qmapboxgl_map_observer.cpp +++ b/platform/qt/src/qmapboxgl_map_observer.cpp @@ -2,6 +2,10 @@ #include "qmapboxgl_p.hpp" +#include <mbgl/util/exception.hpp> + +#include <exception> + QMapboxGLMapObserver::QMapboxGLMapObserver(QMapboxGLPrivate *d) : d_ptr(d) { @@ -44,9 +48,30 @@ void QMapboxGLMapObserver::onDidFinishLoadingMap() emit mapChanged(QMapboxGL::MapChangeDidFinishLoadingMap); } -void QMapboxGLMapObserver::onDidFailLoadingMap(std::exception_ptr) +void QMapboxGLMapObserver::onDidFailLoadingMap(std::exception_ptr exception) { emit mapChanged(QMapboxGL::MapChangeDidFailLoadingMap); + + QMapboxGL::MapLoadingFailure type; + QString description; + + try { + std::rethrow_exception(exception); + } catch (const mbgl::util::StyleParseException& e) { + type = QMapboxGL::MapLoadingFailure::StyleParseFailure; + description = e.what(); + } catch (const mbgl::util::StyleLoadException& e) { + type = QMapboxGL::MapLoadingFailure::StyleLoadFailure; + description = e.what(); + } catch (const mbgl::util::NotFoundException& e) { + type = QMapboxGL::MapLoadingFailure::NotFoundFailure; + description = e.what(); + } catch (const std::exception& e) { + type = QMapboxGL::MapLoadingFailure::UnknownFailure; + description = e.what(); + } + + emit mapLoadingFailed(type, description); } void QMapboxGLMapObserver::onWillStartRenderingFrame() @@ -65,7 +90,7 @@ void QMapboxGLMapObserver::onDidFinishRenderingFrame(mbgl::MapObserver::RenderMo void QMapboxGLMapObserver::onWillStartRenderingMap() { - emit mapChanged(QMapboxGL::MapChangeWillStartLoadingMap); + emit mapChanged(QMapboxGL::MapChangeWillStartRenderingMap); } void QMapboxGLMapObserver::onDidFinishRenderingMap(mbgl::MapObserver::RenderMode mode) diff --git a/platform/qt/src/qmapboxgl_map_observer.hpp b/platform/qt/src/qmapboxgl_map_observer.hpp index c9d0581a90..98da5b6add 100644 --- a/platform/qt/src/qmapboxgl_map_observer.hpp +++ b/platform/qt/src/qmapboxgl_map_observer.hpp @@ -36,6 +36,7 @@ public: signals: void mapChanged(QMapboxGL::MapChange); + void mapLoadingFailed(QMapboxGL::MapLoadingFailure, const QString &reason); void copyrightsChanged(const QString ©rightsHtml); private: diff --git a/platform/qt/src/sqlite3.cpp b/platform/qt/src/sqlite3.cpp index 80efd6a326..4bcaea0e31 100644 --- a/platform/qt/src/sqlite3.cpp +++ b/platform/qt/src/sqlite3.cpp @@ -24,11 +24,11 @@ namespace mapbox { namespace sqlite { // https://www.sqlite.org/rescode.html#ok -static_assert(mbgl::underlying_type(Exception::OK) == 0, "error"); +static_assert(mbgl::underlying_type(ResultCode::OK) == 0, "error"); // https://www.sqlite.org/rescode.html#cantopen -static_assert(mbgl::underlying_type(Exception::CANTOPEN) == 14, "error"); +static_assert(mbgl::underlying_type(ResultCode::CantOpen) == 14, "error"); // https://www.sqlite.org/rescode.html#notadb -static_assert(mbgl::underlying_type(Exception::NOTADB) == 26, "error"); +static_assert(mbgl::underlying_type(ResultCode::NotADB) == 26, "error"); void checkQueryError(const QSqlQuery& query) { QSqlError lastError = query.lastError(); @@ -57,7 +57,7 @@ void checkDatabaseOpenError(const QSqlDatabase &db) { // always returns -1 for `nativeErrorCode()` on database errors. QSqlError lastError = db.lastError(); if (lastError.type() != QSqlError::NoError) { - throw Exception { Exception::Code::CANTOPEN, "Error opening the database." }; + throw Exception { ResultCode::CantOpen, "Error opening the database." }; } } @@ -74,7 +74,7 @@ public: : connectionName(QString::number(uint64_t(QThread::currentThread())) + incrementCounter()) { if (!QSqlDatabase::drivers().contains("QSQLITE")) { - throw Exception { Exception::Code::CANTOPEN, "SQLite driver not found." }; + throw Exception { ResultCode::CantOpen, "SQLite driver not found." }; } assert(!QSqlDatabase::contains(connectionName)); @@ -186,74 +186,82 @@ void Database::exec(const std::string &sql) { } } -Statement Database::prepare(const char *query) { - return Statement(this, query); -} - -Statement::Statement(Database *db, const char *sql) - : impl(std::make_unique<StatementImpl>(QString(sql), QSqlDatabase::database(db->impl->connectionName))) { +Statement::Statement(Database& db, const char* sql) + : impl(std::make_unique<StatementImpl>(QString(sql), + QSqlDatabase::database(db.impl->connectionName))) { assert(impl); } -Statement::Statement(Statement &&other) - : impl(std::move(other.impl)) { - assert(impl); +Statement::~Statement() { +#ifndef NDEBUG + // Crash if we're destructing this object while we know a Query object references this. + assert(!used); +#endif } -Statement &Statement::operator=(Statement &&other) { - assert(impl); - std::swap(impl, other.impl); - return *this; +Query::Query(Statement& stmt_) : stmt(stmt_) { + assert(stmt.impl); + +#ifndef NDEBUG + assert(!stmt.used); + stmt.used = true; +#endif } -Statement::~Statement() { +Query::~Query() { + reset(); + clearBindings(); + +#ifndef NDEBUG + stmt.used = false; +#endif } -template void Statement::bind(int, int64_t); +template void Query::bind(int, int64_t); template <typename T> -void Statement::bind(int offset, T value) { - assert(impl); +void Query::bind(int offset, T value) { + assert(stmt.impl); // Field numbering starts at 0. - impl->query.bindValue(offset - 1, QVariant::fromValue<T>(value), QSql::In); - checkQueryError(impl->query); + stmt.impl->query.bindValue(offset - 1, QVariant::fromValue<T>(value), QSql::In); + checkQueryError(stmt.impl->query); } template <> -void Statement::bind(int offset, std::nullptr_t) { - assert(impl); +void Query::bind(int offset, std::nullptr_t) { + assert(stmt.impl); // Field numbering starts at 0. - impl->query.bindValue(offset - 1, QVariant(QVariant::Invalid), QSql::In); - checkQueryError(impl->query); + stmt.impl->query.bindValue(offset - 1, QVariant(QVariant::Invalid), QSql::In); + checkQueryError(stmt.impl->query); } template <> -void Statement::bind(int offset, int32_t value) { +void Query::bind(int offset, int32_t value) { bind(offset, static_cast<int64_t>(value)); } template <> -void Statement::bind(int offset, bool value) { +void Query::bind(int offset, bool value) { bind(offset, static_cast<int>(value)); } template <> -void Statement::bind(int offset, int8_t value) { +void Query::bind(int offset, int8_t value) { bind(offset, static_cast<int64_t>(value)); } template <> -void Statement::bind(int offset, uint8_t value) { +void Query::bind(int offset, uint8_t value) { bind(offset, static_cast<int64_t>(value)); } template <> -void Statement::bind(int offset, mbgl::Timestamp value) { +void Query::bind(int offset, mbgl::Timestamp value) { bind(offset, std::chrono::system_clock::to_time_t(value)); } template <> -void Statement::bind(int offset, optional<std::string> value) { +void Query::bind(int offset, optional<std::string> value) { if (value) { bind(offset, *value); } else { @@ -262,7 +270,7 @@ void Statement::bind(int offset, optional<std::string> value) { } template <> -void Statement::bind(int offset, optional<mbgl::Timestamp> value) { +void Query::bind(int offset, optional<mbgl::Timestamp> value) { if (value) { bind(offset, *value); } else { @@ -270,30 +278,25 @@ void Statement::bind(int offset, optional<mbgl::Timestamp> value) { } } -void Statement::bind(int offset, const char* value, std::size_t length, bool retain) { - assert(impl); +void Query::bind(int offset, const char* value, std::size_t length, bool /* retain */) { + assert(stmt.impl); if (length > std::numeric_limits<int>::max()) { // Kept for consistence with the default implementation. throw std::range_error("value too long"); } - // Qt SQLite driver treats QByteArray as blob: we need to explicitly - // declare the variant type as string. - QVariant text(QVariant::Type::String); - text.setValue(retain ? QByteArray(value, length) : QByteArray::fromRawData(value, length)); - // Field numbering starts at 0. - impl->query.bindValue(offset - 1, std::move(text), QSql::In); + stmt.impl->query.bindValue(offset - 1, QString(QByteArray(value, length)), QSql::In); - checkQueryError(impl->query); + checkQueryError(stmt.impl->query); } -void Statement::bind(int offset, const std::string& value, bool retain) { +void Query::bind(int offset, const std::string& value, bool retain) { bind(offset, value.data(), value.size(), retain); } -void Statement::bindBlob(int offset, const void* value_, std::size_t length, bool retain) { - assert(impl); +void Query::bindBlob(int offset, const void* value_, std::size_t length, bool retain) { + assert(stmt.impl); const char* value = reinterpret_cast<const char*>(value_); if (length > std::numeric_limits<int>::max()) { // Kept for consistence with the default implementation. @@ -301,123 +304,123 @@ void Statement::bindBlob(int offset, const void* value_, std::size_t length, boo } // Field numbering starts at 0. - impl->query.bindValue(offset - 1, retain ? QByteArray(value, length) : + stmt.impl->query.bindValue(offset - 1, retain ? QByteArray(value, length) : QByteArray::fromRawData(value, length), QSql::In | QSql::Binary); - checkQueryError(impl->query); + checkQueryError(stmt.impl->query); } -void Statement::bindBlob(int offset, const std::vector<uint8_t>& value, bool retain) { +void Query::bindBlob(int offset, const std::vector<uint8_t>& value, bool retain) { bindBlob(offset, value.data(), value.size(), retain); } -bool Statement::run() { - assert(impl); +bool Query::run() { + assert(stmt.impl); - if (!impl->query.isValid()) { - if (impl->query.exec()) { - impl->lastInsertRowId = impl->query.lastInsertId().value<int64_t>(); - impl->changes = impl->query.numRowsAffected(); + if (!stmt.impl->query.isValid()) { + if (stmt.impl->query.exec()) { + stmt.impl->lastInsertRowId = stmt.impl->query.lastInsertId().value<int64_t>(); + stmt.impl->changes = stmt.impl->query.numRowsAffected(); } else { - checkQueryError(impl->query); + checkQueryError(stmt.impl->query); } } - const bool hasNext = impl->query.next(); - if (!hasNext) impl->query.finish(); + const bool hasNext = stmt.impl->query.next(); + if (!hasNext) stmt.impl->query.finish(); return hasNext; } -template bool Statement::get(int); -template int Statement::get(int); -template int64_t Statement::get(int); -template double Statement::get(int); +template bool Query::get(int); +template int Query::get(int); +template int64_t Query::get(int); +template double Query::get(int); -template <typename T> T Statement::get(int offset) { - assert(impl && impl->query.isValid()); - QVariant value = impl->query.value(offset); - checkQueryError(impl->query); +template <typename T> T Query::get(int offset) { + assert(stmt.impl && stmt.impl->query.isValid()); + QVariant value = stmt.impl->query.value(offset); + checkQueryError(stmt.impl->query); return value.value<T>(); } -template <> std::vector<uint8_t> Statement::get(int offset) { - assert(impl && impl->query.isValid()); - QByteArray byteArray = impl->query.value(offset).toByteArray(); - checkQueryError(impl->query); +template <> std::vector<uint8_t> Query::get(int offset) { + assert(stmt.impl && stmt.impl->query.isValid()); + QByteArray byteArray = stmt.impl->query.value(offset).toByteArray(); + checkQueryError(stmt.impl->query); std::vector<uint8_t> blob(byteArray.begin(), byteArray.end()); return blob; } -template <> mbgl::Timestamp Statement::get(int offset) { - assert(impl && impl->query.isValid()); - QVariant value = impl->query.value(offset); - checkQueryError(impl->query); +template <> mbgl::Timestamp Query::get(int offset) { + assert(stmt.impl && stmt.impl->query.isValid()); + QVariant value = stmt.impl->query.value(offset); + checkQueryError(stmt.impl->query); return std::chrono::time_point_cast<std::chrono::seconds>( std::chrono::system_clock::from_time_t(value.value<::time_t>())); } -template <> optional<int64_t> Statement::get(int offset) { - assert(impl && impl->query.isValid()); - QVariant value = impl->query.value(offset); - checkQueryError(impl->query); +template <> optional<int64_t> Query::get(int offset) { + assert(stmt.impl && stmt.impl->query.isValid()); + QVariant value = stmt.impl->query.value(offset); + checkQueryError(stmt.impl->query); if (value.isNull()) return {}; return { value.value<int64_t>() }; } -template <> optional<double> Statement::get(int offset) { - assert(impl && impl->query.isValid()); - QVariant value = impl->query.value(offset); - checkQueryError(impl->query); +template <> optional<double> Query::get(int offset) { + assert(stmt.impl && stmt.impl->query.isValid()); + QVariant value = stmt.impl->query.value(offset); + checkQueryError(stmt.impl->query); if (value.isNull()) return {}; return { value.value<double>() }; } -template <> std::string Statement::get(int offset) { - assert(impl && impl->query.isValid()); - QByteArray value = impl->query.value(offset).toByteArray(); - checkQueryError(impl->query); +template <> std::string Query::get(int offset) { + assert(stmt.impl && stmt.impl->query.isValid()); + QByteArray value = stmt.impl->query.value(offset).toByteArray(); + checkQueryError(stmt.impl->query); return std::string(value.constData(), value.size()); } -template <> optional<std::string> Statement::get(int offset) { - assert(impl && impl->query.isValid()); - QByteArray value = impl->query.value(offset).toByteArray(); - checkQueryError(impl->query); +template <> optional<std::string> Query::get(int offset) { + assert(stmt.impl && stmt.impl->query.isValid()); + QByteArray value = stmt.impl->query.value(offset).toByteArray(); + checkQueryError(stmt.impl->query); if (value.isNull()) return {}; return { std::string(value.constData(), value.size()) }; } -template <> optional<mbgl::Timestamp> Statement::get(int offset) { - assert(impl && impl->query.isValid()); - QVariant value = impl->query.value(offset); - checkQueryError(impl->query); +template <> optional<mbgl::Timestamp> Query::get(int offset) { + assert(stmt.impl && stmt.impl->query.isValid()); + QVariant value = stmt.impl->query.value(offset); + checkQueryError(stmt.impl->query); if (value.isNull()) return {}; return { std::chrono::time_point_cast<mbgl::Seconds>( std::chrono::system_clock::from_time_t(value.value<::time_t>())) }; } -void Statement::reset() { - assert(impl); - impl->query.finish(); +void Query::reset() { + assert(stmt.impl); + stmt.impl->query.finish(); } -void Statement::clearBindings() { +void Query::clearBindings() { // no-op } -int64_t Statement::lastInsertRowId() const { - assert(impl); - return impl->lastInsertRowId; +int64_t Query::lastInsertRowId() const { + assert(stmt.impl); + return stmt.impl->lastInsertRowId; } -uint64_t Statement::changes() const { - assert(impl); - return (impl->changes < 0 ? 0 : impl->changes); +uint64_t Query::changes() const { + assert(stmt.impl); + return (stmt.impl->changes < 0 ? 0 : stmt.impl->changes); } Transaction::Transaction(Database& db_, Mode mode) |