123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165 |
- /*
- * cdownloadmanager_moc.cpp, part of VCMI engine
- *
- * Authors: listed in file AUTHORS in main folder
- *
- * License: GNU General Public License v2.0 or later
- * Full text of license available in license.txt file, in main folder
- *
- */
- #include "StdInc.h"
- #include "cdownloadmanager_moc.h"
- #include "../vcmiqt/launcherdirs.h"
- #include "../../lib/CConfigHandler.h"
- CDownloadManager::CDownloadManager()
- {
- connect(&manager, SIGNAL(finished(QNetworkReply *)),
- SLOT(downloadFinished(QNetworkReply *)));
- connect(&manager, &QNetworkAccessManager::sslErrors, [](QNetworkReply * reply, const QList<QSslError> & errors) {
- if(settings["launcher"]["ignoreSslErrors"].Bool())
- reply->ignoreSslErrors();
- });
- }
- void CDownloadManager::downloadFile(const QUrl & url, const QString & file, qint64 bytesTotal)
- {
- QNetworkRequest request(url);
- FileEntry entry;
- entry.file.reset(new QFile(QString{QLatin1String{"%1/%2"}}.arg(CLauncherDirs::downloadsPath(), file)));
- entry.bytesReceived = 0;
- entry.totalSize = bytesTotal;
- entry.filename = file;
- if(entry.file->open(QIODevice::WriteOnly | QIODevice::Truncate))
- {
- entry.status = FileEntry::IN_PROGRESS;
- entry.reply = manager.get(request);
- connect(entry.reply, SIGNAL(downloadProgress(qint64,qint64)),
- SLOT(downloadProgressChanged(qint64,qint64)));
- }
- else
- {
- entry.status = FileEntry::FAILED;
- entry.reply = nullptr;
- encounteredErrors += entry.file->errorString();
- }
- // even if failed - add it into list to report it in finished() call
- currentDownloads.push_back(entry);
- }
- CDownloadManager::FileEntry & CDownloadManager::getEntry(QNetworkReply * reply)
- {
- assert(reply);
- for(auto & entry : currentDownloads)
- {
- if(entry.reply == reply)
- return entry;
- }
- throw std::runtime_error("Failed to find download entry");
- }
- void CDownloadManager::downloadFinished(QNetworkReply * reply)
- {
- FileEntry & file = getEntry(reply);
- QVariant possibleRedirectUrl = reply->attribute(QNetworkRequest::RedirectionTargetAttribute);
- QUrl qurl = possibleRedirectUrl.toUrl();
- if(possibleRedirectUrl.isValid())
- {
- QString filename;
- qint64 totalSize = 0;
- for(int i = 0; i< currentDownloads.size(); ++i)
- {
- if(currentDownloads[i].file == file.file)
- {
- filename = currentDownloads[i].filename;
- totalSize = currentDownloads[i].totalSize;
- currentDownloads.removeAt(i);
- break;
- }
- }
- downloadFile(qurl, filename, totalSize);
- return;
- }
- if(file.reply->error())
- {
- encounteredErrors += file.reply->errorString();
- file.file->remove();
- file.status = FileEntry::FAILED;
- }
- else
- {
- file.file->write(file.reply->readAll());
- file.file->close();
- file.status = FileEntry::FINISHED;
- }
- bool downloadComplete = true;
- for(auto & entry : currentDownloads)
- {
- if(entry.status == FileEntry::IN_PROGRESS)
- {
- downloadComplete = false;
- break;
- }
- }
- QStringList successful;
- QStringList failed;
- for(auto & entry : currentDownloads)
- {
- if(entry.status == FileEntry::FINISHED)
- successful += entry.file->fileName();
- else
- failed += entry.file->fileName();
- }
- if(downloadComplete)
- Q_EMIT finished(successful, failed, encounteredErrors);
- file.reply->deleteLater();
- file.reply = nullptr;
- }
- void CDownloadManager::downloadProgressChanged(qint64 bytesReceived, qint64 bytesTotal)
- {
- auto reply = dynamic_cast<QNetworkReply *>(sender());
- FileEntry & entry = getEntry(reply);
- entry.file->write(entry.reply->readAll());
- entry.bytesReceived = bytesReceived;
- if(bytesTotal > entry.totalSize)
- entry.totalSize = bytesTotal;
- quint64 total = 0;
- for(auto & entry : currentDownloads)
- total += entry.totalSize > 0 ? entry.totalSize : entry.bytesReceived;
- quint64 received = 0;
- for(auto & entry : currentDownloads)
- received += entry.bytesReceived > 0 ? entry.bytesReceived : 0;
- if(received > total)
- total = received;
- Q_EMIT downloadProgress(received, total);
- }
- bool CDownloadManager::downloadInProgress(const QUrl & url) const
- {
- for(auto & entry : currentDownloads)
- {
- if(entry.reply->url() == url)
- return true;
- }
- return false;
- }
|