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.h | 23 +++++++++++++---------- 1 file changed, 13 insertions(+), 10 deletions(-) (limited to 'src/downloadmanager.h') diff --git a/src/downloadmanager.h b/src/downloadmanager.h index a6d3b20c..780aeb5c 100644 --- a/src/downloadmanager.h +++ b/src/downloadmanager.h @@ -38,6 +38,7 @@ along with Mod Organizer. If not, see . namespace MOBase { class IPluginGame; } class NexusInterface; +class PluginContainer; /*! * \brief manages downloading of files and provides progress information for gui elements @@ -162,6 +163,8 @@ public: */ void setShowHidden(bool showHidden); + void setPluginContainer(PluginContainer *pluginContainer); + /** * @brief download from an already open network connection * @@ -179,7 +182,7 @@ public: * @param fileInfo information previously retrieved from the nexus network * @return true if the download was started, false if it wasn't. The latter currently only happens if there is a duplicate and the user decides not to download again **/ - bool addDownload(QNetworkReply *reply, const QStringList &URLs, const QString &fileName, int modID, int fileID = 0, const MOBase::ModRepositoryFileInfo *fileInfo = new MOBase::ModRepositoryFileInfo()); + bool addDownload(QNetworkReply *reply, const QStringList &URLs, const QString &fileName, QString gameName, int modID, int fileID = 0, const MOBase::ModRepositoryFileInfo *fileInfo = new MOBase::ModRepositoryFileInfo()); /** * @brief start a download using a nxm-link @@ -209,7 +212,7 @@ public: * @param index index of the pending download (index in the range [0, numPendingDownloads()[) * @return pair of modid, fileid */ - std::pair getPendingDownload(int index); + std::tuple getPendingDownload(int index); /** * @brief retrieve the full path to the download specified by index @@ -411,15 +414,15 @@ public slots: void queryInfo(int index); - void nxmDescriptionAvailable(int modID, QVariant userData, QVariant resultData, int requestID); + void nxmDescriptionAvailable(QString gameName, int modID, QVariant userData, QVariant resultData, int requestID); - void nxmFilesAvailable(int modID, QVariant userData, QVariant resultData, int requestID); + void nxmFilesAvailable(QString gameName, int modID, QVariant userData, QVariant resultData, int requestID); - void nxmFileInfoAvailable(int modID, int fileID, QVariant userData, QVariant resultData, int requestID); + void nxmFileInfoAvailable(QString gameName, int modID, int fileID, QVariant userData, QVariant resultData, int requestID); - void nxmDownloadURLsAvailable(int modID, int fileID, QVariant userData, QVariant resultData, int requestID); + void nxmDownloadURLsAvailable(QString gameName, int modID, int fileID, QVariant userData, QVariant resultData, int requestID); - void nxmRequestFailed(int modID, int fileID, QVariant userData, int requestID, const QString &errorString); + void nxmRequestFailed(QString gameName, int modID, int fileID, QVariant userData, int requestID, const QString &errorString); void managedGameChanged(MOBase::IPluginGame const *gamePlugin); @@ -462,7 +465,7 @@ private: * @param fileInfo information previously retrieved from the mod page * @return true if the download was started, false if it wasn't. The latter currently only happens if there is a duplicate and the user decides not to download again **/ - bool addDownload(const QStringList &URLs, int modID, int fileID, const MOBase::ModRepositoryFileInfo *fileInfo); + bool addDownload(const QStringList &URLs, QString gameName, int modID, int fileID, const MOBase::ModRepositoryFileInfo *fileInfo); // important: the caller has to lock the list-mutex, otherwise the DownloadInfo-pointer might get invalidated at any time DownloadInfo *findDownload(QObject *reply, int *index = nullptr) const; @@ -481,7 +484,7 @@ private: QDateTime matchDate(const QString &timeString); - void removePending(int modID, int fileID); + void removePending(QString gameName, int modID, int fileID); static QString getFileTypeString(int fileType); @@ -493,7 +496,7 @@ private: NexusInterface *m_NexusInterface; - QVector > m_PendingDownloads; + QVector> m_PendingDownloads; QVector m_ActiveDownloads; -- 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.h') 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 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.h') 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.h') 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.h') 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.h') 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.h') 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