diff --git a/src/blackcore/airportdatareader.cpp b/src/blackcore/airportdatareader.cpp index 622defb78..512d6caa8 100644 --- a/src/blackcore/airportdatareader.cpp +++ b/src/blackcore/airportdatareader.cpp @@ -61,7 +61,8 @@ namespace BlackCore return; } - CAirportList airports = CAirportList::fromDatabaseJson(array); + CAirportList airports; + airports.convertFromDatabaseJson(array); quint64 timestamp = lastModifiedMsSinceEpoch(nwReply); { diff --git a/src/blackcore/airportdatareader.h b/src/blackcore/airportdatareader.h index cc4dd148b..c4ebc8f66 100644 --- a/src/blackcore/airportdatareader.h +++ b/src/blackcore/airportdatareader.h @@ -61,7 +61,7 @@ namespace BlackCore void ps_airportCacheChanged(); private: - BlackMisc::CData m_airportCache {this, &CAirportDataReader::ps_airportCacheChanged}; + BlackMisc::CData m_airportCache {this, &CAirportDataReader::ps_airportCacheChanged}; mutable QReadWriteLock m_lock; quint64 m_lastModified = 0; //!< When was data file updated, obtained from HTTP Last-Modified header, in ms from epoch diff --git a/src/blackcore/application.cpp b/src/blackcore/application.cpp index 1bad68faf..db797b2d4 100644 --- a/src/blackcore/application.cpp +++ b/src/blackcore/application.cpp @@ -398,106 +398,44 @@ namespace BlackCore QNetworkReply *CApplication::getFromNetwork(const CUrl &url, const CSlot &callback) { - if (this->m_shutdown) { return nullptr; } - return getFromNetwork(url.toNetworkRequest(), callback); + return httpRequestImpl(url.toNetworkRequest(), callback, [ ] (QNetworkAccessManager &nam, const QNetworkRequest &request) { return nam.get(request); }); } QNetworkReply *CApplication::getFromNetwork(const QNetworkRequest &request, const CSlot &callback) { - if (this->m_shutdown) { return nullptr; } - QWriteLocker locker(&m_accessManagerLock); - Q_ASSERT_X(QCoreApplication::instance()->thread() == m_accessManager.thread(), Q_FUNC_INFO, "Network manager supposed to be in main thread"); - if (QThread::currentThread() != this->m_accessManager.thread()) - { - QTimer::singleShot(0, this, [this, request, callback]() { this->getFromNetwork(request, callback); }); - return nullptr; // not yet started - } - - Q_ASSERT_X(QThread::currentThread() == m_accessManager.thread(), Q_FUNC_INFO, "Network manager thread mismatch"); - QNetworkRequest r(request); // no QObject - CNetworkUtils::ignoreSslVerification(r); - CNetworkUtils::setSwiftUserAgent(r); - QNetworkReply *reply = this->m_accessManager.get(r); - if (callback) - { - connect(reply, &QNetworkReply::finished, callback.object(), [ = ] { callback(reply); }, Qt::QueuedConnection); - } - return reply; + return httpRequestImpl(request, callback, [ ] (QNetworkAccessManager &nam, const QNetworkRequest &request) { return nam.get(request); }); } QNetworkReply *CApplication::postToNetwork(const QNetworkRequest &request, const QByteArray &data, const CSlot &callback) { - if (this->m_shutdown) { return nullptr; } - QWriteLocker locker(&m_accessManagerLock); - Q_ASSERT_X(QCoreApplication::instance()->thread() == m_accessManager.thread(), Q_FUNC_INFO, "Network manager supposed to be in main thread"); - if (QThread::currentThread() != this->m_accessManager.thread()) - { - QTimer::singleShot(0, this, [this, request, data, callback]() { this->postToNetwork(request, data, callback); }); - return nullptr; // not yet started - } - - Q_ASSERT_X(QThread::currentThread() == m_accessManager.thread(), Q_FUNC_INFO, "Network manager thread mismatch"); - QNetworkRequest r(request); - CNetworkUtils::ignoreSslVerification(r); - CNetworkUtils::setSwiftUserAgent(r); - QNetworkReply *reply = this->m_accessManager.post(r, data); - if (callback) - { - connect(reply, &QNetworkReply::finished, callback.object(), [ = ] { callback(reply); }, Qt::QueuedConnection); - } - return reply; + return httpRequestImpl(request, callback, [ data ] (QNetworkAccessManager &nam, const QNetworkRequest &request) { return nam.post(request, data); }); } QNetworkReply *CApplication::postToNetwork(const QNetworkRequest &request, QHttpMultiPart *multiPart, const CSlot &callback) { - if (this->m_shutdown) { return nullptr; } - QWriteLocker locker(&m_accessManagerLock); - Q_ASSERT_X(QCoreApplication::instance()->thread() == m_accessManager.thread(), Q_FUNC_INFO, "Network manager supposed to be in main thread"); if (QThread::currentThread() != this->m_accessManager.thread()) { - QTimer::singleShot(0, this, [this, request, multiPart, callback]() { this->postToNetwork(request, multiPart, callback); }); - return nullptr; // not yet started + multiPart->moveToThread(this->m_accessManager.thread()); } - Q_ASSERT_X(QThread::currentThread() == m_accessManager.thread(), Q_FUNC_INFO, "Network manager thread mismatch"); - QNetworkRequest r(request); - CNetworkUtils::ignoreSslVerification(r); - CNetworkUtils::setSwiftUserAgent(r); - QNetworkReply *reply = this->m_accessManager.post(r, multiPart); - if (callback) - { - connect(reply, &QNetworkReply::finished, callback.object(), [ = ] { callback(reply); }); - } - return reply; + return httpRequestImpl(request, callback, [ this, multiPart ] (QNetworkAccessManager &nam, const QNetworkRequest &request) + { + QNetworkReply *reply = nam.post(request, multiPart); + Q_ASSERT(reply); + multiPart->setParent(reply); + return reply; + } + ); } QNetworkReply *CApplication::headerFromNetwork(const CUrl &url, const BlackMisc::CSlot &callback) { - if (this->m_shutdown) { return nullptr; } - return headerFromNetwork(url.toNetworkRequest(), callback); + return httpRequestImpl(url.toNetworkRequest(), callback, [ ] (QNetworkAccessManager &nam, const QNetworkRequest &request) { return nam.head(request); }); } QNetworkReply *CApplication::headerFromNetwork(const QNetworkRequest &request, const BlackMisc::CSlot &callback) { - if (this->m_shutdown) { return nullptr; } - QWriteLocker locker(&m_accessManagerLock); - Q_ASSERT_X(QCoreApplication::instance()->thread() == m_accessManager.thread(), Q_FUNC_INFO, "Network manager supposed to be in main thread"); - if (QThread::currentThread() != this->m_accessManager.thread()) - { - QTimer::singleShot(0, this, [this, request, callback]() { this->headerFromNetwork(request, callback); }); - return nullptr; // not yet started - } - - Q_ASSERT_X(QThread::currentThread() == m_accessManager.thread(), Q_FUNC_INFO, "Network manager thread mismatch"); - QNetworkRequest r(request); // no QObject - CNetworkUtils::ignoreSslVerification(r); - CNetworkUtils::setSwiftUserAgent(r); - QNetworkReply *reply = this->m_accessManager.head(r); - if (callback) - { - connect(reply, &QNetworkReply::finished, callback.object(), [ = ] { callback(reply); }, Qt::QueuedConnection); - } - return reply; + return httpRequestImpl(request, callback, [ ] (QNetworkAccessManager &nam, const QNetworkRequest &request) { return nam.head(request); }); } void CApplication::deleteAllCookies() @@ -1060,4 +998,27 @@ namespace BlackCore #endif } + QNetworkReply *CApplication::httpRequestImpl(const QNetworkRequest &request, const BlackMisc::CSlot &callback, std::function method) + { + if (this->m_shutdown) { return nullptr; } + QWriteLocker locker(&m_accessManagerLock); + Q_ASSERT_X(QCoreApplication::instance()->thread() == m_accessManager.thread(), Q_FUNC_INFO, "Network manager supposed to be in main thread"); + if (QThread::currentThread() != this->m_accessManager.thread()) + { +// QTimer::singleShot(0, this, [this, request, callback, method]() { this->httpRequestImpl(request, callback, method); }); + QTimer::singleShot(0, this, std::bind(&CApplication::httpRequestImpl, this, request, callback, method)); + return nullptr; // not yet started + } + + Q_ASSERT_X(QThread::currentThread() == m_accessManager.thread(), Q_FUNC_INFO, "Network manager thread mismatch"); + QNetworkRequest r(request); // no QObject + CNetworkUtils::ignoreSslVerification(r); + CNetworkUtils::setSwiftUserAgent(r); + QNetworkReply *reply = method(this->m_accessManager, r); + if (callback) + { + connect(reply, &QNetworkReply::finished, callback.object(), [ = ] { callback(reply); }, Qt::QueuedConnection); + } + return reply; + } } // ns diff --git a/src/blackcore/application.h b/src/blackcore/application.h index 4e33d9e45..6bc53dcb9 100644 --- a/src/blackcore/application.h +++ b/src/blackcore/application.h @@ -23,6 +23,7 @@ #include #include #include +#include #include "blackcore/blackcoreexport.h" #include "blackcore/cookiemanager.h" @@ -321,6 +322,7 @@ namespace BlackCore const BlackMisc::CSlot &callback); //! Post to network + //! \note This method takes ownership over \c multiPart. //! \threadsafe QNetworkReply *postToNetwork(const QNetworkRequest &request, QHttpMultiPart *multiPart, const BlackMisc::CSlot &callback); @@ -427,6 +429,11 @@ namespace BlackCore void crashDumpUploadEnabledChanged(); + //! Implementation for getFromNetwork(), postToNetwork() and headerFromNetwork() + QNetworkReply *httpRequestImpl(const QNetworkRequest &request, + const BlackMisc::CSlot &callback, + std::function method); + QScopedPointer m_coreFacade; //!< core facade if any QScopedPointer m_setupReader; //!< setup reader QScopedPointer m_webDataServices; //!< web data services diff --git a/src/blackcore/data/dbcaches.h b/src/blackcore/data/dbcaches.h index 980059ff8..e8561c124 100644 --- a/src/blackcore/data/dbcaches.h +++ b/src/blackcore/data/dbcaches.h @@ -111,7 +111,7 @@ namespace BlackCore }; //! Trait for airport list - struct DbAirportCache : public BlackMisc::CDataTrait + struct TDbAirportCache : public BlackMisc::TDataTrait { //! Defer loading static constexpr bool isDeferred() { return true; } diff --git a/src/blackcore/db/databasewriter.cpp b/src/blackcore/db/databasewriter.cpp index 526314c1c..b497d034e 100644 --- a/src/blackcore/db/databasewriter.cpp +++ b/src/blackcore/db/databasewriter.cpp @@ -66,7 +66,6 @@ namespace BlackCore } m_pendingReply = sApp->postToNetwork(request, multiPart, { this, &CDatabaseWriter::ps_postResponse}); - multiPart->setParent(m_pendingReply); return msgs; } diff --git a/src/blackcore/webreaderflags.h b/src/blackcore/webreaderflags.h index af35c49b0..3877f9bdd 100644 --- a/src/blackcore/webreaderflags.h +++ b/src/blackcore/webreaderflags.h @@ -39,8 +39,8 @@ namespace BlackCore AirportReader = 1 << 6, //!< reader for airport list InfoDataReader = 1 << 7, //!< DB info data (metdata, how many data, when updated) AllVatsimReaders = VatsimBookingReader | VatsimDataReader | VatsimMetarReader | VatsimStatusReader, //!< all VATSIM readers - AllSwiftDbReaders = IcaoDataReader | ModelReader | AirportReader | InfoDataReader, //!< all swift data - AllReaders = AllSwiftDbReaders | AllVatsimReaders //!< everything + AllSwiftDbReaders = IcaoDataReader | ModelReader | InfoDataReader, //!< all swift data + AllReaders = AirportReader | AllSwiftDbReaders | AllVatsimReaders //!< everything }; Q_DECLARE_FLAGS(WebReader, WebReaderFlag) diff --git a/src/blackmisc/aviation/airport.cpp b/src/blackmisc/aviation/airport.cpp index 0173870ea..16352e30b 100644 --- a/src/blackmisc/aviation/airport.cpp +++ b/src/blackmisc/aviation/airport.cpp @@ -52,13 +52,16 @@ namespace BlackMisc (void)QT_TRANSLATE_NOOP("Aviation", "Airport"); } - void CAirport::fromDatabaseJson(const QJsonObject &json) + void CAirport::convertFromDatabaseJson(const QJsonObject &json) { Q_ASSERT(json.value("icao").isString()); setIcao(json.value("icao").toString()); - Q_ASSERT(json.value("country").isString()); - setCountry(json.value("country").toString()); + if (json.value("alpha3").isString() && json.value("country").isString()) + { + CCountry country(json.value("alpha3").toString(), json.value("country").toString()); + setCountry(country); + } Q_ASSERT(json.value("name").isString()); setDescriptiveName(json.value("name").toString()); diff --git a/src/blackmisc/aviation/airport.h b/src/blackmisc/aviation/airport.h index 6d3364830..27fa17503 100644 --- a/src/blackmisc/aviation/airport.h +++ b/src/blackmisc/aviation/airport.h @@ -19,6 +19,7 @@ #include "blackmisc/geo/longitude.h" #include "blackmisc/metaclass.h" #include "blackmisc/pq/length.h" +#include "blackmisc/country.h" #include "blackmisc/propertyindex.h" #include "blackmisc/valueobject.h" #include "blackmisc/variant.h" @@ -80,10 +81,10 @@ namespace BlackMisc void setPosition(const BlackMisc::Geo::CCoordinateGeodetic &position) { this->m_position = position; } //! Get the country - QString getCountry() const { return m_country; } + const CCountry& getCountry() const { return m_country; } //! Set the country - void setCountry(const QString &country) { this->m_country = country; } + void setCountry(const CCountry &country) { this->m_country = country; } //! Elevation //! \sa geodeticHeight @@ -131,13 +132,13 @@ namespace BlackMisc QString convertToQString(bool i18n = false) const; //! \copydoc BlackMisc::CValueObject::convertFromJson - void fromDatabaseJson(const QJsonObject &json); + void convertFromDatabaseJson(const QJsonObject &json); private: CAirportIcaoCode m_icao; QString m_descriptiveName; BlackMisc::Geo::CCoordinateGeodetic m_position; - QString m_country; + CCountry m_country; BLACK_METACLASS( CAirport, diff --git a/src/blackmisc/aviation/airportlist.cpp b/src/blackmisc/aviation/airportlist.cpp index fc2858ac5..57bbee206 100644 --- a/src/blackmisc/aviation/airportlist.cpp +++ b/src/blackmisc/aviation/airportlist.cpp @@ -44,18 +44,17 @@ namespace BlackMisc return this->findFirstByOrDefault(&CAirport::getIcao, icao, ifNotFound); } - CAirportList CAirportList::fromDatabaseJson(const QJsonArray &json) + void CAirportList::convertFromDatabaseJson(const QJsonArray &json) { - CAirportList airports; + clear(); + for (const QJsonValue& value: json) { QJsonObject object = value.toObject(); CAirport airport; - airport.fromDatabaseJson(object); - airports.push_back(airport); + airport.convertFromDatabaseJson(object); + push_back(airport); } - - return airports; } } // namespace diff --git a/src/blackmisc/aviation/airportlist.h b/src/blackmisc/aviation/airportlist.h index d894e6286..ba4946d6f 100644 --- a/src/blackmisc/aviation/airportlist.h +++ b/src/blackmisc/aviation/airportlist.h @@ -50,8 +50,9 @@ namespace BlackMisc //! Find first station by callsign, if not return given value / default CAirport findFirstByIcao(const CAirportIcaoCode &icao, const CAirport &ifNotFound = CAirport()) const; - //! Reads the airport list from JSON - static CAirportList fromDatabaseJson(const QJsonArray& json); + //! Reads the airport list from database JSON + void convertFromDatabaseJson(const QJsonArray& json); + }; } //namespace } // namespace