From 30c177cb371e92fe5e4cfc600cf27586402cf0a8 Mon Sep 17 00:00:00 2001 From: Silarn Date: Mon, 16 Apr 2018 12:47:17 -0500 Subject: Support for multi-game downloads --- src/downloadmanager.cpp | 76 ++++++++++++++++++++++++++++--------------------- 1 file changed, 44 insertions(+), 32 deletions(-) (limited to 'src/downloadmanager.cpp') diff --git a/src/downloadmanager.cpp b/src/downloadmanager.cpp index 569a7d31..d54d6f24 100644 --- a/src/downloadmanager.cpp +++ b/src/downloadmanager.cpp @@ -23,6 +23,7 @@ along with Mod Organizer. If not, see . #include "nexusinterface.h" #include "nxmaccessmanager.h" #include "iplugingame.h" +#include "downloadmanager.h" #include #include #include "utility.h" @@ -113,15 +114,17 @@ DownloadManager::DownloadInfo *DownloadManager::DownloadInfo::createFromMeta(con info->m_Urls = metaFile.value("url", "").toString().split(";"); info->m_Tries = 0; info->m_TaskProgressId = TaskProgressManager::instance().getId(); + QString gameName = metaFile.value("gameName", "").toString(); int modID = metaFile.value("modID", 0).toInt(); int fileID = metaFile.value("fileID", 0).toInt(); - info->m_FileInfo = new ModRepositoryFileInfo(modID, fileID); + info->m_FileInfo = new ModRepositoryFileInfo(gameName, modID, fileID); info->m_FileInfo->name = metaFile.value("name", "").toString(); if (info->m_FileInfo->name == "0") { // bug in earlier version info->m_FileInfo->name = ""; } info->m_FileInfo->modName = metaFile.value("modName", "").toString(); + info->m_FileInfo->gameName = gameName; info->m_FileInfo->modID = modID; info->m_FileInfo->fileID = fileID; info->m_FileInfo->description = metaFile.value("description").toString(); @@ -260,6 +263,11 @@ void DownloadManager::setShowHidden(bool showHidden) refreshList(); } +void DownloadManager::setPluginContainer(PluginContainer *pluginContainer) +{ + m_NexusInterface->setPluginContainer(pluginContainer); +} + void DownloadManager::refreshList() { try { @@ -329,7 +337,7 @@ void DownloadManager::refreshList() } -bool DownloadManager::addDownload(const QStringList &URLs, +bool DownloadManager::addDownload(const QStringList &URLs, QString gameName, int modID, int fileID, const ModRepositoryFileInfo *fileInfo) { QString fileName = QFileInfo(URLs.first()).fileName(); @@ -340,7 +348,7 @@ bool DownloadManager::addDownload(const QStringList &URLs, QUrl preferredUrl = QUrl::fromEncoded(URLs.first().toLocal8Bit()); qDebug("selected download url: %s", qPrintable(preferredUrl.toString())); QNetworkRequest request(preferredUrl); - return addDownload(m_NexusInterface->getAccessManager()->get(request), URLs, fileName, modID, fileID, fileInfo); + return addDownload(m_NexusInterface->getAccessManager()->get(request), URLs, fileName, gameName, modID, fileID, fileInfo); } @@ -351,12 +359,12 @@ bool DownloadManager::addDownload(QNetworkReply *reply, const ModRepositoryFileI fileName = "unknown"; } - return addDownload(reply, QStringList(reply->url().toString()), fileName, fileInfo->modID, fileInfo->fileID, fileInfo); + return addDownload(reply, QStringList(reply->url().toString()), fileName, fileInfo->gameName, fileInfo->modID, fileInfo->fileID, fileInfo); } bool DownloadManager::addDownload(QNetworkReply *reply, const QStringList &URLs, const QString &fileName, - int modID, int fileID, const ModRepositoryFileInfo *fileInfo) + QString gameName, int modID, int fileID, const ModRepositoryFileInfo *fileInfo) { // download invoked from an already open network reply (i.e. download link in the browser) DownloadInfo *newDownload = DownloadInfo::createNew(fileInfo, URLs); @@ -375,7 +383,7 @@ bool DownloadManager::addDownload(QNetworkReply *reply, const QStringList &URLs, (QMessageBox::question(nullptr, tr("Download again?"), tr("A file with the same name has already been downloaded. " "Do you want to download it again? The new file will receive a different name."), QMessageBox::Yes | QMessageBox::No) == QMessageBox::No)) { - removePending(modID, fileID); + removePending(gameName, modID, fileID); delete newDownload; return false; } @@ -387,12 +395,12 @@ bool DownloadManager::addDownload(QNetworkReply *reply, const QStringList &URLs, } -void DownloadManager::removePending(int modID, int fileID) +void DownloadManager::removePending(QString gameName, int modID, int fileID) { emit aboutToUpdate(); - for (auto iter = m_PendingDownloads.begin(); iter != m_PendingDownloads.end(); ++iter) { - if ((iter->first == modID) && (iter->second == fileID)) { - m_PendingDownloads.erase(iter); + for (auto iter : m_PendingDownloads) { + if (gameName.compare(std::get<0>(iter), Qt::CaseInsensitive) == 0 && (std::get<1>(iter) == modID) && (std::get<2>(iter) == fileID)) { + m_PendingDownloads.removeAt(m_PendingDownloads.indexOf(iter)); break; } } @@ -431,7 +439,7 @@ void DownloadManager::startDownload(QNetworkReply *reply, DownloadInfo *newDownl if (!resume) { newDownload->m_PreResumeSize = newDownload->m_Output.size(); - removePending(newDownload->m_FileInfo->modID, newDownload->m_FileInfo->fileID); + removePending(newDownload->m_FileInfo->gameName, newDownload->m_FileInfo->modID, newDownload->m_FileInfo->fileID); emit aboutToUpdate(); m_ActiveDownloads.append(newDownload); @@ -451,17 +459,19 @@ void DownloadManager::addNXMDownload(const QString &url) { NXMUrl nxmInfo(url); - QString managedGame = m_ManagedGame->gameShortName(); + QStringList validGames; + validGames.append(m_ManagedGame->gameShortName()); + validGames.append(m_ManagedGame->validShortNames()); qDebug("add nxm download: %s", qPrintable(url)); - if (nxmInfo.game().compare(managedGame, Qt::CaseInsensitive) != 0) { - qDebug("download requested for wrong game (game: %s, url: %s)", qPrintable(managedGame), qPrintable(nxmInfo.game())); + if (!validGames.contains(nxmInfo.game(), Qt::CaseInsensitive)) { + qDebug("download requested for wrong game (game: %s, url: %s)", qPrintable(m_ManagedGame->gameShortName()), qPrintable(nxmInfo.game())); QMessageBox::information(nullptr, tr("Wrong Game"), tr("The download link is for a mod for \"%1\" but this instance of MO " - "has been set up for \"%2\".").arg(nxmInfo.game()).arg(managedGame), QMessageBox::Ok); + "has been set up for \"%2\".").arg(nxmInfo.game()).arg(m_ManagedGame->gameShortName()), QMessageBox::Ok); return; } - for (auto pair : m_PendingDownloads) { - if (pair.first == nxmInfo.modId() && pair.second == nxmInfo.fileId()) { + for (auto tuple : m_PendingDownloads) { + if (std::get<0>(tuple).compare(nxmInfo.game(), Qt::CaseInsensitive) == 0, std::get<1>(tuple) == nxmInfo.modId() && std::get<2>(tuple) == nxmInfo.fileId()) { qDebug("download requested is already started (mod id: %s, file id: %s)", qPrintable(QString(nxmInfo.modId())), qPrintable(QString(nxmInfo.fileId()))); QMessageBox::information(nullptr, tr("Already Started"), tr("A download for this mod file has already been queued."), QMessageBox::Ok); return; @@ -483,11 +493,11 @@ void DownloadManager::addNXMDownload(const QString &url) emit aboutToUpdate(); - m_PendingDownloads.append(std::make_pair(nxmInfo.modId(), nxmInfo.fileId())); + m_PendingDownloads.append(std::make_tuple(nxmInfo.game(), nxmInfo.modId(), nxmInfo.fileId())); emit update(-1); emit downloadAdded(); - m_RequestIDs.insert(m_NexusInterface->requestFileInfo(nxmInfo.modId(), nxmInfo.fileId(), this, nxmInfo.fileId(), "")); + m_RequestIDs.insert(m_NexusInterface->requestFileInfo(nxmInfo.game(), nxmInfo.modId(), nxmInfo.fileId(), this, nxmInfo.fileId(), "")); } @@ -743,7 +753,7 @@ int DownloadManager::numPendingDownloads() const return m_PendingDownloads.size(); } -std::pair DownloadManager::getPendingDownload(int index) +std::tuple DownloadManager::getPendingDownload(int index) { if ((index < 0) || (index >= m_PendingDownloads.size())) { throw MyException(tr("get pending: invalid download index %1").arg(index)); @@ -1003,10 +1013,10 @@ void DownloadManager::setState(DownloadManager::DownloadInfo *info, DownloadMana info->m_Reply->abort(); } break; case STATE_FETCHINGMODINFO: { - m_RequestIDs.insert(m_NexusInterface->requestDescription(info->m_FileInfo->modID, this, info->m_DownloadID, QString())); + m_RequestIDs.insert(m_NexusInterface->requestDescription(info->m_FileInfo->gameName, info->m_FileInfo->modID, this, info->m_DownloadID, QString())); } break; case STATE_FETCHINGFILEINFO: { - m_RequestIDs.insert(m_NexusInterface->requestFiles(info->m_FileInfo->modID, this, info->m_DownloadID, QString())); + m_RequestIDs.insert(m_NexusInterface->requestFiles(info->m_FileInfo->gameName, info->m_FileInfo->modID, this, info->m_DownloadID, QString())); } break; case STATE_READY: { createMetaFile(info); @@ -1080,6 +1090,7 @@ void DownloadManager::downloadReadyRead() void DownloadManager::createMetaFile(DownloadInfo *info) { QSettings metaFile(QString("%1.meta").arg(info->m_Output.fileName()), QSettings::IniFormat); + metaFile.setValue("gameName", info->m_FileInfo->gameName); metaFile.setValue("modID", info->m_FileInfo->modID); metaFile.setValue("fileID", info->m_FileInfo->fileID); metaFile.setValue("url", info->m_Urls.join(";")); @@ -1108,7 +1119,7 @@ void DownloadManager::createMetaFile(DownloadInfo *info) } -void DownloadManager::nxmDescriptionAvailable(int, QVariant userData, QVariant resultData, int requestID) +void DownloadManager::nxmDescriptionAvailable(QString, int, QVariant userData, QVariant resultData, int requestID) { std::set::iterator idIter = m_RequestIDs.find(requestID); if (idIter == m_RequestIDs.end()) { @@ -1157,7 +1168,7 @@ static EFileCategory convertFileCategory(int id) } -void DownloadManager::nxmFilesAvailable(int, QVariant userData, QVariant resultData, int requestID) +void DownloadManager::nxmFilesAvailable(QString, int, QVariant userData, QVariant resultData, int requestID) { std::set::iterator idIter = m_RequestIDs.find(requestID); if (idIter == m_RequestIDs.end()) { @@ -1237,7 +1248,7 @@ void DownloadManager::nxmFilesAvailable(int, QVariant userData, QVariant resultD } -void DownloadManager::nxmFileInfoAvailable(int modID, int fileID, QVariant userData, QVariant resultData, int requestID) +void DownloadManager::nxmFileInfoAvailable(QString gameName, int modID, int fileID, QVariant userData, QVariant resultData, int requestID) { std::set::iterator idIter = m_RequestIDs.find(requestID); if (idIter == m_RequestIDs.end()) { @@ -1260,11 +1271,12 @@ void DownloadManager::nxmFileInfoAvailable(int modID, int fileID, QVariant userD info->description = BBCode::convertToHTML(result["description"].toString()); info->repository = "Nexus"; + info->gameName = gameName; info->modID = modID; info->fileID = fileID; QObject *test = info; - m_RequestIDs.insert(m_NexusInterface->requestDownloadURL(modID, fileID, this, qVariantFromValue(test), QString())); + m_RequestIDs.insert(m_NexusInterface->requestDownloadURL(gameName, modID, fileID, this, qVariantFromValue(test), QString())); } static int evaluateFileInfoMap(const QVariantMap &map, const std::map &preferredServers) @@ -1300,7 +1312,7 @@ bool DownloadManager::ServerByPreference(const std::map &preferred int DownloadManager::startDownloadURLs(const QStringList &urls) { ModRepositoryFileInfo info; - addDownload(urls, -1, -1, &info); + addDownload(urls, "", -1, -1, &info); return m_ActiveDownloads.size() - 1; } @@ -1326,7 +1338,7 @@ int DownloadManager::indexByName(const QString &fileName) const return -1; } -void DownloadManager::nxmDownloadURLsAvailable(int modID, int fileID, QVariant userData, QVariant resultData, int requestID) +void DownloadManager::nxmDownloadURLsAvailable(QString gameName, int modID, int fileID, QVariant userData, QVariant resultData, int requestID) { std::set::iterator idIter = m_RequestIDs.find(requestID); if (idIter == m_RequestIDs.end()) { @@ -1338,7 +1350,7 @@ void DownloadManager::nxmDownloadURLsAvailable(int modID, int fileID, QVariant u ModRepositoryFileInfo *info = qobject_cast(qvariant_cast(userData)); QVariantList resultList = resultData.toList(); if (resultList.length() == 0) { - removePending(modID, fileID); + removePending(gameName, modID, fileID); emit showMessage(tr("No download server available. Please try again later.")); return; } @@ -1352,11 +1364,11 @@ void DownloadManager::nxmDownloadURLsAvailable(int modID, int fileID, QVariant u foreach (const QVariant &server, resultList) { URLs.append(server.toMap()["URI"].toString()); } - addDownload(URLs, modID, fileID, info); + addDownload(URLs, gameName, modID, fileID, info); } -void DownloadManager::nxmRequestFailed(int modID, int fileID, QVariant userData, int requestID, const QString &errorString) +void DownloadManager::nxmRequestFailed(QString gameName, int modID, int fileID, QVariant userData, int requestID, const QString &errorString) { std::set::iterator idIter = m_RequestIDs.find(requestID); if (idIter == m_RequestIDs.end()) { @@ -1381,7 +1393,7 @@ void DownloadManager::nxmRequestFailed(int modID, int fileID, QVariant userData, } } - removePending(modID, fileID); + removePending(gameName, modID, fileID); emit showMessage(tr("Failed to request file info from nexus: %1").arg(errorString)); } -- cgit v1.3.1 From 85faed5de109c0d5773626370bb6dbd338293f63 Mon Sep 17 00:00:00 2001 From: Silarn Date: Tue, 17 Apr 2018 19:14:17 -0500 Subject: Fix issues with download query --- src/downloadmanager.cpp | 20 ++++++++++++++++---- src/nexusinterface.cpp | 39 +++++++++++++++++++++++++++------------ src/nexusinterface.h | 2 ++ 3 files changed, 45 insertions(+), 16 deletions(-) (limited to 'src/downloadmanager.cpp') diff --git a/src/downloadmanager.cpp b/src/downloadmanager.cpp index d54d6f24..23a1931e 100644 --- a/src/downloadmanager.cpp +++ b/src/downloadmanager.cpp @@ -738,6 +738,20 @@ void DownloadManager::queryInfo(int index) return; } } + + if (info->m_FileInfo->gameName.size() == 0) { + SelectionDialog selection(tr("Please select the source game code for %1").arg(getFileName(index))); + + std::vector> choices = m_NexusInterface->getGameChoices(m_ManagedGame); + for (auto choice : choices) { + selection.addChoice(choice.first, choice.second, choice.first); + } + if (selection.exec() == QDialog::Accepted) { + info->m_FileInfo->gameName = selection.getChoiceData().toString(); + } else { + info->m_FileInfo->gameName = m_ManagedGame->gameShortName(); + } + } info->m_ReQueried = true; setState(info, STATE_FETCHINGMODINFO); } @@ -1204,13 +1218,11 @@ void DownloadManager::nxmFilesAvailable(QString, int, QVariant userData, QVarian if (!info->m_FileInfo->version.isValid()) { info->m_FileInfo->version = info->m_FileInfo->newestVersion; } - // we receive some names html-encoded. This is used to decode it - QTextDocument doc; - doc.setHtml(fileInfo["modName"].toString()); - info->m_FileInfo->modName = doc.toPlainText(); info->m_FileInfo->fileCategory = convertFileCategory(fileInfo["category_id"].toInt()); info->m_FileInfo->fileTime = matchDate(fileInfo["date"].toString()); info->m_FileInfo->fileID = fileInfo["id"].toInt(); + info->m_FileInfo->fileName = fileInfo["uri"].toString(); + info->m_FileInfo->description = BBCode::convertToHTML(fileInfo["description"].toString()); found = true; break; } diff --git a/src/nexusinterface.cpp b/src/nexusinterface.cpp index 434c0334..6cf5b9e9 100644 --- a/src/nexusinterface.cpp +++ b/src/nexusinterface.cpp @@ -270,6 +270,21 @@ QString NexusInterface::getModURL(int modID, QString gameName = "") const return QString("%1/mods/%2").arg(getGameURL(gameName)).arg(modID); } +std::vector> NexusInterface::getGameChoices(const MOBase::IPluginGame *game) +{ + std::vector> choices; + choices.push_back(std::pair(game->gameShortName(), game->gameName())); + for (QString gameName : game->validShortNames()) { + for (auto gamePlugin : m_PluginContainer->plugins()) { + if (gamePlugin->gameShortName().compare(gameName, Qt::CaseInsensitive) == 0) { + choices.push_back(std::pair(gamePlugin->gameShortName(), gamePlugin->gameName())); + break; + } + } + } + return choices; +} + bool NexusInterface::isModURL(int modID, const QString &url) const { if (QUrl(url) == QUrl(getModURL(modID))) { @@ -291,11 +306,11 @@ int NexusInterface::requestDescription(QString gameName, int modID, QObject *rec NXMRequestInfo requestInfo(modID, NXMRequestInfo::TYPE_DESCRIPTION, userData, subModule, game); m_RequestQueue.enqueue(requestInfo); - connect(this, SIGNAL(nxmDescriptionAvailable(QString,int,QVariant,QVariant,int)), - receiver, SLOT(nxmDescriptionAvailable(QString,int,QVariant,QVariant,int)), Qt::UniqueConnection); + connect(this, SIGNAL(nxmDescriptionAvailable(QString, int, QVariant, QVariant, int)), + receiver, SLOT(nxmDescriptionAvailable(QString, int, QVariant, QVariant, int)), Qt::UniqueConnection); - connect(this, SIGNAL(nxmRequestFailed(QString,int,int,QVariant,int,QString)), - receiver, SLOT(nxmRequestFailed(QString,int,int,QVariant,int,QString)), Qt::UniqueConnection); + connect(this, SIGNAL(nxmRequestFailed(QString, int, int, QVariant, int, QString)), + receiver, SLOT(nxmRequestFailed(QString, int, int, QVariant, int, QString)), Qt::UniqueConnection); nextRequest(); return requestInfo.m_ID; @@ -349,11 +364,11 @@ int NexusInterface::requestFiles(QString gameName, int modID, QObject *receiver, { NXMRequestInfo requestInfo(modID, NXMRequestInfo::TYPE_FILES, userData, subModule, game); m_RequestQueue.enqueue(requestInfo); - connect(this, SIGNAL(nxmFilesAvailable(QString,int,QVariant,QVariant,int)), - receiver, SLOT(nxmFilesAvailable(QString,int,QVariant,QVariant,int)), Qt::UniqueConnection); + connect(this, SIGNAL(nxmFilesAvailable(QString, int, QVariant, QVariant, int)), + receiver, SLOT(nxmFilesAvailable(QString, int, QVariant, QVariant, int)), Qt::UniqueConnection); - connect(this, SIGNAL(nxmRequestFailed(QString,int,int,QVariant,int,QString)), - receiver, SLOT(nxmRequestFailed(QString,int,int,QVariant,int,QString)), Qt::UniqueConnection); + connect(this, SIGNAL(nxmRequestFailed(QString, int, int, QVariant, int, QString)), + receiver, SLOT(nxmRequestFailed(QString, int, int, QVariant, int, QString)), Qt::UniqueConnection); nextRequest(); return requestInfo.m_ID; @@ -404,11 +419,11 @@ int NexusInterface::requestToggleEndorsement(QString gameName, int modID, bool e requestInfo.m_Endorse = endorse; m_RequestQueue.enqueue(requestInfo); - connect(this, SIGNAL(nxmEndorsementToggled(QString,int,QVariant,QVariant,int)), - receiver, SLOT(nxmEndorsementToggled(QString,int,QVariant,QVariant,int)), Qt::UniqueConnection); + connect(this, SIGNAL(nxmEndorsementToggled(QString, int, QVariant, QVariant, int)), + receiver, SLOT(nxmEndorsementToggled(QString, int, QVariant, QVariant, int)), Qt::UniqueConnection); - connect(this, SIGNAL(nxmRequestFailed(QString,int,int,QVariant,int,QString)), - receiver, SLOT(nxmRequestFailed(QString,int,int,QVariant,int,QString)), Qt::UniqueConnection); + connect(this, SIGNAL(nxmRequestFailed(QString, int, int, QVariant, int, QString)), + receiver, SLOT(nxmRequestFailed(QString, int, int, QVariant, int, QString)), Qt::UniqueConnection); nextRequest(); return requestInfo.m_ID; diff --git a/src/nexusinterface.h b/src/nexusinterface.h index 9a01c5c5..4a5ac0dd 100644 --- a/src/nexusinterface.h +++ b/src/nexusinterface.h @@ -288,6 +288,8 @@ public: */ void loginCompleted(); + std::vector> getGameChoices(const MOBase::IPluginGame *game); + public: /** -- cgit v1.3.1 From 141ac311d29f2fae6bf6ef0172708bd841e624fe Mon Sep 17 00:00:00 2001 From: Silarn Date: Sat, 21 Apr 2018 22:32:17 -0500 Subject: Don't create meta files if they don't exist --- src/downloadmanager.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'src/downloadmanager.cpp') diff --git a/src/downloadmanager.cpp b/src/downloadmanager.cpp index 23a1931e..3d88e803 100644 --- a/src/downloadmanager.cpp +++ b/src/downloadmanager.cpp @@ -79,6 +79,7 @@ DownloadManager::DownloadInfo *DownloadManager::DownloadInfo::createFromMeta(con DownloadInfo *info = new DownloadInfo; QString metaFileName = filePath + ".meta"; + if (!QFile(metaFileName).exists()) return nullptr; QSettings metaFile(metaFileName, QSettings::IniFormat); if (!showHidden && metaFile.value("removed", false).toBool()) { return nullptr; @@ -937,8 +938,8 @@ void DownloadManager::markInstalled(QString fileName) QSettings metaFile(info->m_Output.fileName() + ".meta", QSettings::IniFormat); metaFile.setValue("installed", true); metaFile.setValue("uninstalled", false); + delete info; } - delete info; } } @@ -972,8 +973,8 @@ void DownloadManager::markUninstalled(QString fileName) if (info != nullptr) { QSettings metaFile(info->m_Output.fileName() + ".meta", QSettings::IniFormat); metaFile.setValue("uninstalled", true); + delete info; } - delete info; } } -- cgit v1.3.1 From 31bf15f3b43e52a9e9090b8e71191c81be084ba6 Mon Sep 17 00:00:00 2001 From: Silarn Date: Mon, 23 Apr 2018 22:12:46 -0700 Subject: Need to check if the file is in the download directory for creating meta --- src/downloadmanager.cpp | 9 +++++---- src/downloadmanager.h | 2 +- 2 files changed, 6 insertions(+), 5 deletions(-) (limited to 'src/downloadmanager.cpp') diff --git a/src/downloadmanager.cpp b/src/downloadmanager.cpp index 3d88e803..aec2ad85 100644 --- a/src/downloadmanager.cpp +++ b/src/downloadmanager.cpp @@ -74,12 +74,13 @@ DownloadManager::DownloadInfo *DownloadManager::DownloadInfo::createNew(const Mo return info; } -DownloadManager::DownloadInfo *DownloadManager::DownloadInfo::createFromMeta(const QString &filePath, bool showHidden) +DownloadManager::DownloadInfo *DownloadManager::DownloadInfo::createFromMeta(const QString &filePath, bool showHidden, const QString outputDirectory) { DownloadInfo *info = new DownloadInfo; QString metaFileName = filePath + ".meta"; - if (!QFile(metaFileName).exists()) return nullptr; + QFileInfo metaFileInfo(metaFileName); + if (QDir::fromNativeSeparators(metaFileInfo.path()).compare(QDir::fromNativeSeparators(outputDirectory), Qt::CaseInsensitive) != 0) return nullptr; QSettings metaFile(metaFileName, QSettings::IniFormat); if (!showHidden && metaFile.value("removed", false).toBool()) { return nullptr; @@ -322,7 +323,7 @@ void DownloadManager::refreshList() QString fileName = QDir::fromNativeSeparators(m_OutputDirectory) + "/" + file; - DownloadInfo *info = DownloadInfo::createFromMeta(fileName, m_ShowHidden); + DownloadInfo *info = DownloadInfo::createFromMeta(fileName, m_ShowHidden, m_OutputDirectory); if (info != nullptr) { m_ActiveDownloads.push_front(info); } @@ -945,7 +946,7 @@ void DownloadManager::markInstalled(QString fileName) DownloadManager::DownloadInfo* DownloadManager::getDownloadInfo(QString fileName) { - return DownloadInfo::createFromMeta(fileName, true); + return DownloadInfo::createFromMeta(fileName, true, m_OutputDirectory); } void DownloadManager::markUninstalled(int index) diff --git a/src/downloadmanager.h b/src/downloadmanager.h index 780aeb5c..308d365b 100644 --- a/src/downloadmanager.h +++ b/src/downloadmanager.h @@ -93,7 +93,7 @@ private: bool m_Hidden; static DownloadInfo *createNew(const MOBase::ModRepositoryFileInfo *fileInfo, const QStringList &URLs); - static DownloadInfo *createFromMeta(const QString &filePath, bool showHidden); + static DownloadInfo *createFromMeta(const QString &filePath, bool showHidden, const QString outputDirectory); /** * @brief rename the file -- cgit v1.3.1 From 275afb730fa762f09836f3b38b2e25ff0128faa0 Mon Sep 17 00:00:00 2001 From: Silarn Date: Mon, 30 Apr 2018 13:56:27 -0500 Subject: A couple download header-based fixes * If an unknown content error, only fail if the filesize is off * If a text content type, output a warning but do not retry the download --- src/downloadmanager.cpp | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) (limited to 'src/downloadmanager.cpp') diff --git a/src/downloadmanager.cpp b/src/downloadmanager.cpp index aec2ad85..77a4cf98 100644 --- a/src/downloadmanager.cpp +++ b/src/downloadmanager.cpp @@ -1431,15 +1431,16 @@ void DownloadManager::downloadFinished() if ((info->m_State != STATE_CANCELING) && (info->m_State != STATE_PAUSING)) { bool textData = reply->header(QNetworkRequest::ContentTypeHeader).toString().startsWith("text", Qt::CaseInsensitive); + if (textData) + emit showMessage(tr("Warning: Content type is: %1").arg(reply->header(QNetworkRequest::ContentTypeHeader).toString())); if ((info->m_Output.size() == 0) || - ((reply->error() != QNetworkReply::NoError) && (reply->error() != QNetworkReply::OperationCanceledError)) || - textData) { + ((reply->error() != QNetworkReply::NoError) + && (reply->error() != QNetworkReply::OperationCanceledError) + && (reply->error() == QNetworkReply::UnknownContentError && (info->m_Output.size() != reply->header(QNetworkRequest::ContentLengthHeader).toLongLong())))) { + if (reply->error() == QNetworkReply::UnknownContentError) + emit showMessage(tr("Download header content length: %1 downloaded file size: %2").arg(reply->header(QNetworkRequest::ContentLengthHeader).toLongLong()).arg(info->m_Output.size())); if (info->m_Tries == 0) { - if (textData && (reply->error() == QNetworkReply::NoError)) { - emit showMessage(tr("Download failed. Server reported: %1").arg(QString(data))); - } else { - emit showMessage(tr("Download failed: %1 (%2)").arg(reply->errorString()).arg(reply->error())); - } + emit showMessage(tr("Download failed: %1 (%2)").arg(reply->errorString()).arg(reply->error())); } error = true; setState(info, STATE_PAUSING); -- cgit v1.3.1 From d62ec9c867b448276ab9873ddd3f320487ab5572 Mon Sep 17 00:00:00 2001 From: Silarn Date: Tue, 1 May 2018 21:50:20 -0500 Subject: Allow downloads to display speed and complete % --- src/downloadlistwidget.cpp | 4 +++- src/downloadlistwidgetcompact.cpp | 3 ++- src/downloadmanager.cpp | 30 +++++++++++++++++++++++------- src/downloadmanager.h | 4 ++-- 4 files changed, 30 insertions(+), 11 deletions(-) (limited to 'src/downloadmanager.cpp') diff --git a/src/downloadlistwidget.cpp b/src/downloadlistwidget.cpp index cb7a49c3..2af74cc2 100644 --- a/src/downloadlistwidget.cpp +++ b/src/downloadlistwidget.cpp @@ -53,6 +53,7 @@ DownloadListWidgetDelegate::DownloadListWidgetDelegate(DownloadManager *manager, m_InstallLabel = m_ItemWidget->findChild("installLabel"); m_InstallLabel->setVisible(false); + m_Progress->setTextVisible(true); connect(manager, SIGNAL(stateChanged(int,DownloadManager::DownloadState)), this, SLOT(stateChanged(int,DownloadManager::DownloadState))); connect(manager, SIGNAL(downloadRemoved(int)), this, SLOT(resetCache(int))); @@ -159,7 +160,8 @@ void DownloadListWidgetDelegate::paintRegularDownload(int downloadIndex) const } else { m_InstallLabel->setVisible(false); m_Progress->setVisible(true); - m_Progress->setValue(m_Manager->getProgress(downloadIndex)); + m_Progress->setValue(m_Manager->getProgress(downloadIndex).first); + m_Progress->setFormat(m_Manager->getProgress(downloadIndex).second); } } diff --git a/src/downloadlistwidgetcompact.cpp b/src/downloadlistwidgetcompact.cpp index b390bff4..898d400a 100644 --- a/src/downloadlistwidgetcompact.cpp +++ b/src/downloadlistwidgetcompact.cpp @@ -138,7 +138,8 @@ void DownloadListWidgetCompactDelegate::paintRegularDownload(int downloadIndex) } else { m_DoneLabel->setVisible(false); m_Progress->setVisible(true); - m_Progress->setValue(m_Manager->getProgress(downloadIndex)); + m_Progress->setValue(m_Manager->getProgress(downloadIndex).first); + m_Progress->setFormat(m_Manager->getProgress(downloadIndex).second); } } diff --git a/src/downloadmanager.cpp b/src/downloadmanager.cpp index 77a4cf98..097a1168 100644 --- a/src/downloadmanager.cpp +++ b/src/downloadmanager.cpp @@ -62,7 +62,7 @@ DownloadManager::DownloadInfo *DownloadManager::DownloadInfo::createNew(const Mo info->m_DownloadID = s_NextDownloadID++; info->m_StartTime.start(); info->m_PreResumeSize = 0LL; - info->m_Progress = 0; + info->m_Progress = std::make_pair(0, "0 bytes/sec"); info->m_ResumePos = 0; info->m_FileInfo = new ModRepositoryFileInfo(*fileInfo); info->m_Urls = URLs; @@ -852,7 +852,7 @@ qint64 DownloadManager::getFileSize(int index) const } -int DownloadManager::getProgress(int index) const +std::pair DownloadManager::getProgress(int index) const { if ((index < 0) || (index >= m_ActiveDownloads.size())) { throw MyException(tr("progress: invalid download index %1").arg(index)); @@ -1076,12 +1076,28 @@ void DownloadManager::downloadProgress(qint64 bytesReceived, qint64 bytesTotal) if (bytesTotal > info->m_TotalSize) { info->m_TotalSize = bytesTotal; } - int oldProgress = info->m_Progress; - info->m_Progress = ((info->m_ResumePos + bytesReceived) * 100) / (info->m_ResumePos + bytesTotal); - TaskProgressManager::instance().updateProgress(info->m_TaskProgressId, bytesReceived, bytesTotal); - if (oldProgress != info->m_Progress) { - emit update(index); + int oldProgress = info->m_Progress.first; + info->m_Progress.first = ((info->m_ResumePos + bytesReceived) * 100) / (info->m_ResumePos + bytesTotal); + + // calculate the download speed + double speed = bytesReceived * 1000.0 / info->m_StartTime.elapsed(); + 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"; } + + info->m_Progress.second = QString::fromLatin1("%1% - %2 %3").arg(info->m_Progress.first).arg(speed, 3, 'f', 1).arg(unit); + + TaskProgressManager::instance().updateProgress(info->m_TaskProgressId, bytesReceived, bytesTotal); + emit update(index); } } } catch (const std::bad_alloc&) { diff --git a/src/downloadmanager.h b/src/downloadmanager.h index 308d365b..0ff77011 100644 --- a/src/downloadmanager.h +++ b/src/downloadmanager.h @@ -75,7 +75,7 @@ private: QNetworkReply *m_Reply; QTime m_StartTime; qint64 m_PreResumeSize; - int m_Progress; + std::pair m_Progress; DownloadState m_State; int m_CurrentUrl; QStringList m_Urls; @@ -259,7 +259,7 @@ public: * @param index index of the file to look up * @return progress of the download in percent (integer) **/ - int getProgress(int index) const; + std::pair getProgress(int index) const; /** * @brief retrieve the current state of the download -- cgit v1.3.1 From 168da18aa51868ad3ac908affb55a8aabdba1aed Mon Sep 17 00:00:00 2001 From: Silarn Date: Wed, 2 May 2018 12:38:23 -0500 Subject: Fix MO endorsement check and add game to ModInfo s_ModsByModID --- src/downloadmanager.cpp | 8 ++++++++ src/downloadmanager.h | 8 ++++++++ src/mainwindow.cpp | 12 ++++++++++-- src/modinfo.cpp | 14 ++++++++------ src/modinfo.h | 4 ++-- src/organizercore.cpp | 3 ++- 6 files changed, 38 insertions(+), 11 deletions(-) (limited to 'src/downloadmanager.cpp') diff --git a/src/downloadmanager.cpp b/src/downloadmanager.cpp index 097a1168..d9e86544 100644 --- a/src/downloadmanager.cpp +++ b/src/downloadmanager.cpp @@ -895,6 +895,14 @@ int DownloadManager::getModID(int index) const return m_ActiveDownloads.at(index)->m_FileInfo->modID; } +QString DownloadManager::getGameName(int index) const +{ + if ((index < 0) || (index >= m_ActiveDownloads.size())) { + throw MyException(tr("mod id: invalid download index %1").arg(index)); + } + return m_ActiveDownloads.at(index)->m_FileInfo->gameName; +} + bool DownloadManager::isHidden(int index) const { if ((index < 0) || (index >= m_ActiveDownloads.size())) { diff --git a/src/downloadmanager.h b/src/downloadmanager.h index 0ff77011..e1925040 100644 --- a/src/downloadmanager.h +++ b/src/downloadmanager.h @@ -288,6 +288,14 @@ public: **/ int getModID(int index) const; + /** + * @brief retrieve the game name of the downlaod specified by the index + * + * @param index index of the file to look up + * @return the game name + **/ + QString getGameName(int index) const; + /** * @brief determine if the specified file is supposed to be hidden * @param index index of the file to look up diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp index 3933987e..a95b7b70 100644 --- a/src/mainwindow.cpp +++ b/src/mainwindow.cpp @@ -4231,12 +4231,20 @@ void MainWindow::nxmUpdatesAvailable(const std::vector &modIDs, QVariant us QVariantList resultList = resultData.toList(); for (auto iter = resultList.begin(); iter != resultList.end(); ++iter) { QVariantMap result = iter->toMap(); - if (result["id"].toInt() == m_OrganizerCore.managedGame()->nexusModOrganizerID()) { + if (result["id"].toInt() == m_OrganizerCore.managedGame()->nexusModOrganizerID() + && result["game_id"].toInt() == m_OrganizerCore.managedGame()->nexusGameID()) { if (!result["voted_by_user"].toBool()) { ui->actionEndorseMO->setVisible(true); } } else { - std::vector info = ModInfo::getByModID(result["id"].toInt()); + QString gameName = m_OrganizerCore.managedGame()->gameShortName(); + for (IPluginGame *game : m_PluginContainer.plugins()) { + if (game->nexusGameID() == result["game_id"].toInt()) { + gameName = game->gameShortName(); + break; + } + } + std::vector info = ModInfo::getByModID(gameName, result["id"].toInt()); for (auto iter = info.begin(); iter != info.end(); ++iter) { (*iter)->setNewestVersion(result["version"].toString()); (*iter)->setNexusDescription(result["description"].toString()); diff --git a/src/modinfo.cpp b/src/modinfo.cpp index d916d982..6b3fd528 100644 --- a/src/modinfo.cpp +++ b/src/modinfo.cpp @@ -48,7 +48,7 @@ using namespace MOShared; std::vector ModInfo::s_Collection; std::map ModInfo::s_ModsByName; -std::map > ModInfo::s_ModsByModID; +std::map, std::vector> ModInfo::s_ModsByModID; int ModInfo::s_NextID; QMutex ModInfo::s_Mutex(QMutex::Recursive); @@ -132,11 +132,11 @@ ModInfo::Ptr ModInfo::getByIndex(unsigned int index) } -std::vector ModInfo::getByModID(int modID) +std::vector ModInfo::getByModID(QString game, int modID) { QMutexLocker locker(&s_Mutex); - auto iter = s_ModsByModID.find(modID); + auto iter = s_ModsByModID.find(std::pair(game, modID)); if (iter == s_ModsByModID.end()) { return std::vector(); } @@ -161,11 +161,11 @@ bool ModInfo::removeMod(unsigned int index) ModInfo::Ptr modInfo = s_Collection[index]; s_ModsByName.erase(s_ModsByName.find(modInfo->name())); - auto iter = s_ModsByModID.find(modInfo->getNexusID()); + auto iter = s_ModsByModID.find(std::pair(modInfo->getGameName(), modInfo->getNexusID())); if (iter != s_ModsByModID.end()) { std::vector indices = iter->second; indices.erase(std::remove(indices.begin(), indices.end(), index), indices.end()); - s_ModsByModID[modInfo->getNexusID()] = indices; + s_ModsByModID[std::pair(modInfo->getGameName(), modInfo->getNexusID())] = indices; } // physically remove the mod directory @@ -255,9 +255,10 @@ void ModInfo::updateIndices() for (unsigned int i = 0; i < s_Collection.size(); ++i) { QString modName = s_Collection[i]->internalName(); + QString game = s_Collection[i]->getGameName(); int modID = s_Collection[i]->getNexusID(); s_ModsByName[modName] = i; - s_ModsByModID[modID].push_back(i); + s_ModsByModID[std::pair(game, modID)].push_back(i); } } @@ -289,6 +290,7 @@ int ModInfo::checkAllForUpdate(PluginContainer *pluginContainer, QObject *receiv IPluginGame const *game = qApp->property("managed_game").value(); modIDs.push_back(game->nexusModOrganizerID()); checkChunkForUpdate(pluginContainer, modIDs, receiver, game->gameShortName()); + modIDs.clear(); std::multimap> organizedGames; for (auto mod : s_Collection) { diff --git a/src/modinfo.h b/src/modinfo.h index 19be2ca2..7bb2bdad 100644 --- a/src/modinfo.h +++ b/src/modinfo.h @@ -148,7 +148,7 @@ public: * @todo in its current form, this function is broken! There may be multiple mods with the same nexus id, * this function will return only one of them **/ - static std::vector getByModID(int modID); + static std::vector getByModID(QString game, int modID); /** * @brief remove a mod by index @@ -638,7 +638,7 @@ protected: private: static QMutex s_Mutex; - static std::map > s_ModsByModID; + static std::map, std::vector > s_ModsByModID; static int s_NextID; bool m_Valid; diff --git a/src/organizercore.cpp b/src/organizercore.cpp index 69c28c5c..4739021a 100644 --- a/src/organizercore.cpp +++ b/src/organizercore.cpp @@ -919,13 +919,14 @@ void OrganizerCore::installDownload(int index) { try { QString fileName = m_DownloadManager.getFilePath(index); + QString gameName = m_DownloadManager.getGameName(index); int modID = m_DownloadManager.getModID(index); int fileID = m_DownloadManager.getFileInfo(index)->fileID; GuessedValue modName; // see if there already are mods with the specified mod id if (modID != 0) { - std::vector modInfo = ModInfo::getByModID(modID); + std::vector modInfo = ModInfo::getByModID(gameName, modID); for (auto iter = modInfo.begin(); iter != modInfo.end(); ++iter) { std::vector flags = (*iter)->getFlags(); if (std::find(flags.begin(), flags.end(), ModInfo::FLAG_BACKUP) -- cgit v1.3.1 From cc32c8c06bc20dbd0905e48ffd8c6d027184ad06 Mon Sep 17 00:00:00 2001 From: Silarn Date: Thu, 3 May 2018 17:14:05 -0500 Subject: Use a five second delta to calculate speed for more responsive display --- src/downloadmanager.cpp | 18 ++++++++++++++++-- src/downloadmanager.h | 3 ++- 2 files changed, 18 insertions(+), 3 deletions(-) (limited to 'src/downloadmanager.cpp') diff --git a/src/downloadmanager.cpp b/src/downloadmanager.cpp index d9e86544..a60057ef 100644 --- a/src/downloadmanager.cpp +++ b/src/downloadmanager.cpp @@ -686,6 +686,9 @@ void DownloadManager::resumeDownloadInt(int index) qDebug("request resume from url %s", qPrintable(info->currentURL())); QNetworkRequest request(QUrl::fromEncoded(info->currentURL().toLocal8Bit())); info->m_ResumePos = info->m_Output.size(); + std::get<0>(info->m_SpeedDiff) = 0; + std::get<1>(info->m_SpeedDiff) = 0; + std::get<2>(info->m_SpeedDiff) = 0; qDebug("resume at %lld bytes", info->m_ResumePos); QByteArray rangeHeader = "bytes=" + QByteArray::number(info->m_ResumePos) + "-"; request.setRawHeader("Range", rangeHeader); @@ -1080,7 +1083,8 @@ void DownloadManager::downloadProgress(qint64 bytesReceived, qint64 bytesTotal) setState(info, STATE_CANCELED); } else if (info->m_State == STATE_PAUSING) { setState(info, STATE_PAUSED); - } else { + } + else { if (bytesTotal > info->m_TotalSize) { info->m_TotalSize = bytesTotal; } @@ -1088,7 +1092,11 @@ void DownloadManager::downloadProgress(qint64 bytesReceived, qint64 bytesTotal) info->m_Progress.first = ((info->m_ResumePos + bytesReceived) * 100) / (info->m_ResumePos + bytesTotal); // calculate the download speed - double speed = bytesReceived * 1000.0 / info->m_StartTime.elapsed(); + double speed = (bytesReceived - std::get<1>(info->m_SpeedDiff)) * 1000.0 / // Calculate with the data transferred in the last 5 seconds... + (std::get<1>(info->m_SpeedDiff) ? // If we are past 5 seconds + (5 * 1000) + (info->m_StartTime.elapsed() - std::get<2>(info->m_SpeedDiff)) : // Divide by 5 seconds + the diff between chunks + info->m_StartTime.elapsed()); // Else just use the current elapsed time + QString unit; if (speed < 1024) { unit = "bytes/sec"; @@ -1104,6 +1112,12 @@ void DownloadManager::downloadProgress(qint64 bytesReceived, qint64 bytesTotal) info->m_Progress.second = QString::fromLatin1("%1% - %2 %3").arg(info->m_Progress.first).arg(speed, 3, 'f', 1).arg(unit); + if (info->m_StartTime.elapsed() >= 5 * 1000) { + std::get<1>(info->m_SpeedDiff) = std::get<1>(info->m_SpeedDiff) + bytesReceived - std::get<0>(info->m_SpeedDiff); + std::get<2>(info->m_SpeedDiff) = info->m_StartTime.elapsed(); + } + std::get<0>(info->m_SpeedDiff) = bytesReceived; + TaskProgressManager::instance().updateProgress(info->m_TaskProgressId, bytesReceived, bytesTotal); emit update(index); } diff --git a/src/downloadmanager.h b/src/downloadmanager.h index e1925040..6a110a41 100644 --- a/src/downloadmanager.h +++ b/src/downloadmanager.h @@ -76,6 +76,7 @@ private: QTime m_StartTime; qint64 m_PreResumeSize; std::pair m_Progress; + std::tuple m_SpeedDiff; DownloadState m_State; int m_CurrentUrl; QStringList m_Urls; @@ -113,7 +114,7 @@ private: private: static unsigned int s_NextDownloadID; private: - DownloadInfo() : m_TotalSize(0), m_ReQueried(false), m_Hidden(false) {} + DownloadInfo() : m_TotalSize(0), m_ReQueried(false), m_Hidden(false), m_SpeedDiff(std::tuple(0,0,0)) {} }; public: -- cgit v1.3.1 From fe33d7af43465f0ee46eab8353bb4f3d4b145331 Mon Sep 17 00:00:00 2001 From: Silarn Date: Sat, 5 May 2018 01:28:09 -0500 Subject: Rework the existing file download dialog to pause the download while waiting - Also fixes direct calls to downloadFinished --- src/downloadmanager.cpp | 51 ++++++++++++++++++++++++++++++++----------------- src/downloadmanager.h | 4 ++-- 2 files changed, 36 insertions(+), 19 deletions(-) (limited to 'src/downloadmanager.cpp') diff --git a/src/downloadmanager.cpp b/src/downloadmanager.cpp index a60057ef..0da5ced3 100644 --- a/src/downloadmanager.cpp +++ b/src/downloadmanager.cpp @@ -381,14 +381,6 @@ bool DownloadManager::addDownload(QNetworkReply *reply, const QStringList &URLs, baseName = dispoName; } } - if (QFile::exists(m_OutputDirectory + "/" + baseName) && - (QMessageBox::question(nullptr, tr("Download again?"), tr("A file with the same name has already been downloaded. " - "Do you want to download it again? The new file will receive a different name."), - QMessageBox::Yes | QMessageBox::No) == QMessageBox::No)) { - removePending(gameName, modID, fileID); - delete newDownload; - return false; - } newDownload->setName(getDownloadFileName(baseName), false); startDownload(reply, newDownload, false); @@ -434,7 +426,6 @@ void DownloadManager::startDownload(QNetworkReply *reply, DownloadInfo *newDownl } connect(newDownload->m_Reply, SIGNAL(downloadProgress(qint64, qint64)), this, SLOT(downloadProgress(qint64, qint64))); - connect(newDownload->m_Reply, SIGNAL(finished()), this, SLOT(downloadFinished())); connect(newDownload->m_Reply, SIGNAL(error(QNetworkReply::NetworkError)), this, SLOT(downloadError(QNetworkReply::NetworkError))); connect(newDownload->m_Reply, SIGNAL(readyRead()), this, SLOT(downloadReadyRead())); connect(newDownload->m_Reply, SIGNAL(metaDataChanged()), this, SLOT(metaDataChanged())); @@ -449,11 +440,33 @@ void DownloadManager::startDownload(QNetworkReply *reply, DownloadInfo *newDownl emit update(-1); emit downloadAdded(); - if (reply->isFinished()) { - // it's possible the download has already finished before this function ran - downloadFinished(); + if (QFile::exists(m_OutputDirectory + "/" + newDownload->m_FileName)) { + setState(newDownload, STATE_PAUSING); + QCoreApplication::processEvents(); + if (QMessageBox::question(nullptr, tr("Download again?"), tr("A file with the same name has already been downloaded. " + "Do you want to download it again? The new file will receive a different name."), + QMessageBox::Yes | QMessageBox::No) == QMessageBox::No) { + if (reply->isFinished()) + setState(newDownload, STATE_CANCELED); + else + setState(newDownload, STATE_CANCELING); + } else { + newDownload->setName(getDownloadFileName(newDownload->m_FileName, true), true); + if (newDownload->m_State == STATE_PAUSED) + resumeDownload(indexByName(newDownload->m_FileName)); + else + setState(newDownload, STATE_DOWNLOADING); + } + } + + QCoreApplication::processEvents(); + + if (newDownload->m_State != STATE_DOWNLOADING && reply->isFinished()) { + downloadFinished(indexByName(newDownload->m_FileName)); + return; } } + connect(newDownload->m_Reply, SIGNAL(finished()), this, SLOT(downloadFinished())); } @@ -991,10 +1004,10 @@ void DownloadManager::markUninstalled(QString fileName) } -QString DownloadManager::getDownloadFileName(const QString &baseName) const +QString DownloadManager::getDownloadFileName(const QString &baseName, bool rename) const { QString fullPath = m_OutputDirectory + "/" + baseName; - if (QFile::exists(fullPath)) { + if (QFile::exists(fullPath) && rename) { int i = 1; while (QFile::exists(QString("%1/%2_%3").arg(m_OutputDirectory).arg(i).arg(baseName))) { ++i; @@ -1035,6 +1048,7 @@ void DownloadManager::setState(DownloadManager::DownloadInfo *info, DownloadMana case STATE_PAUSED: case STATE_ERROR: { info->m_Reply->abort(); + info->m_Output.close(); } break; case STATE_CANCELED: { info->m_Reply->abort(); @@ -1450,11 +1464,14 @@ void DownloadManager::nxmRequestFailed(QString gameName, int modID, int fileID, } -void DownloadManager::downloadFinished() +void DownloadManager::downloadFinished(int index) { - int index = 0; + DownloadInfo *info; + if (index) + info = m_ActiveDownloads[index]; + else + info = findDownload(this->sender(), &index); - DownloadInfo *info = findDownload(this->sender(), &index); if (info != nullptr) { QNetworkReply *reply = info->m_Reply; QByteArray data; diff --git a/src/downloadmanager.h b/src/downloadmanager.h index 6a110a41..6e3f9c2c 100644 --- a/src/downloadmanager.h +++ b/src/downloadmanager.h @@ -439,7 +439,7 @@ private slots: void downloadProgress(qint64 bytesReceived, qint64 bytesTotal); void downloadReadyRead(); - void downloadFinished(); + void downloadFinished(int index = 0); void downloadError(QNetworkReply::NetworkError error); void metaDataChanged(); void directoryChanged(const QString &dirctory); @@ -460,7 +460,7 @@ public: * * @return Unique(ish) name */ - QString getDownloadFileName(const QString &baseName) const; + QString getDownloadFileName(const QString &baseName, bool rename = false) const; private: -- cgit v1.3.1 From 6359d7d23f4137a35dfd241a0daa22c6a885e426 Mon Sep 17 00:00:00 2001 From: Silarn Date: Sun, 6 May 2018 17:21:35 -0500 Subject: Fixes for downloads and installs --- src/downloadmanager.cpp | 49 +++++++++++++++++++++++++-------------------- src/downloadmanager.h | 4 ++-- src/installationmanager.cpp | 43 +++++++++++++++++---------------------- src/installationmanager.h | 7 ++----- 4 files changed, 49 insertions(+), 54 deletions(-) (limited to 'src/downloadmanager.cpp') diff --git a/src/downloadmanager.cpp b/src/downloadmanager.cpp index 0da5ced3..2ab56fab 100644 --- a/src/downloadmanager.cpp +++ b/src/downloadmanager.cpp @@ -145,8 +145,10 @@ void DownloadManager::DownloadInfo::setName(QString newName, bool renameFile) QString oldMetaFileName = QString("%1.meta").arg(m_FileName); m_FileName = QFileInfo(newName).fileName(); if ((m_State == DownloadManager::STATE_STARTED) || - (m_State == DownloadManager::STATE_DOWNLOADING)) { + (m_State == DownloadManager::STATE_DOWNLOADING) || + (m_State == DownloadManager::STATE_PAUSED)) { newName.append(UNFINISHED); + oldMetaFileName = QString("%1%2.meta").arg(m_FileName).arg(UNFINISHED); } if (renameFile) { if ((newName != m_Output.fileName()) && !m_Output.rename(newName)) { @@ -154,10 +156,9 @@ void DownloadManager::DownloadInfo::setName(QString newName, bool renameFile) return; } - QFile metaFile(oldMetaFileName); - if (metaFile.exists()) { + QFile metaFile(QFileInfo(newName).path() + "/" + oldMetaFileName); + if (metaFile.exists()) metaFile.rename(newName.mid(0).append(".meta")); - } } if (!m_Output.isOpen()) { // can't set file name if it's open @@ -457,7 +458,9 @@ void DownloadManager::startDownload(QNetworkReply *reply, DownloadInfo *newDownl else setState(newDownload, STATE_DOWNLOADING); } - } + } else + connect(newDownload->m_Reply, SIGNAL(finished()), this, SLOT(downloadFinished())); + QCoreApplication::processEvents(); @@ -465,8 +468,8 @@ void DownloadManager::startDownload(QNetworkReply *reply, DownloadInfo *newDownl downloadFinished(indexByName(newDownload->m_FileName)); return; } - } - connect(newDownload->m_Reply, SIGNAL(finished()), this, SLOT(downloadFinished())); + } else + connect(newDownload->m_Reply, SIGNAL(finished()), this, SLOT(downloadFinished())); } @@ -496,11 +499,11 @@ void DownloadManager::addNXMDownload(const QString &url) for (DownloadInfo *download : m_ActiveDownloads) { if (download->m_FileInfo->modID == nxmInfo.modId() && download->m_FileInfo->fileID == nxmInfo.fileId()) { if (download->m_State == STATE_DOWNLOADING || download->m_State == STATE_PAUSED || download->m_State == STATE_STARTED) { - qDebug("download requested is already started (mod: %s, file: %s)", qPrintable(download->m_FileInfo->modName), + qDebug("download requested is already started (mod: %s, file: %s)", qPrintable(download->m_FileInfo->modID), qPrintable(download->m_FileInfo->fileName)); - QMessageBox::information(nullptr, tr("Already Started"), tr("There is already a download started for this file (%2).") - .arg(download->m_FileInfo->modName).arg(download->m_FileInfo->name), QMessageBox::Ok); + QMessageBox::information(nullptr, tr("Already Started"), tr("There is already a download started for this file (mod: %1, file: %2).") + .arg(download->m_FileInfo->modName).arg(download->m_FileInfo->fileName), QMessageBox::Ok); return; } } @@ -702,6 +705,8 @@ void DownloadManager::resumeDownloadInt(int index) std::get<0>(info->m_SpeedDiff) = 0; std::get<1>(info->m_SpeedDiff) = 0; std::get<2>(info->m_SpeedDiff) = 0; + std::get<3>(info->m_SpeedDiff) = 0; + std::get<4>(info->m_SpeedDiff) = 0; qDebug("resume at %lld bytes", info->m_ResumePos); QByteArray rangeHeader = "bytes=" + QByteArray::number(info->m_ResumePos) + "-"; request.setRawHeader("Range", rangeHeader); @@ -1105,11 +1110,17 @@ void DownloadManager::downloadProgress(qint64 bytesReceived, qint64 bytesTotal) int oldProgress = info->m_Progress.first; info->m_Progress.first = ((info->m_ResumePos + bytesReceived) * 100) / (info->m_ResumePos + bytesTotal); + int elapsed = info->m_StartTime.elapsed(); + std::get<0>(info->m_SpeedDiff) = bytesReceived - std::get<2>(info->m_SpeedDiff); + std::get<1>(info->m_SpeedDiff) = elapsed - std::get<3>(info->m_SpeedDiff); + std::get<2>(info->m_SpeedDiff) = bytesReceived; + std::get<3>(info->m_SpeedDiff) = elapsed; + + double calc = ((double)std::get<0>(info->m_SpeedDiff)) / (((double)(std::get<1>(info->m_SpeedDiff)) / 5000.0)); + std::get<4>(info->m_SpeedDiff) = ((calc*0.5) + (std::get<4>(info->m_SpeedDiff)*1.5)) / 2; + // calculate the download speed - double speed = (bytesReceived - std::get<1>(info->m_SpeedDiff)) * 1000.0 / // Calculate with the data transferred in the last 5 seconds... - (std::get<1>(info->m_SpeedDiff) ? // If we are past 5 seconds - (5 * 1000) + (info->m_StartTime.elapsed() - std::get<2>(info->m_SpeedDiff)) : // Divide by 5 seconds + the diff between chunks - info->m_StartTime.elapsed()); // Else just use the current elapsed time + double speed = (std::get<4>(info->m_SpeedDiff) * 1000.0) / (5 * 1000); QString unit; if (speed < 1024) { @@ -1126,12 +1137,6 @@ void DownloadManager::downloadProgress(qint64 bytesReceived, qint64 bytesTotal) info->m_Progress.second = QString::fromLatin1("%1% - %2 %3").arg(info->m_Progress.first).arg(speed, 3, 'f', 1).arg(unit); - if (info->m_StartTime.elapsed() >= 5 * 1000) { - std::get<1>(info->m_SpeedDiff) = std::get<1>(info->m_SpeedDiff) + bytesReceived - std::get<0>(info->m_SpeedDiff); - std::get<2>(info->m_SpeedDiff) = info->m_StartTime.elapsed(); - } - std::get<0>(info->m_SpeedDiff) = bytesReceived; - TaskProgressManager::instance().updateProgress(info->m_TaskProgressId, bytesReceived, bytesTotal); emit update(index); } @@ -1551,7 +1556,7 @@ void DownloadManager::downloadFinished(int index) QString newName = getFileNameFromNetworkReply(reply); QString oldName = QFileInfo(info->m_Output).fileName(); - if (!newName.isEmpty() && (newName != oldName)) { + if (!newName.isEmpty() && (oldName.isEmpty())) { info->setName(getDownloadFileName(newName), true); } else { info->setName(m_OutputDirectory + "/" + info->m_FileName, true); // don't rename but remove the ".unfinished" extension @@ -1594,7 +1599,7 @@ void DownloadManager::metaDataChanged() DownloadInfo *info = findDownload(this->sender(), &index); if (info != nullptr) { QString newName = getFileNameFromNetworkReply(info->m_Reply); - if (!newName.isEmpty() && (newName != info->m_FileName)) { + if (!newName.isEmpty() && (info->m_FileName.isEmpty())) { info->setName(getDownloadFileName(newName), true); refreshAlphabeticalTranslation(); if (!info->m_Output.isOpen() && !info->m_Output.open(QIODevice::WriteOnly | QIODevice::Append)) { diff --git a/src/downloadmanager.h b/src/downloadmanager.h index 6e3f9c2c..98f5e468 100644 --- a/src/downloadmanager.h +++ b/src/downloadmanager.h @@ -76,7 +76,7 @@ private: QTime m_StartTime; qint64 m_PreResumeSize; std::pair m_Progress; - std::tuple m_SpeedDiff; + std::tuple m_SpeedDiff; DownloadState m_State; int m_CurrentUrl; QStringList m_Urls; @@ -114,7 +114,7 @@ private: private: static unsigned int s_NextDownloadID; private: - DownloadInfo() : m_TotalSize(0), m_ReQueried(false), m_Hidden(false), m_SpeedDiff(std::tuple(0,0,0)) {} + DownloadInfo() : m_TotalSize(0), m_ReQueried(false), m_Hidden(false), m_SpeedDiff(std::tuple(0,0,0,0,0)) {} }; public: diff --git a/src/installationmanager.cpp b/src/installationmanager.cpp index 27c83787..b7ec3d68 100644 --- a/src/installationmanager.cpp +++ b/src/installationmanager.cpp @@ -95,9 +95,6 @@ InstallationManager::InstallationManager() if (!m_ArchiveHandler->isValid()) { throw MyException(getErrorString(m_ArchiveHandler->getLastError())); } - - connect(this, SIGNAL(progressUpdate(float)), this, (SLOT(doProgressUpdate(float))), Qt::QueuedConnection); - connect(this, SIGNAL(progressUpdate(const QString)), this, (SLOT(doProgressFileUpdate(const QString))), Qt::QueuedConnection); } InstallationManager::~InstallationManager() @@ -203,9 +200,12 @@ bool InstallationManager::unpackSingleFile(const QString &fileName) ); }); do { - ::Sleep(50); + if (m_Progress != m_InstallationProgress->value()) + m_InstallationProgress->setValue(m_Progress); + if (m_ProgressFile != m_InstallationProgress->labelText()) + m_InstallationProgress->setLabelText(m_ProgressFile); QCoreApplication::processEvents(); - } while (!future.isFinished()); + } while (!future.isFinished() || m_InstallationProgress->isVisible()); bool res = future.result(); return res; @@ -301,9 +301,12 @@ QStringList InstallationManager::extractFiles(const QStringList &filesOrig, bool ); }); do { - ::Sleep(50); + if (m_Progress != m_InstallationProgress->value()) + m_InstallationProgress->setValue(m_Progress); + if (m_ProgressFile != m_InstallationProgress->labelText()) + m_InstallationProgress->setLabelText(m_ProgressFile); QCoreApplication::processEvents(); - } while (!future.isFinished()); + } while (!future.isFinished() || m_InstallationProgress->isVisible()); if (!future.result()) { throw MyException(QString("extracting failed (%1)").arg(m_ArchiveHandler->getLastError())); } @@ -430,21 +433,9 @@ DirectoryTree::Node *InstallationManager::getSimpleArchiveBase(DirectoryTree *da void InstallationManager::updateProgress(float percentage) -{ - emit progressUpdate(percentage); -} - - -void InstallationManager::updateProgressFile(QString const &fileName) -{ - emit progressUpdate(fileName); -} - - -void InstallationManager::doProgressUpdate(float percentage) { if (m_InstallationProgress != nullptr) { - m_InstallationProgress->setValue(static_cast(percentage * 100.0)); + m_Progress = static_cast(percentage * 100.0); if (m_InstallationProgress->wasCanceled()) { m_ArchiveHandler->cancel(); @@ -453,11 +444,10 @@ void InstallationManager::doProgressUpdate(float percentage) } } -void InstallationManager::doProgressFileUpdate(QString const fileName) + +void InstallationManager::updateProgressFile(QString const &fileName) { - if (m_InstallationProgress != nullptr) { - m_InstallationProgress->setLabelText(fileName); - } + m_ProgressFile = fileName; } @@ -610,7 +600,10 @@ bool InstallationManager::doInstall(GuessedValue &modName, QString game ); }); do { - ::Sleep(50); + if (m_Progress != m_InstallationProgress->value()) + m_InstallationProgress->setValue(m_Progress); + if (m_ProgressFile != m_InstallationProgress->labelText()) + m_InstallationProgress->setLabelText(m_ProgressFile); QCoreApplication::processEvents(); } while (!future.isFinished()); if (!future.result()) { diff --git a/src/installationmanager.h b/src/installationmanager.h index 84ccd1a4..e17aee17 100644 --- a/src/installationmanager.h +++ b/src/installationmanager.h @@ -182,11 +182,6 @@ signals: void progressUpdate(float percentage); void progressUpdate(QString const fileName); -private slots: - - void doProgressUpdate(float percentage); - void doProgressFileUpdate(const QString fileName); - private: struct ByPriority { @@ -217,6 +212,8 @@ private: QString m_CurrentFile; QProgressDialog *m_InstallationProgress { nullptr }; + int m_Progress; + QString m_ProgressFile; std::set m_TempFilesToDelete; -- cgit v1.3.1