From 8c3faa4ca932d4a32b017f438784d6ebd284a08a Mon Sep 17 00:00:00 2001 From: Klaus Basan Date: Thu, 27 Dec 2018 10:29:29 +0100 Subject: [PATCH] Ref T489, support download progress in our readers * signal for download progress per entity (DB reader) * ProgressSlot * changed signatures for ProgressSlot --- src/blackcore/application.cpp | 73 ++++++++++++++++++++++------- src/blackcore/application.h | 27 +++++++++-- src/blackcore/db/databasereader.cpp | 15 +++++- src/blackcore/db/databasereader.h | 10 ++++ src/blackcore/setupreader.cpp | 16 +++++-- src/blackcore/setupreader.h | 3 ++ src/blackcore/threadedreader.cpp | 21 ++++++++- src/blackcore/threadedreader.h | 14 ++++++ src/blackcore/webdataservices.cpp | 18 +++++-- src/blackcore/webdataservices.h | 7 +++ 10 files changed, 171 insertions(+), 33 deletions(-) diff --git a/src/blackcore/application.cpp b/src/blackcore/application.cpp index ab048d5f2..45dbdc71f 100644 --- a/src/blackcore/application.cpp +++ b/src/blackcore/application.cpp @@ -427,7 +427,7 @@ namespace BlackCore if (m_setupReader->isSetupAvailable()) { msgs.push_back(CStatusMessage(this).info(forced ? QStringLiteral("Setup available after forcing (so likely web read still pending)") - : QStringLiteral("Setup available"))); + : QStringLiteral("Setup available"))); return msgs; } @@ -635,24 +635,37 @@ namespace BlackCore return str; } - QNetworkReply *CApplication::getFromNetwork(const CUrl &url, const CSlot &callback, int maxRedirects) + + QNetworkReply *CApplication::getFromNetwork(const CUrl &url, const CApplication::CallbackSlot &callback, int maxRedirects) { - return getFromNetwork(url.toNetworkRequest(), NoLogRequestId, callback, maxRedirects); + const CApplication::ProgressSlot progress; + return this->getFromNetwork(url, callback, progress, maxRedirects); } - QNetworkReply *CApplication::getFromNetwork(const CUrl &url, int logId, const CSlot &callback, int maxRedirects) + QNetworkReply *CApplication::getFromNetwork(const CUrl &url, const CApplication::CallbackSlot &callback, const CApplication::ProgressSlot &progress, int maxRedirects) { - return getFromNetwork(url.toNetworkRequest(), logId, callback, maxRedirects); + return this->getFromNetwork(url.toNetworkRequest(), NoLogRequestId, callback, progress, maxRedirects); } - QNetworkReply *CApplication::getFromNetwork(const QNetworkRequest &request, const CSlot &callback, int maxRedirects) + QNetworkReply *CApplication::getFromNetwork(const CUrl &url, int logId, const CApplication::CallbackSlot &callback, const CApplication::ProgressSlot &progress, int maxRedirects) { - return getFromNetwork(request, NoLogRequestId, callback, maxRedirects); + return this->getFromNetwork(url.toNetworkRequest(), logId, callback, progress, maxRedirects); } - QNetworkReply *CApplication::getFromNetwork(const QNetworkRequest &request, int logId, const CallbackSlot &callback, int maxRedirects) + QNetworkReply *CApplication::getFromNetwork(const QNetworkRequest &request, const CApplication::CallbackSlot &callback, int maxRedirects) { - return httpRequestImpl(request, logId, callback, maxRedirects, [](QNetworkAccessManager & qam, const QNetworkRequest & request) + const CApplication::ProgressSlot progress; + return this->getFromNetwork(request, callback, progress, maxRedirects); + } + + QNetworkReply *CApplication::getFromNetwork(const QNetworkRequest &request, const CApplication::CallbackSlot &callback, const CApplication::ProgressSlot &progress, int maxRedirects) + { + return this->getFromNetwork(request, NoLogRequestId, callback, progress, maxRedirects); + } + + QNetworkReply *CApplication::getFromNetwork(const QNetworkRequest &request, int logId, const CApplication::CallbackSlot &callback, const CApplication::ProgressSlot &progress, int maxRedirects) + { + return this->httpRequestImpl(request, logId, callback, progress, maxRedirects, [](QNetworkAccessManager & qam, const QNetworkRequest & request) { QNetworkReply *nr = qam.get(request); return nr; @@ -661,7 +674,7 @@ namespace BlackCore QNetworkReply *CApplication::postToNetwork(const QNetworkRequest &request, int logId, const QByteArray &data, const CSlot &callback) { - return httpRequestImpl(request, logId, callback, NoRedirects, [ data ](QNetworkAccessManager & qam, const QNetworkRequest & request) + return this->httpRequestImpl(request, logId, callback, NoRedirects, [ data ](QNetworkAccessManager & qam, const QNetworkRequest & request) { QNetworkReply *nr = qam.post(request, data); return nr; @@ -706,7 +719,7 @@ namespace BlackCore const QFileInfo fi(saveAsFileName); if (!fi.dir().exists()) { return nullptr; } - CallbackSlot slot([ = ](QNetworkReply * reply) + CallbackSlot callbackSlot([ = ](QNetworkReply * reply) { QScopedPointer nwReply(reply); CStatusMessage msg; @@ -728,8 +741,14 @@ namespace BlackCore callback(msg); }); }); - slot.setObject(this); // object for thread - QNetworkReply *reply = this->getFromNetwork(url, slot, maxRedirects); + + ProgressSlot progressSlot([ = ](int, qint64, qint64, const QUrl &) + { + // so far not implemented + }); + + callbackSlot.setObject(this); // object for thread + QNetworkReply *reply = this->getFromNetwork(url, callbackSlot, progressSlot, maxRedirects); return reply; } @@ -1693,7 +1712,7 @@ namespace BlackCore m_crashAndLogInfo.appendInfo(info); } - void CApplication::httpRequestImplInQAMThread(const QNetworkRequest &request, int logId, const CallbackSlot &callback, int maxRedirects, NetworkRequestOrPostFunction requestOrPostMethod) + void CApplication::httpRequestImplInQAMThread(const QNetworkRequest &request, int logId, const CallbackSlot &callback, const ProgressSlot &progress, int maxRedirects, NetworkRequestOrPostFunction requestOrPostMethod) { // run in QAM thread if (this->isShuttingDown()) { return; } @@ -1702,7 +1721,7 @@ namespace BlackCore // should be now in QAM thread if (!sApp || sApp->isShuttingDown()) { return; } Q_ASSERT_X(CThreadUtils::isCurrentThreadObjectThread(sApp->m_accessManager), Q_FUNC_INFO, "Wrong thread, must be QAM thread"); - this->httpRequestImpl(request, logId, callback, maxRedirects, requestOrPostMethod); + this->httpRequestImpl(request, logId, callback, progress, maxRedirects, requestOrPostMethod); }); } @@ -1722,7 +1741,15 @@ namespace BlackCore QNetworkReply *CApplication::httpRequestImpl( const QNetworkRequest &request, int logId, - const CallbackSlot &callback, int maxRedirects, NetworkRequestOrPostFunction requestOrPostMethod) + const CApplication::CallbackSlot &callback, int maxRedirects, NetworkRequestOrPostFunction requestOrPostMethod) + { + ProgressSlot progress; + return this->httpRequestImpl(request, logId, callback, progress, maxRedirects, requestOrPostMethod); + } + + QNetworkReply *CApplication::httpRequestImpl( + const QNetworkRequest &request, int logId, + const CallbackSlot &callback, const ProgressSlot &progress, int maxRedirects, NetworkRequestOrPostFunction requestOrPostMethod) { if (this->isShuttingDown()) { return nullptr; } if (!this->isNetworkAccessible()) { return nullptr; } @@ -1730,7 +1757,7 @@ namespace BlackCore Q_ASSERT_X(CThreadUtils::isApplicationThreadObjectThread(m_accessManager), Q_FUNC_INFO, "Network manager supposed to be in main thread"); if (!CThreadUtils::isCurrentThreadObjectThread(m_accessManager)) { - this->httpRequestImplInQAMThread(request, logId, callback, maxRedirects, requestOrPostMethod); + this->httpRequestImplInQAMThread(request, logId, callback, progress, maxRedirects, requestOrPostMethod); return nullptr; // not yet started, will be called again in QAM thread } @@ -1743,6 +1770,16 @@ namespace BlackCore QNetworkReply *reply = requestOrPostMethod(*m_accessManager, copiedRequest); reply->setProperty("started", QVariant(QDateTime::currentMSecsSinceEpoch())); reply->setProperty(CUrlLog::propertyNameId(), QVariant(logId)); + const QUrl url(reply->url()); + + if (progress) + { + connect(reply, &QNetworkReply::downloadProgress, progress.object(), [ = ](qint64 current, qint64 max) + { + progress(logId, current, max, url); + }); + } + if (callback) { Q_ASSERT_X(callback.object(), Q_FUNC_INFO, "Need callback object (to determine thread)"); @@ -1759,7 +1796,7 @@ namespace BlackCore { QNetworkRequest redirectRequest(redirectUrl); const int redirectsLeft = maxRedirects - 1; - this->httpRequestImplInQAMThread(redirectRequest, logId, callback, redirectsLeft, requestOrPostMethod); + this->httpRequestImplInQAMThread(redirectRequest, logId, callback, progress, redirectsLeft, requestOrPostMethod); return; } } diff --git a/src/blackcore/application.h b/src/blackcore/application.h index 48d349a02..209e16437 100644 --- a/src/blackcore/application.h +++ b/src/blackcore/application.h @@ -425,6 +425,9 @@ namespace BlackCore //! The network reply callback when request is completed using CallbackSlot = BlackMisc::CSlot; + //! The progress slot + using ProgressSlot = BlackMisc::CSlot; + //! Delete all cookies from cookie manager void deleteAllCookies(); @@ -475,20 +478,29 @@ namespace BlackCore QNetworkReply *getFromNetwork(const BlackMisc::Network::CUrl &url, const CallbackSlot &callback, int maxRedirects = DefaultMaxRedirects); + //! Request to get network reply + //! \threadsafe + QNetworkReply *getFromNetwork(const BlackMisc::Network::CUrl &url, + const CallbackSlot &callback, const ProgressSlot &progress, int maxRedirects = DefaultMaxRedirects); + //! Request to get network reply, supporting BlackMisc::Network::CUrlLog //! \threadsafe QNetworkReply *getFromNetwork(const BlackMisc::Network::CUrl &url, int logId, - const CallbackSlot &callback, int maxRedirects = DefaultMaxRedirects); + const CallbackSlot &callback, const ProgressSlot &progress, int maxRedirects = DefaultMaxRedirects); + + //! Request to get network reply + //! \threadsafe + QNetworkReply *getFromNetwork(const QNetworkRequest &request, const CallbackSlot &callback, int maxRedirects = DefaultMaxRedirects); //! Request to get network reply //! \threadsafe QNetworkReply *getFromNetwork(const QNetworkRequest &request, - const CallbackSlot &callback, int maxRedirects = DefaultMaxRedirects); + const CallbackSlot &callback, const ProgressSlot &progress, int maxRedirects = DefaultMaxRedirects); //! Request to get network reply, supporting BlackMisc::Network::CUrlLog //! \threadsafe QNetworkReply *getFromNetwork(const QNetworkRequest &request, int logId, - const CallbackSlot &callback, int maxRedirects = DefaultMaxRedirects); + const CallbackSlot &callback, const ProgressSlot &progress, int maxRedirects = DefaultMaxRedirects); //! Post to network //! \threadsafe @@ -645,15 +657,22 @@ namespace BlackCore using NetworkRequestOrPostFunction = std::function; + //! Implementation for getFromNetwork(), postToNetwork() and headerFromNetwork() //! \return QNetworkReply reply will only be returned, if the QNetworkAccessManager is in the same thread QNetworkReply *httpRequestImpl(const QNetworkRequest &request, int logId, const CallbackSlot &callback, int maxRedirects, NetworkRequestOrPostFunction requestOrPostMethod); + //! Implementation for getFromNetwork(), postToNetwork() and headerFromNetwork() + //! \return QNetworkReply reply will only be returned, if the QNetworkAccessManager is in the same thread + QNetworkReply *httpRequestImpl(const QNetworkRequest &request, + int logId, const CallbackSlot &callback, const ProgressSlot &progress, + int maxRedirects, NetworkRequestOrPostFunction requestOrPostMethod); + //! Call httpRequestImpl in correct thread void httpRequestImplInQAMThread(const QNetworkRequest &request, - int logId, const CallbackSlot &callback, + int logId, const CallbackSlot &callback, const ProgressSlot &progress, int maxRedirects, NetworkRequestOrPostFunction requestOrPostMethod); //! Triggers a check of the network accessibility diff --git a/src/blackcore/db/databasereader.cpp b/src/blackcore/db/databasereader.cpp index 2244e7396..907448224 100644 --- a/src/blackcore/db/databasereader.cpp +++ b/src/blackcore/db/databasereader.cpp @@ -201,6 +201,7 @@ namespace BlackCore QTimer::singleShot(0, this, [ = ] { if (!myself) { return; } + if (!sApp || sApp->isShuttingDown()) { return; } emit this->dataRead(validInCacheEntities, CEntityFlags::ReadFinished, 0); }); } @@ -220,7 +221,8 @@ namespace BlackCore if (entities == CEntityFlags::NoEntity) { return; } if (!this->isInternetAccessible(QStringLiteral("No network/internet access, will not read %1").arg(CEntityFlags::flagToString(entities)))) { return; } - //! \todo MS 2018-12 Error: CDatabaseReader has no ps_read method + //! \todo MS 2018-12 Error: CDatabaseReader has no ps_read method -> T490 + //! \todo KB 2018-12 https://dev.swift-project.org/T490 const bool s = QMetaObject::invokeMethod(this, "ps_read", Q_ARG(BlackMisc::Network::CEntityFlags::Entity, entities), Q_ARG(BlackMisc::Db::CDbFlags::DataRetrievalModeFlag, mode), @@ -674,6 +676,17 @@ namespace BlackCore << CThreadUtils::currentThreadInfo() << response.toQString(); } + void CDatabaseReader::networkReplyProgress(int logId, qint64 current, qint64 max, const QUrl &url) + { + CThreadedReader::networkReplyProgress(logId, current, max, url); + const QString fileName = url.fileName(); + const CEntityFlags::Entity entity = CEntityFlags::singleEntityByName(fileName); + if (CEntityFlags::isSingleEntity(entity)) + { + emit this->entityDownloadProgress(entity, logId, m_networkReplyProgress, m_networkReplyCurrent, m_networkReplyNax, url); + } + } + QString CDatabaseReader::fileNameForMode(CEntityFlags::Entity entity, CDbFlags::DataRetrievalModeFlag mode) { Q_ASSERT_X(CEntityFlags::isSingleEntity(entity), Q_FUNC_INFO, "needs single entity"); diff --git a/src/blackcore/db/databasereader.h b/src/blackcore/db/databasereader.h index a5f56e797..a8cd11dce 100644 --- a/src/blackcore/db/databasereader.h +++ b/src/blackcore/db/databasereader.h @@ -301,6 +301,13 @@ namespace BlackCore //! Header of shared file read void sharedFileHeaderRead(BlackMisc::Network::CEntityFlags::Entity entity, const QString &fileName, bool success); + //! Database reader messages + //! \remark used with splash screen + void databaseReaderMessages(const BlackMisc::CStatusMessageList &messages); + + //! Download progress for an entity + void entityDownloadProgress(BlackMisc::Network::CEntityFlags::Entity entity, int logId, int progress, qint64 current, qint64 max, const QUrl &url); + protected: CDatabaseReaderConfigList m_config; //!< DB reder configuration QString m_statusMessage; //!< Returned status message from watchdog @@ -421,6 +428,9 @@ namespace BlackCore //! Parsing info message void logParseMessage(const QString &entity, int size, int msElapsed, const JsonDatastoreResponse &response) const; + + //! Network request progress + virtual void networkReplyProgress(int logId, qint64 current, qint64 max, const QUrl &url) override; }; } // ns } // ns diff --git a/src/blackcore/setupreader.cpp b/src/blackcore/setupreader.cpp index dc430d32a..e50d1649b 100644 --- a/src/blackcore/setupreader.cpp +++ b/src/blackcore/setupreader.cpp @@ -243,7 +243,7 @@ namespace BlackCore if (!url.isEmpty()) { m1 = CStatusMessage(this, CStatusMessage::SeverityInfo, "Start reading bootstrap 1st URL: " + url.toQString()); - sApp->getFromNetwork(url.toNetworkRequest(), { this, &CSetupReader::parseBootstrapFile }); + sApp->getFromNetwork(url.toNetworkRequest(), { this, &CSetupReader::parseBootstrapFile }, { this, &CSetupReader::networkReplyProgress }); } else { @@ -265,7 +265,7 @@ namespace BlackCore CLogMessage(this).info(u"Cancel second bootstrap read ('%1'), as there was a 1st read: '%2'") << url.toQString() << m_lastSuccessfulSetupUrl; return; } - sApp->getFromNetwork(url.toNetworkRequest(), { this, &CSetupReader::parseBootstrapFile }); + sApp->getFromNetwork(url.toNetworkRequest(), { this, &CSetupReader::parseBootstrapFile }, { this, &CSetupReader::networkReplyProgress }); }); } else @@ -297,7 +297,7 @@ namespace BlackCore if (!sApp || m_shutdown) { return; } CUrl url = randomUrls.front(); const CStatusMessage m1(this, CStatusMessage::SeverityInfo, "Start reading update info 1st URL: " + url.toQString()); - sApp->getFromNetwork(url.toNetworkRequest(), { this, &CSetupReader::parseUpdateInfoFile }); + sApp->getFromNetwork(url.toNetworkRequest(), { this, &CSetupReader::parseUpdateInfoFile }, { this, &CSetupReader::networkReplyProgress }); url = randomUrls.back(); const CStatusMessage m2(this, CStatusMessage::SeverityInfo, "Will also trigger deferred update info reading 2nd URL: " + url.toQString()); @@ -311,7 +311,7 @@ namespace BlackCore CLogMessage(this).info(u"Cancel second update info read ('%1'), as there was a 1st read '%2'") << url.toQString() << m_lastSuccessfulUpdateInfoUrl; return; } - sApp->getFromNetwork(url.toNetworkRequest(), { this, &CSetupReader::parseUpdateInfoFile }); + sApp->getFromNetwork(url.toNetworkRequest(), { this, &CSetupReader::parseUpdateInfoFile }, { this, &CSetupReader::networkReplyProgress }); }); } @@ -651,6 +651,14 @@ namespace BlackCore m_setupReadErrorMsgs = messages.getErrorMessages(); } + void CSetupReader::networkReplyProgress(int logId, qint64 current, qint64 max, const QUrl &url) + { + Q_UNUSED(url); + Q_UNUSED(logId); + Q_UNUSED(current); + Q_UNUSED(max); + } + CStatusMessageList CSetupReader::manageSetupAvailability(bool webRead, bool localRead) { Q_ASSERT_X(!(webRead && localRead), Q_FUNC_INFO, "Local and web read together seems to be wrong"); diff --git a/src/blackcore/setupreader.h b/src/blackcore/setupreader.h index 9b8ccdaea..b18f2e4dd 100644 --- a/src/blackcore/setupreader.h +++ b/src/blackcore/setupreader.h @@ -219,6 +219,9 @@ namespace BlackCore //! Set last setup parsing messages void setLastSetupReadErrorMessages(const BlackMisc::CStatusMessageList &messages); + //! Progress + void networkReplyProgress(int logId, qint64 current, qint64 max, const QUrl &url); + //! Convert string to bootstrap mode static BootstrapMode stringToEnum(const QString &s); diff --git a/src/blackcore/threadedreader.cpp b/src/blackcore/threadedreader.cpp index 006f5b117..745526afe 100644 --- a/src/blackcore/threadedreader.cpp +++ b/src/blackcore/threadedreader.cpp @@ -171,7 +171,7 @@ namespace BlackCore return true; } - QNetworkReply *CThreadedReader::getFromNetworkAndLog(const CUrl &url, const BlackMisc::CSlot &callback) + QNetworkReply *CThreadedReader::getFromNetworkAndLog(const CUrl &url, const CSlot &callback) { QWriteLocker wl(&m_lock); const CUrlLogList outdatedPendingUrls = m_urlReadLog.findOutdatedPending(OutdatedPendingCallMs); @@ -185,7 +185,24 @@ namespace BlackCore wl.unlock(); // returned QNetworkReply normally nullptr since QAM is in different thread - return sApp->getFromNetwork(url, id, callback); + QNetworkReply *nr = sApp->getFromNetwork(url, id, callback, { this, &CThreadedReader::networkReplyProgress }); + return nr; + } + + QPair CThreadedReader::getNetworkReplyBytes() const + { + return QPair(m_networkReplyCurrent, m_networkReplyNax); + } + + void CThreadedReader::networkReplyProgress(int logId, qint64 current, qint64 max, const QUrl &url) + { + // max can be -1 if file size is not available + m_networkReplyProgress = (current > 0 && max > 0) ? static_cast((current * 100) / max) : -1; + m_networkReplyCurrent = current; + m_networkReplyNax = max; + + Q_UNUSED(url); + Q_UNUSED(logId); } void CThreadedReader::logNetworkReplyReceived(QNetworkReply *reply) diff --git a/src/blackcore/threadedreader.h b/src/blackcore/threadedreader.h index de4a4a99a..d287d613f 100644 --- a/src/blackcore/threadedreader.h +++ b/src/blackcore/threadedreader.h @@ -23,6 +23,7 @@ #include #include #include +#include #include class QNetworkReply; @@ -93,8 +94,18 @@ namespace BlackCore //! \threadsafe BlackMisc::Network::CUrlLogList getUrlLogList() const; + //! Progress 0..100 + //! \threadsafe + int getNetworkReplyProgress() const { return m_networkReplyProgress; } + + //! Max./current bytes + QPair getNetworkReplyBytes() const; + protected: mutable QReadWriteLock m_lock { QReadWriteLock::Recursive }; //!< lock which can be used from the derived classes + std::atomic_int m_networkReplyProgress; //!< Progress percentage 0...100 + std::atomic_llong m_networkReplyCurrent; //!< current bytes + std::atomic_llong m_networkReplyNax; //!< max bytes //! Constructor CThreadedReader(QObject *owner, const QString &name); @@ -123,6 +134,9 @@ namespace BlackCore //! \threadsafe read log access is thread safe QNetworkReply *getFromNetworkAndLog(const BlackMisc::Network::CUrl &url, const BlackMisc::CSlot &callback); + //! Network request progress + virtual void networkReplyProgress(int logId, qint64 current, qint64 max, const QUrl &url); + //! Network reply received, mark in m_urlReadLog //! \threadsafe void logNetworkReplyReceived(QNetworkReply *reply); diff --git a/src/blackcore/webdataservices.cpp b/src/blackcore/webdataservices.cpp index df99d82e9..7ec6b8163 100644 --- a/src/blackcore/webdataservices.cpp +++ b/src/blackcore/webdataservices.cpp @@ -1026,7 +1026,8 @@ namespace BlackCore const QPointer myself(this); QTimer::singleShot(100, this, [ = ]() { - if (!myself) { return; } + if (!myself || m_shuttingDown) { return; } + if (!sApp || sApp->isShuttingDown()) { return; } m_vatsimStatusReader->readInBackgroundThread(); }); } @@ -1082,6 +1083,8 @@ namespace BlackCore Q_ASSERT_X(c, Q_FUNC_INFO, "Cannot connect ICAO reader signals"); c = connect(m_icaoDataReader, &CIcaoDataReader::swiftDbDataRead, this, &CWebDataServices::swiftDbDataRead, typeReaderReadSignals); Q_ASSERT_X(c, Q_FUNC_INFO, "Cannot connect Model reader signals"); + c = connect(m_icaoDataReader, &CIcaoDataReader::entityDownloadProgress, this, &CWebDataServices::entityDownloadProgress, typeReaderReadSignals); + Q_ASSERT_X(c, Q_FUNC_INFO, "Cannot connect Model reader signals"); m_icaoDataReader->start(QThread::LowPriority); } @@ -1095,6 +1098,8 @@ namespace BlackCore Q_ASSERT_X(c, Q_FUNC_INFO, "Cannot connect Model reader signals"); c = connect(m_modelDataReader, &CModelDataReader::swiftDbDataRead, this, &CWebDataServices::swiftDbDataRead, typeReaderReadSignals); Q_ASSERT_X(c, Q_FUNC_INFO, "Cannot connect Model reader signals"); + c = connect(m_modelDataReader, &CModelDataReader::entityDownloadProgress, this, &CWebDataServices::entityDownloadProgress, typeReaderReadSignals); + Q_ASSERT_X(c, Q_FUNC_INFO, "Cannot connect Model reader signals"); m_modelDataReader->start(QThread::LowPriority); } @@ -1108,6 +1113,8 @@ namespace BlackCore Q_ASSERT_X(c, Q_FUNC_INFO, "Cannot connect Model reader signals"); c = connect(m_airportDataReader, &CAirportDataReader::swiftDbDataRead, this, &CWebDataServices::swiftDbDataRead, typeReaderReadSignals); Q_ASSERT_X(c, Q_FUNC_INFO, "Cannot connect Model reader signals"); + c = connect(m_airportDataReader, &CAirportDataReader::entityDownloadProgress, this, &CWebDataServices::entityDownloadProgress, typeReaderReadSignals); + Q_ASSERT_X(c, Q_FUNC_INFO, "Cannot connect Model reader signals"); m_airportDataReader->start(QThread::LowPriority); } Q_UNUSED(c); // signal connect flag @@ -1133,7 +1140,8 @@ namespace BlackCore const QPointer myself(this); QTimer::singleShot(0, this, [ = ] { - if (!myself) { return; } + if (!myself || m_shuttingDown) { return; } + if (!sApp || sApp->isShuttingDown()) { return; } this->initDbInfoObjectReaderAndTriggerRead(); }); return; @@ -1149,6 +1157,7 @@ namespace BlackCore // relay signal c = connect(m_dbInfoDataReader, &CInfoDataReader::dataRead, this, &CWebDataServices::dataRead); Q_ASSERT_X(c, Q_FUNC_INFO, "Info reader connect failed"); + c = connect(m_dbInfoDataReader, &CInfoDataReader::databaseReaderMessages, this, &CWebDataServices::databaseReaderMessages); Q_UNUSED(c); // start in own thread @@ -1158,6 +1167,7 @@ namespace BlackCore QTimer::singleShot(25, m_dbInfoDataReader, [ = ]() { if (!myself || m_shuttingDown) { return; } + if (!sApp || sApp->isShuttingDown()) { return; } m_dbInfoDataReader->read(); // trigger read of info objects }); } @@ -1384,7 +1394,7 @@ namespace BlackCore Q_ASSERT_X(m_dbInfoDataReader, Q_FUNC_INFO, "need reader"); if (m_dbInfoDataReader->areAllInfoObjectsRead()) { return true; } - if (!m_dbInfoObjectTimeout.isValid()) { m_dbInfoObjectTimeout = QDateTime::currentDateTimeUtc().addMSecs(10 * 1000); } + if (!m_dbInfoObjectTimeout.isValid()) { m_dbInfoObjectTimeout = QDateTime::currentDateTimeUtc().addMSecs(15 * 1000); } const bool read = this->waitForInfoObjectsThenRead(entities, "DB", m_dbInfoDataReader, m_dbInfoObjectTimeout); return read; } @@ -1395,7 +1405,7 @@ namespace BlackCore Q_ASSERT_X(m_sharedInfoDataReader, Q_FUNC_INFO, "need reader"); if (m_sharedInfoDataReader->areAllInfoObjectsRead()) { return true; } - if (!m_sharedInfoObjectsTimeout.isValid()) { m_sharedInfoObjectsTimeout = QDateTime::currentDateTimeUtc().addMSecs(10 * 1000); } + if (!m_sharedInfoObjectsTimeout.isValid()) { m_sharedInfoObjectsTimeout = QDateTime::currentDateTimeUtc().addMSecs(15 * 1000); } const bool read = this->waitForInfoObjectsThenRead(entities, "shared", m_sharedInfoDataReader, m_sharedInfoObjectsTimeout); return read; } diff --git a/src/blackcore/webdataservices.h b/src/blackcore/webdataservices.h index e628de58c..5900ba95f 100644 --- a/src/blackcore/webdataservices.h +++ b/src/blackcore/webdataservices.h @@ -492,6 +492,13 @@ namespace BlackCore //! Combined read signal void dataRead(BlackMisc::Network::CEntityFlags::Entity entity, BlackMisc::Network::CEntityFlags::ReadState state, int number); + //! Download progress for an entity + void entityDownloadProgress(BlackMisc::Network::CEntityFlags::Entity entity, int logId, int progress, qint64 current, qint64 max, const QUrl &url); + + //! Database reader messages + //! \remark used with splash screen + void databaseReaderMessages(const BlackMisc::CStatusMessageList &messages); + //! DB data read void swiftDbDataRead(bool success);