From c1b17e251af33d0a14a668018f08a809d5d85bae Mon Sep 17 00:00:00 2001 From: "Thiago Marcos P. Santos" Date: Sun, 25 Feb 2018 11:08:56 +0200 Subject: [qt] Fix wrong signal being emitted Probably caused by a typo when refactoring the asynchronous rendering. --- platform/qt/src/qmapboxgl_map_observer.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'platform/qt/src') diff --git a/platform/qt/src/qmapboxgl_map_observer.cpp b/platform/qt/src/qmapboxgl_map_observer.cpp index e180ed8fda..60c6b81841 100644 --- a/platform/qt/src/qmapboxgl_map_observer.cpp +++ b/platform/qt/src/qmapboxgl_map_observer.cpp @@ -65,7 +65,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) -- cgit v1.2.1 From ba019b025681fc6f623ab07f62488b509f10bb4a Mon Sep 17 00:00:00 2001 From: "Thiago Marcos P. Santos" Date: Fri, 23 Feb 2018 11:16:41 +0100 Subject: [qt] Fix issue if resources not being found on the database Once again QVariant getting confused about its contents datatype. With this patch we use QString directly and copy the contents, which should be cheap with Qt implicity sharing. --- platform/qt/src/sqlite3.cpp | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) (limited to 'platform/qt/src') diff --git a/platform/qt/src/sqlite3.cpp b/platform/qt/src/sqlite3.cpp index 80efd6a326..eb4a798043 100644 --- a/platform/qt/src/sqlite3.cpp +++ b/platform/qt/src/sqlite3.cpp @@ -270,20 +270,15 @@ void Statement::bind(int offset, optional value) { } } -void Statement::bind(int offset, const char* value, std::size_t length, bool retain) { +void Statement::bind(int offset, const char* value, std::size_t length, bool /* retain */) { assert(impl); if (length > std::numeric_limits::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); + impl->query.bindValue(offset - 1, QString(QByteArray(value, length)), QSql::In); checkQueryError(impl->query); } -- cgit v1.2.1 From 380f5dc88bb4103a528740e67d887a8695529528 Mon Sep 17 00:00:00 2001 From: Bruno de Oliveira Abinader Date: Mon, 26 Feb 2018 18:05:05 +0200 Subject: [qt] Rename Qt SDK to 'Mapbox Maps SDK for Qt' --- platform/qt/src/qmapbox.cpp | 14 +++++++------- platform/qt/src/qmapboxgl.cpp | 4 ++-- 2 files changed, 9 insertions(+), 9 deletions(-) (limited to 'platform/qt/src') diff --git a/platform/qt/src/qmapbox.cpp b/platform/qt/src/qmapbox.cpp index ec76ebfe53..1386a4b7aa 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. @@ -195,7 +195,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 414b65255c..982f4b3b35 100644 --- a/platform/qt/src/qmapboxgl.cpp +++ b/platform/qt/src/qmapboxgl.cpp @@ -136,7 +136,7 @@ std::unique_ptr 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 Date: Tue, 13 Feb 2018 14:52:49 +0100 Subject: [core] refactor SQLite error/status codes --- platform/qt/src/sqlite3.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'platform/qt/src') diff --git a/platform/qt/src/sqlite3.cpp b/platform/qt/src/sqlite3.cpp index eb4a798043..09a3a16002 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)); -- cgit v1.2.1 From 136e536159a1e22aa4a92c4e6463893600b809d0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Konstantin=20K=C3=A4fer?= Date: Tue, 6 Feb 2018 17:55:50 +0100 Subject: [core, qt] move self-resetting Statement/Query object to shared header --- platform/qt/src/sqlite3.cpp | 198 +++++++++++++++++++++++--------------------- 1 file changed, 103 insertions(+), 95 deletions(-) (limited to 'platform/qt/src') diff --git a/platform/qt/src/sqlite3.cpp b/platform/qt/src/sqlite3.cpp index 09a3a16002..4bcaea0e31 100644 --- a/platform/qt/src/sqlite3.cpp +++ b/platform/qt/src/sqlite3.cpp @@ -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(QString(sql), QSqlDatabase::database(db->impl->connectionName))) { +Statement::Statement(Database& db, const char* sql) + : impl(std::make_unique(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 -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(value), QSql::In); - checkQueryError(impl->query); + stmt.impl->query.bindValue(offset - 1, QVariant::fromValue(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(value)); } template <> -void Statement::bind(int offset, bool value) { +void Query::bind(int offset, bool value) { bind(offset, static_cast(value)); } template <> -void Statement::bind(int offset, int8_t value) { +void Query::bind(int offset, int8_t value) { bind(offset, static_cast(value)); } template <> -void Statement::bind(int offset, uint8_t value) { +void Query::bind(int offset, uint8_t value) { bind(offset, static_cast(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 value) { +void Query::bind(int offset, optional value) { if (value) { bind(offset, *value); } else { @@ -262,7 +270,7 @@ void Statement::bind(int offset, optional value) { } template <> -void Statement::bind(int offset, optional value) { +void Query::bind(int offset, optional value) { if (value) { bind(offset, *value); } else { @@ -270,25 +278,25 @@ void Statement::bind(int offset, optional 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::max()) { // Kept for consistence with the default implementation. throw std::range_error("value too long"); } // Field numbering starts at 0. - impl->query.bindValue(offset - 1, QString(QByteArray(value, length)), 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(value_); if (length > std::numeric_limits::max()) { // Kept for consistence with the default implementation. @@ -296,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& value, bool retain) { +void Query::bindBlob(int offset, const std::vector& 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(); - impl->changes = impl->query.numRowsAffected(); + if (!stmt.impl->query.isValid()) { + if (stmt.impl->query.exec()) { + stmt.impl->lastInsertRowId = stmt.impl->query.lastInsertId().value(); + 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 T Statement::get(int offset) { - assert(impl && impl->query.isValid()); - QVariant value = impl->query.value(offset); - checkQueryError(impl->query); +template 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(); } -template <> std::vector Statement::get(int offset) { - assert(impl && impl->query.isValid()); - QByteArray byteArray = impl->query.value(offset).toByteArray(); - checkQueryError(impl->query); +template <> std::vector 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 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::system_clock::from_time_t(value.value<::time_t>())); } -template <> optional Statement::get(int offset) { - assert(impl && impl->query.isValid()); - QVariant value = impl->query.value(offset); - checkQueryError(impl->query); +template <> optional 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() }; } -template <> optional Statement::get(int offset) { - assert(impl && impl->query.isValid()); - QVariant value = impl->query.value(offset); - checkQueryError(impl->query); +template <> optional 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() }; } -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 Statement::get(int offset) { - assert(impl && impl->query.isValid()); - QByteArray value = impl->query.value(offset).toByteArray(); - checkQueryError(impl->query); +template <> optional 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 Statement::get(int offset) { - assert(impl && impl->query.isValid()); - QVariant value = impl->query.value(offset); - checkQueryError(impl->query); +template <> optional 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( 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) -- cgit v1.2.1 From fc140e265b559868a2a9f568583689ee4a6b9dfd Mon Sep 17 00:00:00 2001 From: Bruno de Oliveira Abinader Date: Fri, 2 Mar 2018 19:43:30 +0200 Subject: [Qt] Expose mapLoadingFailed signal --- platform/qt/src/qmapboxgl.cpp | 1 + platform/qt/src/qmapboxgl_map_observer.cpp | 7 ++++++- platform/qt/src/qmapboxgl_map_observer.hpp | 1 + 3 files changed, 8 insertions(+), 1 deletion(-) (limited to 'platform/qt/src') diff --git a/platform/qt/src/qmapboxgl.cpp b/platform/qt/src/qmapboxgl.cpp index 982f4b3b35..5430af30e2 100644 --- a/platform/qt/src/qmapboxgl.cpp +++ b/platform/qt/src/qmapboxgl.cpp @@ -1649,6 +1649,7 @@ QMapboxGLPrivate::QMapboxGLPrivate(QMapboxGL *q, const QMapboxGLSettings &settin qRegisterMetaType("QMapboxGL::MapChange"); connect(m_mapObserver.get(), SIGNAL(mapChanged(QMapboxGL::MapChange)), q, SIGNAL(mapChanged(QMapboxGL::MapChange))); + connect(m_mapObserver.get(), SIGNAL(mapLoadingFailed(QString)), q, SIGNAL(mapLoadingFailed(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 60c6b81841..43b4162eb4 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 + +#include + QMapboxGLMapObserver::QMapboxGLMapObserver(QMapboxGLPrivate *d) : d_ptr(d) { @@ -44,9 +48,10 @@ void QMapboxGLMapObserver::onDidFinishLoadingMap() emit mapChanged(QMapboxGL::MapChangeDidFinishLoadingMap); } -void QMapboxGLMapObserver::onDidFailLoadingMap(std::exception_ptr) +void QMapboxGLMapObserver::onDidFailLoadingMap(std::exception_ptr exception) { emit mapChanged(QMapboxGL::MapChangeDidFailLoadingMap); + emit mapLoadingFailed(QString::fromStdString(mbgl::util::toString(exception))); } void QMapboxGLMapObserver::onWillStartRenderingFrame() diff --git a/platform/qt/src/qmapboxgl_map_observer.hpp b/platform/qt/src/qmapboxgl_map_observer.hpp index c9d0581a90..7c272c39ae 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(const QString &reason); void copyrightsChanged(const QString ©rightsHtml); private: -- cgit v1.2.1 From 803a4d46ed15a790876f5bda0e1d49d9ba0483a4 Mon Sep 17 00:00:00 2001 From: Bruno de Oliveira Abinader Date: Mon, 5 Mar 2018 13:47:31 -0500 Subject: [Qt] Added QMapboxGL::MapLoadingFailure enum --- platform/qt/src/qmapboxgl.cpp | 22 +++++++++++++++++++++- platform/qt/src/qmapboxgl_map_observer.cpp | 24 ++++++++++++++++++++++-- platform/qt/src/qmapboxgl_map_observer.hpp | 2 +- 3 files changed, 44 insertions(+), 4 deletions(-) (limited to 'platform/qt/src') diff --git a/platform/qt/src/qmapboxgl.cpp b/platform/qt/src/qmapboxgl.cpp index 5430af30e2..34fd5509fa 100644 --- a/platform/qt/src/qmapboxgl.cpp +++ b/platform/qt/src/qmapboxgl.cpp @@ -517,6 +517,19 @@ void QMapboxGLSettings::setResourceTransform(const std::function("QMapboxGL::MapChange"); connect(m_mapObserver.get(), SIGNAL(mapChanged(QMapboxGL::MapChange)), q, SIGNAL(mapChanged(QMapboxGL::MapChange))); - connect(m_mapObserver.get(), SIGNAL(mapLoadingFailed(QString)), q, SIGNAL(mapLoadingFailed(QString))); + 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 43b4162eb4..44cb8c41d5 100644 --- a/platform/qt/src/qmapboxgl_map_observer.cpp +++ b/platform/qt/src/qmapboxgl_map_observer.cpp @@ -2,7 +2,7 @@ #include "qmapboxgl_p.hpp" -#include +#include #include @@ -51,7 +51,27 @@ void QMapboxGLMapObserver::onDidFinishLoadingMap() void QMapboxGLMapObserver::onDidFailLoadingMap(std::exception_ptr exception) { emit mapChanged(QMapboxGL::MapChangeDidFailLoadingMap); - emit mapLoadingFailed(QString::fromStdString(mbgl::util::toString(exception))); + + 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() diff --git a/platform/qt/src/qmapboxgl_map_observer.hpp b/platform/qt/src/qmapboxgl_map_observer.hpp index 7c272c39ae..98da5b6add 100644 --- a/platform/qt/src/qmapboxgl_map_observer.hpp +++ b/platform/qt/src/qmapboxgl_map_observer.hpp @@ -36,7 +36,7 @@ public: signals: void mapChanged(QMapboxGL::MapChange); - void mapLoadingFailed(const QString &reason); + void mapLoadingFailed(QMapboxGL::MapLoadingFailure, const QString &reason); void copyrightsChanged(const QString ©rightsHtml); private: -- cgit v1.2.1 From 0767bf06869c380305c57df1b69d74fac5a6c94a Mon Sep 17 00:00:00 2001 From: "Thiago Marcos P. Santos" Date: Wed, 25 Apr 2018 15:22:00 -0700 Subject: [qt] Only share a FileSource if it points to the same path Previously all QMapboxGL objects were sharing the same cache created by the first instantiated object. Now it will share the cache only if it points to the same path. Fixes #11766 --- platform/qt/src/qmapboxgl.cpp | 37 +++++++++++++++++++++++++++---------- 1 file changed, 27 insertions(+), 10 deletions(-) (limited to 'platform/qt/src') diff --git a/platform/qt/src/qmapboxgl.cpp b/platform/qt/src/qmapboxgl.cpp index e2c1b31eea..8c3355dc09 100644 --- a/platform/qt/src/qmapboxgl.cpp +++ b/platform/qt/src/qmapboxgl.cpp @@ -89,15 +89,33 @@ QThreadStorage> loop; std::shared_ptr sharedDefaultFileSource( const std::string& cachePath, const std::string& assetRoot, uint64_t maximumCacheSize) { - static std::weak_ptr weak; - auto fs = weak.lock(); + static std::mutex mutex; + static std::unordered_map> fileSources; - if (!fs) { - weak = fs = std::make_shared( - cachePath, assetRoot, maximumCacheSize); + std::lock_guard lock(mutex); + + // Purge entries no longer in use. + for (auto it = fileSources.begin(); it != fileSources.end();) { + if (!it->second.lock()) { + it = fileSources.erase(it); + } else { + ++it; + } } - return fs; + // Return an existing FileSource if available. + auto sharedFileSource = fileSources.find(cachePath); + if (sharedFileSource != fileSources.end()) { + return sharedFileSource->second.lock(); + } + + // New path, create a new FileSource. + auto newFileSource = std::make_shared( + cachePath, assetRoot, maximumCacheSize); + + fileSources[cachePath] = newFileSource; + + return newFileSource; } // Conversion helper functions. @@ -141,10 +159,9 @@ std::unique_ptr toStyleImage(const QString &id, const QImage QMapboxGLSettings is used to configure QMapboxGL at the moment of its creation. Once created, the QMapboxGLSettings of a QMapboxGL can no longer be changed. - Cache-related settings are shared between all QMapboxGL instances because different - maps will share the same cache database file. The first map to configure cache properties - such as size and path will force the configuration to all newly instantiated QMapboxGL - objects. + Cache-related settings are shared between all QMapboxGL instances using the same cache path. + The first map to configure cache properties such as size will force the configuration + to all newly instantiated QMapboxGL objects using the same cache in the same process. \since 4.7 */ -- cgit v1.2.1 From a1195f6a9dc57910f7c3e6c9217e3041929a01fb Mon Sep 17 00:00:00 2001 From: John Firebaugh Date: Tue, 8 May 2018 10:40:35 -0700 Subject: Avoid exceptions for flow control during database creation Unfortuntely, it's difficult to avoid all exceptions, because sqlite3_open_v2 does not reliably return SQLITE_NOTADB if the file is not a database. However, this should avoid cases where developers misinterpret the SQLITE_CANTOPEN exception as a crash, which is the common case. --- platform/qt/src/sqlite3.cpp | 85 +++++++++++++++++++++++++-------------------- 1 file changed, 47 insertions(+), 38 deletions(-) (limited to 'platform/qt/src') diff --git a/platform/qt/src/sqlite3.cpp b/platform/qt/src/sqlite3.cpp index 4bcaea0e31..351991f881 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() { @@ -127,12 +95,51 @@ public: template using optional = std::experimental::optional; +mapbox::util::variant 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(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"); + } + if (flags & OpenFlag::SharedCache) { + if (!connectOptions.isEmpty()) connectOptions.append(';'); + connectOptions.append("QSQLITE_ENABLE_SHARED_CACHE"); + } + + 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(connectionName)); +} + +Database Database::open(const std::string &filename, int flags) { + auto result = tryOpen(filename, flags); + if (result.is()) { + throw result.get(); + } else { + return std::move(result.get()); + } } +Database::Database(std::unique_ptr impl_) + : impl(std::move(impl_)) +{} + Database::Database(Database &&other) : impl(std::move(other.impl)) { assert(impl); @@ -165,7 +172,9 @@ 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." }; } } -- cgit v1.2.1