You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
139 lines
4.8 KiB
C++
139 lines
4.8 KiB
C++
/*
|
|
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
|
|
* its licensors.
|
|
*
|
|
* For complete copyright and license terms please see the LICENSE at the root of this
|
|
* distribution (the "License"). All use of this software is governed by the License,
|
|
* or, if provided, by the license below or the license accompanying this file. Do not
|
|
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
*
|
|
*/
|
|
|
|
#include "QtDownloader.h"
|
|
|
|
#include <QNetworkAccessManager>
|
|
#include <QNetworkRequest>
|
|
#include <QNetworkReply>
|
|
#include <QThread>
|
|
|
|
|
|
namespace News
|
|
{
|
|
QtDownloader::QtDownloader()
|
|
: m_thread(new QThread())
|
|
{
|
|
// make sure that everything that QObject::connects to us knows we're running in a different thread
|
|
moveToThread(m_thread);
|
|
|
|
// handle clean up of both ourselves and of our thread.
|
|
// We manage thread clean up so that it can keep running and be cleaned up later, regardless of what
|
|
// the thing that created the QtDownloader does
|
|
connect(m_thread, &QThread::finished, m_thread, [this] {
|
|
m_thread->deleteLater();
|
|
deleteLater();
|
|
});
|
|
|
|
auto abortDownloadsHandler = [this] {
|
|
auto replies = m_downloads.keys();
|
|
for (QNetworkReply* reply : replies)
|
|
{
|
|
reply->abort();
|
|
}
|
|
|
|
m_downloads.clear();
|
|
};
|
|
|
|
auto queueDownloadHandler = [this](int downloadId, QString url) {
|
|
if (m_networkManager)
|
|
{
|
|
QNetworkReply* reply = m_networkManager->get(QNetworkRequest(QUrl(url)));
|
|
m_downloads.insert(reply, downloadId);
|
|
}
|
|
};
|
|
|
|
auto createNetworkManagerHandler = [this] {
|
|
m_networkManager = new QNetworkAccessManager;
|
|
connect(m_networkManager, &QNetworkAccessManager::finished, this, &QtDownloader::downloadFinished);
|
|
};
|
|
|
|
auto deleteNetworkManagerHandler = [this] {
|
|
delete m_networkManager;
|
|
m_networkManager = nullptr;
|
|
};
|
|
|
|
auto quitHandler = [this] {
|
|
// call quit via this callback, so that it executes in the running thread.
|
|
// QThread::quit() is actually blocking and waits until everything finishes, so
|
|
// we don't want to call it in the main thread
|
|
m_thread->quit();
|
|
};
|
|
|
|
// make sure the response handlers are queued connections as the worker runs in one thread, but these triggers
|
|
// will be emitted from the main thread
|
|
connect(this, &QtDownloader::triggerAbortAll, this, abortDownloadsHandler, Qt::QueuedConnection);
|
|
connect(this, &QtDownloader::triggerDownload, this, queueDownloadHandler, Qt::QueuedConnection);
|
|
connect(this, &QtDownloader::triggerQuit, this, quitHandler, Qt::QueuedConnection);
|
|
|
|
// create/delete the QNetworkAccessManager in our thread, to ensure that any slowdowns caused by
|
|
// having to create network connectors / load drivers are done in our non-ui thread.
|
|
// make sure that these connections are direct so that network requests can't predate the network engine itself
|
|
connect(m_thread, &QThread::started, this, createNetworkManagerHandler, Qt::DirectConnection);
|
|
connect(m_thread, &QThread::finished, this, deleteNetworkManagerHandler, Qt::DirectConnection);
|
|
|
|
m_thread->start();
|
|
}
|
|
|
|
QtDownloader::~QtDownloader()
|
|
{
|
|
}
|
|
|
|
int QtDownloader::Download(const QString& url)
|
|
{
|
|
// create a unique id for this download
|
|
int downloadId = m_lastId++;
|
|
|
|
// trigger a download running in our worker thread
|
|
Q_EMIT triggerDownload(downloadId, url);
|
|
|
|
return downloadId;
|
|
}
|
|
|
|
void QtDownloader::Abort()
|
|
{
|
|
// trigger an abort in our worker thread
|
|
Q_EMIT triggerAbortAll();
|
|
}
|
|
|
|
void QtDownloader::Finish()
|
|
{
|
|
// trigger a quit in our worker thread
|
|
Q_EMIT triggerQuit();
|
|
}
|
|
|
|
void QtDownloader::downloadFinished(QNetworkReply* reply)
|
|
{
|
|
// Note: this will run in our worker thread
|
|
int downloadId = m_downloads[reply];
|
|
|
|
// emit the signal back to the main thread indicating that we're finished, either
|
|
// successfully or unsuccessfully
|
|
if (reply->error() == QNetworkReply::NoError)
|
|
{
|
|
Q_EMIT successfullyFinished(downloadId, reply->readAll());
|
|
}
|
|
else
|
|
{
|
|
Q_EMIT failed(downloadId);
|
|
}
|
|
|
|
// clean up the reply; have to do this later, according to the Qt docs
|
|
reply->deleteLater();
|
|
|
|
// make sure to remove our reference to this reply from our list of active downloads
|
|
m_downloads.remove(reply);
|
|
}
|
|
|
|
#include "NewsShared/ResourceManagement/moc_QtDownloader.cpp"
|
|
}
|