#include "app.h" #include "filesystem.h" #include "lotromanager.h" #include #include #include #include #include #include #include #include DownloadManager::DownloadManager(QObject *parent) : QObject(parent), downloadedCount(0), totalCount(0) { busy = false; } void DownloadManager::append(const QStringList &urlList){ foreach (QString url, urlList) append(QUrl::fromEncoded(url.toUtf8())); if (downloadQueue.isEmpty()) QTimer::singleShot(0, this, SIGNAL(finished())); } void DownloadManager::append(const QUrl &url){ qDebug("%s:%i: %s%s", __FILE__, __LINE__, "Добавлен файл для скачивания: ", url.fileName().toUtf8().data()); if (downloadQueue.count(url) == 0) { downloadQueue.enqueue(url); ++totalCount; } else { qDebug("%s:%i: %s %s%s", __FILE__, __LINE__, "Не добавляю закачку " , url.fileName().toUtf8().data() , ", так как она уже находится в очереди закачек"); } qDebug("%s:%i: %s%i", __FILE__, __LINE__, "Загрузок в списке: ", totalCount); //if (!busy) // QTimer::singleShot(0, this, SLOT(startNextDownload())); } void DownloadManager::startDownloads() { if (!busy) QTimer::singleShot(0, this, SLOT(startNextDownload())); } void DownloadManager::startNextDownload() { current_speed = ""; bytesReceivedBeforeSecond = 0; timeElapsedBeforeSecond = 0; elapsed_time = "высчитывается..."; if (busy) { qWarning("%s:%i: %s", __FILE__, __LINE__, "Ошибка! Обнаружена попытка начала загрузки, когда не завершилась другая загрузка"); return; } App *app = &App::getInstance(); app->helper->setState("busy"); busy = true; if (downloadQueue.isEmpty()) { app->helper->setState("free");// говорим что приложение освободилось qDebug("%s:%i: %s%d/%d", __FILE__, __LINE__, "Загрузка завершена. Загружено файлов: ", downloadedCount, totalCount); busy = false; emit finished(); return; } QUrl url = downloadQueue.dequeue(); QString filename = QFileInfo(url.path()).fileName(); output.setFileName(QApplication::applicationDirPath() + "/data/" + filename); qDebug("%s:%i: %s%s", __FILE__, __LINE__, "Начата загрузка файла: ", filename.toUtf8().data()); // Проверяем целостность файла и игнорируем в случае если он цел QString hash = FileSystem::fileHash(QApplication::applicationDirPath() + "/data/" + filename, QCryptographicHash::Md5); QStringList pname = output.fileName().split("/"); QStringList ptype = pname.last().split("_"); qDebug() << ptype.first(); QString keyname = ptype.first(); if(keyname == "loadscreens") keyname = "screens"; if(hash == app->config->getValue("Hashes", ptype.first()) && app->config->getValue("Editor", keyname) == "true"){ qDebug("%s:%i: %s%s", __FILE__, __LINE__, "Проверка хэша успешно завершена: ", filename.toUtf8().data()); busy = false; QTimer::singleShot(0, this, SLOT(startNextDownload())); return; } qDebug("%s:%i: %s%s", __FILE__, __LINE__, "Хэш файла не совпал: ", filename.toUtf8().data()); QStringList parsename = filename.split("_"); QString name = parsename[0] + "Status"; download_name = parsename[0]; // Проверка, что файл не был отменён if(app->config->getValue("Editor", download_name) == "false") { emit changePatchStatus(download_name, "Отменён"); busy = false; QTimer::singleShot(0, this, SLOT(startNextDownload())); return; } if (!output.open(QIODevice::WriteOnly)) { qWarning("%s:%i: %s%s", __FILE__, __LINE__, "Произошла остановка скачивания (не могу открыть файл) " , filename.toUtf8().data()); emit changePatchStatus(download_name, "Ошибка записи"); busy = false; QTimer::singleShot(0, this, SLOT(startNextDownload())); return; } qInfo("%s:%i: %s%s", __FILE__, __LINE__, "Начинаем скачивание ", url.fileName().toUtf8().data()); QNetworkRequest request(url); currentDownload = manager.get(request); connect(this, SIGNAL(cancelDownload()), currentDownload, SLOT(abort())); connect(currentDownload, SIGNAL(downloadProgress(qint64,qint64)), SLOT(downloadProgress(qint64,qint64))); connect(currentDownload, SIGNAL(finished()), SLOT(downloadFinished())); connect(currentDownload, SIGNAL(readyRead()), SLOT(downloadReadyRead())); // prepare the output downloadTime.start(); } void DownloadManager::downloadProgress(qint64 bytesReceived, qint64 bytesTotal) { App* app = &App::getInstance(); double speed = (bytesReceived - bytesReceivedBeforeSecond) * 1000.0 / (downloadTime.elapsed() - timeElapsedBeforeSecond); double percent = double(std::ceil(((double)bytesReceived/ bytesTotal) * 100 * 10)) / 10.0; QString unit; if (speed < 1024) { unit = "bytes/sec"; } else if (speed < 1024*1024) { speed /= 1024; unit = "kB/s"; } else { speed /= 1024*1024; unit = "MB/s"; } QString speedtext = QString::fromLatin1("%1 %2").arg(speed, 3, 'f', 1).arg(unit); QString percenttext = QString::fromLatin1("%1").arg(percent, 3, 'f', 1); if (downloadTime.elapsed() - timeElapsedBeforeSecond >= 1000) { timeElapsedBeforeSecond = downloadTime.elapsed(); bytesReceivedBeforeSecond = bytesReceived; current_speed = speedtext; elapsed_time = app->helper->countFormattedElapsedTime(bytesTotal - bytesReceived, bytesReceived * 1000.0 / downloadTime.elapsed()); } if (current_speed == "") current_speed = speedtext; emit changePatchStatus(download_name, "Загрузка ...
" + percenttext + "% (" + current_speed + ")"); emit changeHint("Загрузка патча " + LotroManager::getInstance().patchTitleFromName(download_name), "Завершено " + percenttext + "% (" + current_speed + "). Оставшееся время: " + elapsed_time); } void DownloadManager::downloadFinished() { busy = false; output.close(); qDebug() << "Finished download: " << output.fileName().split('/').last().split('_')[0]; downloaded_list.append(output.fileName().split('/').last().split('_')[0]); App *app = &App::getInstance(); app->helper->setState("free");// говорим что приложение освободилось if (currentDownload->error()) { qWarning("%s:%i: %s%s", __FILE__, __LINE__, "Загрузка не удалась: ", currentDownload->errorString().toUtf8().data()); emit changePatchStatus(download_name, "Не удалась"); } else { emit changePatchStatus(download_name, "Готово"); ++downloadedCount; } if (downloadQueue.isEmpty()) { qInfo("%s:%i: %s", __FILE__, __LINE__, "Все загрузки завершены. Загрузчик завершил свою работу."); emit allDownloadsFinished(downloaded_list); } else { QTimer::singleShot(0, this, SLOT(startNextDownload())); } currentDownload->deleteLater(); } void DownloadManager::downloadReadyRead(){ output.write(currentDownload->readAll()); } void DownloadManager::abortDownload(QString name){ App *app = &App::getInstance(); if(download_name == name){ if(app->state != "free" && currentDownload != NULL && currentDownload->isOpen()) { qDebug() << "Прерываем закачку " + download_name; qInfo("%s:%i: %s%s", __FILE__, __LINE__, "Пользователь прервал закачку файла ", download_name.toUtf8().data()); emit changePatchStatus(name, "Отменён"); currentDownload->abort(); } } downloadQueue.removeAll(name); } int DownloadManager::getDownloadedCount() { return downloadedCount; } void DownloadManager::resetDownloadedCount() { totalCount = 0; downloadedCount = 0; downloaded_list.clear(); }