123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213 |
- #include "patchdownloader.h"
- #include "models/filesystem.h"
- #include <QApplication>
- #include <QDir>
- #include <QStringList>
- #include <QUrlQuery>
- #include <QVariant>
- #include <QDebug>
- PatchDownloader::PatchDownloader(QObject *parent) : QObject(parent)
- {
- patch_download_dir = QDir(QApplication::applicationDirPath() + "/data");
- connect(&update_check_timer, &QTimer::timeout, this, &PatchDownloader::checkForUpdates);
- update_check_timer.setInterval(1000 * 60 * 5); // 5 minutes
- update_check_timer.start();
- }
- PatchDownloader::~PatchDownloader()
- {
- clearDownloadQueue();
- }
- void PatchDownloader::checkForUpdates()
- {
- if (!download_queue.empty()) {
- qDebug() << "PatchDownloader: downloads are not ready yet, passing checkForUpdates";
- return;
- }
- if (!updatePatchList())
- return;
- removeOldPatchesFromDirecrory();
- addMissingPatchesToDownloadList();
- }
- void PatchDownloader::onDownloaderCompleted(Downloader *downloader_ptr)
- {
- downloader_ptr->targetFile->close();
- downloader_ptr->targetFile->deleteLater();
- }
- void PatchDownloader::onDownloaderProgressChanged(Downloader*)
- {
- quint64 totalSize = 0;
- quint64 downloadedSize = 0;
- quint64 summary_speed = 0;
- quint64 time_elapsed = 0;
- foreach (Downloader* downloader, download_queue) {
- totalSize += downloader->getBytesTotal();
- downloadedSize += downloader->getBytesDownloaded();
- if (downloader->getBytesTotal() != downloader->getBytesDownloaded()) {
- summary_speed += downloader->getSpeed();
- }
- }
- time_elapsed = (totalSize - downloadedSize) / qMax(quint64(1), summary_speed);
- if (totalSize == downloadedSize)
- emit downloadCompleted();
- else
- emit progressChanged(downloadedSize, totalSize,
- Downloader::getSpeedFormatted(summary_speed),
- Downloader::getElapsedTimeFormatted(time_elapsed));
- }
- int PatchDownloader::versionFromPatchFilename(QString filename)
- {
- int version = 0;
- for (int i = filename.indexOf("_v") + 2; i < filename.indexOf("_v") + 7; i += 2) {
- version = version * 10 + (filename.at(i).toLatin1() - '0');
- }
- return version;
- }
- bool PatchDownloader::updatePatchList()
- {
- QUrlQuery query; // query for building GET-request aka patch-version
- QStringList names;
- names << "sound" << "text" << "image" << "loadscreen" << "texture" << "font";
- foreach(QString patch_name, names) {
- query.addQueryItem(patch_name, "100");
- }
- QUrl target_url;
- target_url.setUrl("http://translate.lotros.ru/groupware/check_updates");
- target_url.setQuery(query);
- QByteArray target_array;
- Downloader downloader;
- downloader.setUrl(target_url);
- downloader.targetBytearray = &target_array;
- downloader.start();
- downloader.waitForDownloaded();
- if (target_array.isEmpty()) {
- qDebug() << __FUNCTION__ << "Cannot download, target_array is empty!";
- emit getPatchListError();
- return false;
- }
- QStringList entry_list = QString(target_array).split('|');
- if (entry_list.size() != names.size()) {
- qDebug() << __FUNCTION__ << "Entry list size is not equal to patch names size!" << QString(target_array);
- emit getPatchListError();
- return false;
- }
- patches.clear();
- for (int i = 0; i < entry_list.size(); ++i) {
- QStringList patch_data = entry_list[i].split(":::");
- if (patch_data.size() != 3) {
- qDebug() << __FUNCTION__ << "Incorrect patch entry size! Entry: " << entry_list[i];
- emit getPatchListError();
- return false;
- }
- patches.append({patch_data[0], patch_data[1], patch_data[2]});
- }
- return true;
- }
- bool PatchDownloader::removeOldPatchesFromDirecrory()
- {
- QStringList actual_hash_list;
- foreach (Patch patch, patches) {
- actual_hash_list.append(patch.md5_hash);
- }
- qDebug() << "Removing old patches. Current hash list " << actual_hash_list;
- QStringList paths = patch_download_dir.entryList(QDir::Files);
- foreach (QString filename, paths) {
- QString hash = FileSystem::fileHash(patch_download_dir.absolutePath() + "/" + filename, QCryptographicHash::Md5);
- if (!actual_hash_list.contains(hash)) {
- qDebug() << "File " << filename << " with hash " << hash << "seems outdated, deleting!";
- if (!QFile::remove(patch_download_dir.absolutePath() + "/" +filename)) {
- qDebug() << __FUNCTION__ << "Unable to remove file " << filename;
- emit removeFileError(patch_download_dir.absolutePath() + "/" + filename);
- }
- }
- }
- return true;
- }
- bool PatchDownloader::addMissingPatchesToDownloadList()
- {
- QStringList file_hashes;
- QStringList paths = patch_download_dir.entryList(QDir::Files);
- QDir dir(patch_download_dir);
- if (!dir.exists())
- QDir().mkdir(patch_download_dir.absolutePath());
- foreach (QString filename, paths) {
- file_hashes << FileSystem::fileHash(patch_download_dir.absolutePath() + "/" + filename, QCryptographicHash::Md5);
- }
- bool download_started = false;
- foreach (Patch patch, patches) {
- if (file_hashes.contains(patch.md5_hash))
- continue;
- QString patch_filepath = patch_download_dir.absolutePath() + "/" + patch.url.fileName();
- if (FileSystem::fileExists(patch_filepath) && !QFile::remove(patch_filepath)) {
- qDebug() << __FUNCTION__ << "Unable to remove file " << patch_filepath;
- emit removeFileError(patch_filepath);
- continue;
- }
- if (!download_started) {
- download_started = true;
- emit downloadStarted();
- }
- qDebug() << "Starting download of file " << patch_filepath << " from url " << patch.url;
- Downloader* downloader = new Downloader();
- connect(downloader, &Downloader::progressChanged, this, &PatchDownloader::onDownloaderProgressChanged);
- connect(downloader, &Downloader::downloadFinished, this, &PatchDownloader::onDownloaderCompleted);
- downloader->setUrl(patch.url);
- downloader->targetFile = new QFile(patch_filepath, downloader);
- downloader->targetFile->open(QIODevice::ReadWrite);
- downloader->start();
- download_queue.append(downloader);
- }
- return true;
- }
- void PatchDownloader::clearDownloadQueue()
- {
- for (int i = 0; i < download_queue.size(); ++i) {
- Downloader* downloader = download_queue[i];
- if (download_queue.indexOf(downloader) != i)
- continue; // this downloader was already stopped and deleted in previous iterations.
- // this shouldn't normally happen because it means that file was being downloaded many times
- downloader->stop();
- downloader->targetFile->close();
- downloader->targetFile->deleteLater();
- downloader->deleteLater();
- }
- download_queue.clear();
- }
|