##// END OF EJS Templates
Updates model after an event has been created through the colored zone
Updates model after an event has been created through the colored zone

File last commit:

r760:ba0e6f7d7791
r1231:073d4af7c849
Show More
NetworkController.cpp
148 lines | 5.5 KiB | text/x-c | CppLexer
/ core / src / Network / NetworkController.cpp
#include "Network/NetworkController.h"
#include <QMutex>
#include <QNetworkAccessManager>
#include <QNetworkReply>
#include <QNetworkRequest>
#include <QReadWriteLock>
#include <QThread>
#include <unordered_map>
Q_LOGGING_CATEGORY(LOG_NetworkController, "NetworkController")
struct NetworkController::NetworkControllerPrivate {
explicit NetworkControllerPrivate(NetworkController *parent) : m_WorkingMutex{} {}
void lockRead() { m_Lock.lockForRead(); }
void lockWrite() { m_Lock.lockForWrite(); }
void unlock() { m_Lock.unlock(); }
QMutex m_WorkingMutex;
QReadWriteLock m_Lock;
std::unordered_map<QNetworkReply *, QUuid> m_NetworkReplyToId;
std::unique_ptr<QNetworkAccessManager> m_AccessManager{nullptr};
};
NetworkController::NetworkController(QObject *parent)
: QObject(parent), impl{spimpl::make_unique_impl<NetworkControllerPrivate>(this)}
{
}
void NetworkController::onProcessRequested(std::shared_ptr<QNetworkRequest> request,
QUuid identifier,
std::function<void(QNetworkReply *, QUuid)> callback)
{
qCDebug(LOG_NetworkController()) << tr("NetworkController onProcessRequested")
<< QThread::currentThread()->objectName() << &request;
auto reply = impl->m_AccessManager->get(*request);
// Store the couple reply id
impl->lockWrite();
impl->m_NetworkReplyToId[reply] = identifier;
qCDebug(LOG_NetworkController()) << tr("Store for reply: ") << identifier;
impl->unlock();
auto onReplyFinished = [request, reply, this, identifier, callback]() {
qCDebug(LOG_NetworkController()) << tr("NetworkController onReplyFinished")
<< QThread::currentThread() << request.get() << reply;
impl->lockRead();
auto it = impl->m_NetworkReplyToId.find(reply);
if (it != impl->m_NetworkReplyToId.cend()) {
qCDebug(LOG_NetworkController()) << tr("Remove for reply: ") << it->second;
impl->unlock();
impl->lockWrite();
impl->m_NetworkReplyToId.erase(reply);
impl->unlock();
// Deletes reply
callback(reply, identifier);
reply->deleteLater();
}
else {
impl->unlock();
}
qCDebug(LOG_NetworkController()) << tr("NetworkController onReplyFinished END")
<< QThread::currentThread() << reply;
};
auto onReplyProgress = [reply, request, this](qint64 bytesRead, qint64 totalBytes) {
// NOTE: a totalbytes of 0 can happened when a request has been aborted
if (totalBytes > 0) {
double progress = (bytesRead * 100.0) / totalBytes;
qCDebug(LOG_NetworkController()) << tr("NetworkController onReplyProgress") << progress
<< QThread::currentThread() << request.get() << reply
<< bytesRead << totalBytes;
impl->lockRead();
auto it = impl->m_NetworkReplyToId.find(reply);
if (it != impl->m_NetworkReplyToId.cend()) {
auto id = it->second;
impl->unlock();
emit this->replyDownloadProgress(id, request, progress);
}
else {
impl->unlock();
}
qCDebug(LOG_NetworkController()) << tr("NetworkController onReplyProgress END")
<< QThread::currentThread() << reply;
}
};
connect(reply, &QNetworkReply::finished, this, onReplyFinished);
connect(reply, &QNetworkReply::downloadProgress, this, onReplyProgress);
qCDebug(LOG_NetworkController()) << tr("NetworkController registered END")
<< QThread::currentThread()->objectName() << reply;
}
void NetworkController::initialize()
{
qCDebug(LOG_NetworkController()) << tr("NetworkController init") << QThread::currentThread();
impl->m_WorkingMutex.lock();
impl->m_AccessManager = std::make_unique<QNetworkAccessManager>();
auto onReplyErrors = [this](QNetworkReply *reply, const QList<QSslError> &errors) {
qCCritical(LOG_NetworkController()) << tr("NetworkAcessManager errors: ") << errors;
};
connect(impl->m_AccessManager.get(), &QNetworkAccessManager::sslErrors, this, onReplyErrors);
qCDebug(LOG_NetworkController()) << tr("NetworkController init END");
}
void NetworkController::finalize()
{
impl->m_WorkingMutex.unlock();
}
void NetworkController::onReplyCanceled(QUuid identifier)
{
auto findReply = [identifier](const auto &entry) { return identifier == entry.second; };
qCDebug(LOG_NetworkController()) << tr("NetworkController onReplyCanceled")
<< QThread::currentThread() << identifier;
impl->lockRead();
auto end = impl->m_NetworkReplyToId.cend();
auto it = std::find_if(impl->m_NetworkReplyToId.cbegin(), end, findReply);
impl->unlock();
if (it != end) {
qCDebug(LOG_NetworkController()) << tr("NetworkController onReplyCanceled ABORT DONE")
<< QThread::currentThread() << identifier;
it->first->abort();
}
qCDebug(LOG_NetworkController()) << tr("NetworkController onReplyCanceled END")
<< QThread::currentThread();
}
void NetworkController::waitForFinish()
{
QMutexLocker locker{&impl->m_WorkingMutex};
}