diff options
Diffstat (limited to 'src/downloadmanager.cpp')
| -rw-r--r-- | src/downloadmanager.cpp | 432 |
1 files changed, 279 insertions, 153 deletions
diff --git a/src/downloadmanager.cpp b/src/downloadmanager.cpp index 31d8bcec..5200bb4f 100644 --- a/src/downloadmanager.cpp +++ b/src/downloadmanager.cpp @@ -27,6 +27,7 @@ along with Mod Organizer. If not, see <http://www.gnu.org/licenses/>. #include "json.h" #include "selectiondialog.h" #include <utility.h> +#include <bbcode.h> #include <QTimer> #include <QFileInfo> #include <QRegExp> @@ -49,7 +50,7 @@ static const char UNFINISHED[] = ".unfinished"; unsigned int DownloadManager::DownloadInfo::s_NextDownloadID = 1U; -DownloadManager::DownloadInfo *DownloadManager::DownloadInfo::createNew(const NexusInfo &nexusInfo, int modID, int fileID, const QStringList &URLs) +DownloadManager::DownloadInfo *DownloadManager::DownloadInfo::createNew(const ModRepositoryFileInfo *fileInfo, const QStringList &URLs) { DownloadInfo *info = new DownloadInfo; info->m_DownloadID = s_NextDownloadID++; @@ -57,9 +58,7 @@ DownloadManager::DownloadInfo *DownloadManager::DownloadInfo::createNew(const Ne info->m_PreResumeSize = 0LL; info->m_Progress = 0; info->m_ResumePos = 0; - info->m_ModID = modID; - info->m_FileID = fileID; - info->m_NexusInfo = nexusInfo; + info->m_FileInfo = new ModRepositoryFileInfo(*fileInfo); info->m_Urls = URLs; info->m_CurrentUrl = 0; info->m_Tries = AUTOMATIC_RETRIES; @@ -104,17 +103,28 @@ DownloadManager::DownloadInfo *DownloadManager::DownloadInfo::createFromMeta(con info->m_Output.setFileName(filePath); info->m_TotalSize = QFileInfo(filePath).size(); info->m_PreResumeSize = info->m_TotalSize; - info->m_ModID = metaFile.value("modID", 0).toInt(); - info->m_FileID = metaFile.value("fileID", 0).toInt(); info->m_CurrentUrl = 0; info->m_Urls = metaFile.value("url", "").toString().split(";"); info->m_Tries = 0; info->m_TaskProgressId = TaskProgressManager::instance().getId(); - info->m_NexusInfo.m_Name = metaFile.value("name", 0).toString(); - info->m_NexusInfo.m_ModName = metaFile.value("modName", "").toString(); - info->m_NexusInfo.m_Version = metaFile.value("version", 0).toString(); - info->m_NexusInfo.m_NewestVersion = metaFile.value("newestVersion", "").toString(); - info->m_NexusInfo.m_Category = metaFile.value("category", 0).toInt(); + int modID = metaFile.value("modID", 0).toInt(); + int fileID = metaFile.value("fileID", 0).toInt(); + info->m_FileInfo = new ModRepositoryFileInfo(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->modID = modID; + info->m_FileInfo->fileID = fileID; + info->m_FileInfo->description = metaFile.value("description").toString(); + info->m_FileInfo->version.parse(metaFile.value("version", "0").toString()); + info->m_FileInfo->newestVersion.parse(metaFile.value("newestVersion", "0").toString()); + info->m_FileInfo->categoryID = metaFile.value("category", 0).toInt(); + info->m_FileInfo->fileCategory = metaFile.value("fileCategory", 0).toInt(); + info->m_FileInfo->repository = metaFile.value("repository", "Nexus").toString(); + info->m_FileInfo->userData = metaFile.value("userData").toMap(); return info; } @@ -138,7 +148,10 @@ void DownloadManager::DownloadInfo::setName(QString newName, bool renameFile) metaFile.rename(newName.mid(0).append(".meta")); } } - m_Output.setFileName(newName); + if (!m_Output.isOpen()) { + // can't set file name if it's open + m_Output.setFileName(newName); + } } bool DownloadManager::DownloadInfo::isPausedState() @@ -243,72 +256,75 @@ void DownloadManager::setShowHidden(bool showHidden) void DownloadManager::refreshList() { - int downloadsBefore = m_ActiveDownloads.size(); + try { + int downloadsBefore = m_ActiveDownloads.size(); - // remove finished downloads - for (QVector<DownloadInfo*>::iterator Iter = m_ActiveDownloads.begin(); Iter != m_ActiveDownloads.end();) { - if (((*Iter)->m_State == STATE_READY) || ((*Iter)->m_State == STATE_INSTALLED) || ((*Iter)->m_State == STATE_UNINSTALLED)) { - delete *Iter; - Iter = m_ActiveDownloads.erase(Iter); - } else { - ++Iter; + // remove finished downloads + for (QVector<DownloadInfo*>::iterator iter = m_ActiveDownloads.begin(); iter != m_ActiveDownloads.end();) { + if (((*iter)->m_State == STATE_READY) || ((*iter)->m_State == STATE_INSTALLED) || ((*iter)->m_State == STATE_UNINSTALLED)) { + delete *iter; + iter = m_ActiveDownloads.erase(iter); + } else { + ++iter; + } } - } - QStringList nameFilters(m_SupportedExtensions); - foreach (const QString &extension, m_SupportedExtensions) { - nameFilters.append("*." + extension); - } - - nameFilters.append(QString("*").append(UNFINISHED)); - QDir dir(QDir::fromNativeSeparators(m_OutputDirectory)); - - // find orphaned meta files and delete them (sounds cruel but it's better for everyone) - QStringList orphans; - QStringList metaFiles = dir.entryList(QStringList() << "*.meta"); - foreach (const QString &metaFile, metaFiles) { - QString baseFile = metaFile.left(metaFile.length() - 5); - if (!QFile::exists(dir.absoluteFilePath(baseFile))) { - orphans.append(dir.absoluteFilePath(metaFile)); + QStringList nameFilters(m_SupportedExtensions); + foreach (const QString &extension, m_SupportedExtensions) { + nameFilters.append("*." + extension); } - } - if (orphans.size() > 0) { - qDebug("%d orphaned meta files will be deleted", orphans.size()); - shellDelete(orphans, true); - } - // add existing downloads to list - foreach (QString file, dir.entryList(nameFilters, QDir::Files, QDir::Time)) { - bool Exists = false; - for (QVector<DownloadInfo*>::const_iterator Iter = m_ActiveDownloads.begin(); Iter != m_ActiveDownloads.end() && !Exists; ++Iter) { - if (QString::compare((*Iter)->m_FileName, file, Qt::CaseInsensitive) == 0) { - Exists = true; - } else if (QString::compare(QFileInfo((*Iter)->m_Output.fileName()).fileName(), file, Qt::CaseInsensitive) == 0) { - Exists = true; + nameFilters.append(QString("*").append(UNFINISHED)); + QDir dir(QDir::fromNativeSeparators(m_OutputDirectory)); + + // find orphaned meta files and delete them (sounds cruel but it's better for everyone) + QStringList orphans; + QStringList metaFiles = dir.entryList(QStringList() << "*.meta"); + foreach (const QString &metaFile, metaFiles) { + QString baseFile = metaFile.left(metaFile.length() - 5); + if (!QFile::exists(dir.absoluteFilePath(baseFile))) { + orphans.append(dir.absoluteFilePath(metaFile)); } } - if (Exists) { - qDebug("%s exists", qPrintable(file)); - continue; + if (orphans.size() > 0) { + qDebug("%d orphaned meta files will be deleted", orphans.size()); + shellDelete(orphans, true); } - QString fileName = QDir::fromNativeSeparators(m_OutputDirectory) + "/" + file; + // add existing downloads to list + foreach (QString file, dir.entryList(nameFilters, QDir::Files, QDir::Time)) { + bool Exists = false; + for (QVector<DownloadInfo*>::const_iterator Iter = m_ActiveDownloads.begin(); Iter != m_ActiveDownloads.end() && !Exists; ++Iter) { + if (QString::compare((*Iter)->m_FileName, file, Qt::CaseInsensitive) == 0) { + Exists = true; + } else if (QString::compare(QFileInfo((*Iter)->m_Output.fileName()).fileName(), file, Qt::CaseInsensitive) == 0) { + Exists = true; + } + } + if (Exists) { + continue; + } - DownloadInfo *info = DownloadInfo::createFromMeta(fileName, m_ShowHidden); - if (info != NULL) { - m_ActiveDownloads.push_front(info); + QString fileName = QDir::fromNativeSeparators(m_OutputDirectory) + "/" + file; + + DownloadInfo *info = DownloadInfo::createFromMeta(fileName, m_ShowHidden); + if (info != NULL) { + m_ActiveDownloads.push_front(info); + } } - } - if (m_ActiveDownloads.size() != downloadsBefore) { - qDebug("downloads after refresh: %d", m_ActiveDownloads.size()); + if (m_ActiveDownloads.size() != downloadsBefore) { + qDebug("downloads after refresh: %d", m_ActiveDownloads.size()); + } + emit update(-1); + } catch (const std::bad_alloc&) { + reportError(tr("Memory allocation error (in refreshing directory).")); } - emit update(-1); } bool DownloadManager::addDownload(const QStringList &URLs, - int modID, int fileID, const NexusInfo &nexusInfo) + int modID, int fileID, const ModRepositoryFileInfo *fileInfo) { QString fileName = QFileInfo(URLs.first()).fileName(); if (fileName.isEmpty()) { @@ -316,20 +332,34 @@ bool DownloadManager::addDownload(const QStringList &URLs, } QNetworkRequest request(URLs.first()); - return addDownload(m_NexusInterface->getAccessManager()->get(request), URLs, fileName, modID, fileID, nexusInfo); + return addDownload(m_NexusInterface->getAccessManager()->get(request), URLs, fileName, modID, fileID, fileInfo); +} + + +bool DownloadManager::addDownload(QNetworkReply *reply, const ModRepositoryFileInfo *fileInfo) +{ + QString fileName = getFileNameFromNetworkReply(reply); + if (fileName.isEmpty()) { + fileName = "unknown"; + } + + return addDownload(reply, QStringList(reply->url().toString()), fileName, fileInfo->modID, fileInfo->fileID, fileInfo); } bool DownloadManager::addDownload(QNetworkReply *reply, const QStringList &URLs, const QString &fileName, - int modID, int fileID, const NexusInfo &nexusInfo) + int modID, int fileID, const ModRepositoryFileInfo *fileInfo) { + if (!reply->isRunning()) { + qDebug("this is not a running download! %d", reply->isFinished()); + } // download invoked from an already open network reply (i.e. download link in the browser) - DownloadInfo *newDownload = DownloadInfo::createNew(nexusInfo, modID, fileID, URLs); + DownloadInfo *newDownload = DownloadInfo::createNew(fileInfo, URLs); QString baseName = fileName; - if (!nexusInfo.m_FileName.isEmpty()) { - baseName = nexusInfo.m_FileName; + if (!fileInfo->fileName.isEmpty()) { + baseName = fileInfo->fileName; } else { QString dispoName = getFileNameFromNetworkReply(reply); @@ -383,6 +413,7 @@ void DownloadManager::startDownload(QNetworkReply *reply, DownloadInfo *newDownl } newDownload->m_StartTime.start(); + createMetaFile(newDownload); if (!newDownload->m_Output.open(mode)) { reportError(tr("failed to download %1: could not open output file: %2") @@ -392,20 +423,24 @@ 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())); if (!resume) { newDownload->m_PreResumeSize = newDownload->m_Output.size(); - - removePending(newDownload->m_ModID, newDownload->m_FileID); + removePending(newDownload->m_FileInfo->modID, newDownload->m_FileInfo->fileID); emit aboutToUpdate(); - m_ActiveDownloads.append(newDownload); emit update(-1); emit downloadAdded(); + + if (reply->isFinished()) { + // it's possible the download has already finished before this function ran + downloadFinished(); + } } } @@ -424,12 +459,11 @@ void DownloadManager::addNXMDownload(const QString &url) } emit aboutToUpdate(); - m_PendingDownloads.append(std::make_pair(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.modId(), nxmInfo.fileId(), this, nxmInfo.fileId(), "")); } @@ -574,8 +608,11 @@ void DownloadManager::pauseDownload(int index) DownloadInfo *info = m_ActiveDownloads.at(index); if (info->m_State == STATE_DOWNLOADING) { - setState(info, STATE_PAUSING); - qDebug("pausing %d - %s", index, info->m_FileName.toUtf8().constData()); + if (info->m_Reply->isRunning()) { + setState(info, STATE_PAUSING); + } else { + setState(info, STATE_PAUSED); + } } else if ((info->m_State == STATE_FETCHINGMODINFO) || (info->m_State == STATE_FETCHINGFILEINFO)) { setState(info, STATE_READY); } @@ -600,6 +637,11 @@ void DownloadManager::resumeDownloadInt(int index) } DownloadInfo *info = m_ActiveDownloads[index]; if (info->isPausedState()) { + if ((info->m_Urls.size() == 0) + || ((info->m_Urls.size() == 1) && (info->m_Urls[0].size() == 0))) { + emit showMessage(tr("No known download urls. Sorry, this download can't be resumed.")); + return; + } if (info->m_State == STATE_ERROR) { info->m_CurrentUrl = (info->m_CurrentUrl + 1) % info->m_Urls.count(); } @@ -635,16 +677,21 @@ void DownloadManager::queryInfo(int index) } DownloadInfo *info = m_ActiveDownloads[index]; + if (info->m_FileInfo->repository != "Nexus") { + qWarning("re-querying file info is currently only possible with Nexus"); + return; + } + if (info->m_State < DownloadManager::STATE_READY) { // UI shouldn't allow this return; } - if (info->m_ModID == 0UL) { + if (info->m_FileInfo->modID == 0UL) { QString fileName = getFileName(index); QString ignore; - NexusInterface::interpretNexusFileName(fileName, ignore, info->m_ModID, true); - if (info->m_ModID < 0) { + NexusInterface::interpretNexusFileName(fileName, ignore, info->m_FileInfo->modID, true); + if (info->m_FileInfo->modID < 0) { QString modIDString; while (modIDString.isEmpty()) { modIDString = QInputDialog::getText(NULL, tr("Please enter the nexus mod id"), tr("Mod ID:"), QLineEdit::Normal, @@ -657,12 +704,11 @@ void DownloadManager::queryInfo(int index) modIDString.clear(); } } - info->m_ModID = modIDString.toInt(NULL, 10); + info->m_FileInfo->modID = modIDString.toInt(NULL, 10); } } info->m_ReQueried = true; setState(info, STATE_FETCHINGMODINFO); -// m_RequestIDs.insert(m_NexusInterface->requestFiles(info->m_ModID, this, qVariantFromValue(static_cast<void*>(info)))); } @@ -694,6 +740,34 @@ QString DownloadManager::getFilePath(int index) const return m_OutputDirectory + "/" + m_ActiveDownloads.at(index)->m_FileName; } +QString DownloadManager::getFileTypeString(int fileType) +{ + switch (fileType) { + case 1: return tr("Main"); + case 2: return tr("Update"); + case 3: return tr("Optional"); + case 4: return tr("Old"); + case 5: return tr("Misc"); + default: return tr("Unknown"); + } +} + +QString DownloadManager::getDisplayName(int index) const +{ + if ((index < 0) || (index >= m_ActiveDownloads.size())) { + throw MyException(tr("invalid index")); + } + + DownloadInfo *info = m_ActiveDownloads.at(index); + + if (!info->m_FileInfo->name.isEmpty()) { + return QString("%1 (%2, v%3)").arg(info->m_FileInfo->name) + .arg(getFileTypeString(info->m_FileInfo->fileCategory)) + .arg(info->m_FileInfo->version.displayString()); + } else { + return info->m_FileName; + } +} QString DownloadManager::getFileName(int index) const { @@ -755,7 +829,11 @@ bool DownloadManager::isInfoIncomplete(int index) const } DownloadInfo *info = m_ActiveDownloads.at(index); - return (info->m_FileID == 0) || (info->m_ModID == 0) || info->m_NexusInfo.m_Version.isEmpty(); + if (info->m_FileInfo->repository != "Nexus") { + // other repositories currently don't support re-querying info anyway + return false; + } + return (info->m_FileInfo->fileID == 0) || (info->m_FileInfo->modID == 0) || !info->m_FileInfo->version.isValid(); } @@ -764,7 +842,7 @@ int DownloadManager::getModID(int index) const if ((index < 0) || (index >= m_ActiveDownloads.size())) { throw MyException(tr("invalid index")); } - return m_ActiveDownloads.at(index)->m_ModID; + return m_ActiveDownloads.at(index)->m_FileInfo->modID; } bool DownloadManager::isHidden(int index) const @@ -776,13 +854,13 @@ bool DownloadManager::isHidden(int index) const } -NexusInfo DownloadManager::getNexusInfo(int index) const +const ModRepositoryFileInfo *DownloadManager::getFileInfo(int index) const { if ((index < 0) || (index >= m_ActiveDownloads.size())) { throw MyException(tr("invalid index")); } - return m_ActiveDownloads.at(index)->m_NexusInfo; + return m_ActiveDownloads.at(index)->m_FileInfo; } @@ -864,10 +942,10 @@ void DownloadManager::setState(DownloadManager::DownloadInfo *info, DownloadMana info->m_Reply->abort(); } break; case STATE_FETCHINGMODINFO: { - m_RequestIDs.insert(m_NexusInterface->requestDescription(info->m_ModID, this, info->m_DownloadID)); + m_RequestIDs.insert(m_NexusInterface->requestDescription(info->m_FileInfo->modID, this, info->m_DownloadID, QString())); } break; case STATE_FETCHINGFILEINFO: { - m_RequestIDs.insert(m_NexusInterface->requestFiles(info->m_ModID, this, info->m_DownloadID)); + m_RequestIDs.insert(m_NexusInterface->requestFiles(info->m_FileInfo->modID, this, info->m_DownloadID, QString())); } break; case STATE_READY: { createMetaFile(info); @@ -900,32 +978,40 @@ void DownloadManager::downloadProgress(qint64 bytesReceived, qint64 bytesTotal) return; } int index = 0; - DownloadInfo *info = findDownload(this->sender(), &index); - if (info != NULL) { - if (info->m_State == STATE_CANCELING) { - setState(info, STATE_CANCELED); - } else if (info->m_State == STATE_PAUSING) { - setState(info, STATE_PAUSED); - } else { - 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); + try { + DownloadInfo *info = findDownload(this->sender(), &index); + if (info != NULL) { + if (info->m_State == STATE_CANCELING) { + setState(info, STATE_CANCELED); + } else if (info->m_State == STATE_PAUSING) { + setState(info, STATE_PAUSED); + } else { + 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); + } } } + } catch (const std::bad_alloc&) { + reportError(tr("Memory allocation error (in processing progress event).")); } } void DownloadManager::downloadReadyRead() { - DownloadInfo *info = findDownload(this->sender()); - if (info != NULL) { - info->m_Output.write(info->m_Reply->readAll()); + try { + DownloadInfo *info = findDownload(this->sender()); + if (info != NULL) { + info->m_Output.write(info->m_Reply->readAll()); + } + } catch (const std::bad_alloc&) { + reportError(tr("Memory allocation error (in processing downloaded data).")); } } @@ -933,16 +1019,19 @@ void DownloadManager::downloadReadyRead() void DownloadManager::createMetaFile(DownloadInfo *info) { QSettings metaFile(QString("%1.meta").arg(info->m_Output.fileName()), QSettings::IniFormat); - metaFile.setValue("modID", info->m_ModID); - metaFile.setValue("fileID", info->m_FileID); + metaFile.setValue("modID", info->m_FileInfo->modID); + metaFile.setValue("fileID", info->m_FileInfo->fileID); metaFile.setValue("url", info->m_Urls.join(";")); - metaFile.setValue("name", info->m_NexusInfo.m_Name); - metaFile.setValue("modName", info->m_NexusInfo.m_ModName); - metaFile.setValue("version", info->m_NexusInfo.m_Version); - metaFile.setValue("fileTime", info->m_NexusInfo.m_FileTime); - metaFile.setValue("fileCategory", info->m_NexusInfo.m_FileCategory); - metaFile.setValue("newestVersion", info->m_NexusInfo.m_NewestVersion); - metaFile.setValue("category", info->m_NexusInfo.m_Category); + metaFile.setValue("name", info->m_FileInfo->name); + metaFile.setValue("description", info->m_FileInfo->description); + metaFile.setValue("modName", info->m_FileInfo->modName); + metaFile.setValue("version", info->m_FileInfo->version.canonicalString()); + metaFile.setValue("newestVersion", info->m_FileInfo->newestVersion.canonicalString()); + metaFile.setValue("fileTime", info->m_FileInfo->fileTime); + metaFile.setValue("fileCategory", info->m_FileInfo->fileCategory); + metaFile.setValue("category", info->m_FileInfo->categoryID); + metaFile.setValue("repository", info->m_FileInfo->repository); + metaFile.setValue("userData", info->m_FileInfo->userData); metaFile.setValue("installed", info->m_State == DownloadManager::STATE_INSTALLED); metaFile.setValue("uninstalled", info->m_State == DownloadManager::STATE_UNINSTALLED); metaFile.setValue("paused", (info->m_State == DownloadManager::STATE_PAUSED) || @@ -971,10 +1060,10 @@ void DownloadManager::nxmDescriptionAvailable(int, QVariant userData, QVariant r DownloadInfo *info = downloadInfoByID(userData.toInt()); if (info == NULL) return; - info->m_NexusInfo.m_Category = result["category_id"].toInt(); - info->m_NexusInfo.m_ModName = result["name"].toString().trimmed(); - info->m_NexusInfo.m_NewestVersion = result["version"].toString(); - if (info->m_FileID != 0) { + info->m_FileInfo->categoryID = result["category_id"].toInt(); + info->m_FileInfo->modName = result["name"].toString().trimmed(); + info->m_FileInfo->newestVersion.parse(result["version"].toString()); + if (info->m_FileInfo->fileID != 0) { setState(info, STATE_READY); } else { setState(info, STATE_FETCHINGFILEINFO); @@ -993,6 +1082,18 @@ QDateTime DownloadManager::matchDate(const QString &timeString) } +EFileCategory convertFileCategory(int id) +{ + // TODO: need to handle file categories in the mod page plugin + switch (id) { + case 0: return TYPE_MAIN; + case 1: return TYPE_UPDATE; + case 2: return TYPE_OPTION; + default: return TYPE_MAIN; + } +} + + void DownloadManager::nxmFilesAvailable(int, QVariant userData, QVariant resultData, int requestID) { std::set<int>::iterator idIter = m_RequestIDs.find(requestID); @@ -1024,14 +1125,14 @@ void DownloadManager::nxmFilesAvailable(int, QVariant userData, QVariant resultD QString fileNameVariant = fileName.mid(0).replace(' ', '_'); if ((fileName == info->m_FileName) || (fileName == alternativeLocalName) || (fileNameVariant == info->m_FileName) || (fileNameVariant == alternativeLocalName)) { - info->m_NexusInfo.m_Name = fileInfo["name"].toString(); - info->m_NexusInfo.m_Version = fileInfo["version"].toString(); - if (info->m_NexusInfo.m_Version.isEmpty()) { - info->m_NexusInfo.m_Version = info->m_NexusInfo.m_NewestVersion; + info->m_FileInfo->name = fileInfo["name"].toString(); + info->m_FileInfo->version.parse(fileInfo["version"].toString()); + if (!info->m_FileInfo->version.isValid()) { + info->m_FileInfo->version = info->m_FileInfo->newestVersion; } - info->m_NexusInfo.m_FileCategory = fileInfo["category_id"].toInt(); - info->m_NexusInfo.m_FileTime = matchDate(fileInfo["date"].toString()); - info->m_FileID = fileInfo["id"].toInt(); + info->m_FileInfo->fileCategory = convertFileCategory(fileInfo["category_id"].toInt()); + info->m_FileInfo->fileTime = matchDate(fileInfo["date"].toString()); + info->m_FileInfo->fileID = fileInfo["id"].toInt(); found = true; break; } @@ -1050,16 +1151,16 @@ void DownloadManager::nxmFilesAvailable(int, QVariant userData, QVariant resultD } if (selection.exec() == QDialog::Accepted) { QVariantMap fileInfo = selection.getChoiceData().toMap(); - info->m_NexusInfo.m_Name = fileInfo["name"].toString(); - info->m_NexusInfo.m_Version = fileInfo["version"].toString(); - info->m_NexusInfo.m_FileCategory = fileInfo["category_id"].toInt(); - info->m_FileID = fileInfo["id"].toInt(); + info->m_FileInfo->name = fileInfo["name"].toString(); + info->m_FileInfo->version.parse(fileInfo["version"].toString()); + info->m_FileInfo->fileCategory = convertFileCategory(fileInfo["category_id"].toInt()); + info->m_FileInfo->fileID = fileInfo["id"].toInt(); } else { emit showMessage(tr("No matching file found on Nexus! Maybe this file is no longer available or it was renamed?")); } } } else { - if (info->m_FileID == 0) { + if (info->m_FileInfo->fileID == 0) { qWarning("could not determine file id for %s (state %d)", info->m_FileName.toUtf8().constData(), info->m_State); } @@ -1078,19 +1179,26 @@ void DownloadManager::nxmFileInfoAvailable(int modID, int fileID, QVariant userD m_RequestIDs.erase(idIter); } - NexusInfo info; + ModRepositoryFileInfo *info = new ModRepositoryFileInfo(); QVariantMap result = resultData.toMap(); - info.m_Name = result["name"].toString(); - qDebug("file info received for %s", qPrintable(info.m_Name)); - info.m_Version = result["version"].toString(); - if (info.m_Version.isEmpty()) { - info.m_Version = info.m_NewestVersion; + info->name = result["name"].toString(); + qDebug("file info received for %s", qPrintable(info->name)); + info->version.parse(result["version"].toString()); + if (!info->version.isValid()) { + info->version = info->newestVersion; } - info.m_FileName = result["uri"].toString(); - info.m_FileTime = matchDate(result["date"].toString()); + info->fileName = result["uri"].toString(); + info->fileCategory = result["category_id"].toInt(); + info->fileTime = matchDate(result["date"].toString()); + info->description = BBCode::convertToHTML(result["description"].toString()); + + info->repository = "Nexus"; + info->modID = modID; + info->fileID = fileID; - m_RequestIDs.insert(m_NexusInterface->requestDownloadURL(modID, fileID, this, QVariant::fromValue(info))); + QObject *test = info; + m_RequestIDs.insert(m_NexusInterface->requestDownloadURL(modID, fileID, this, qVariantFromValue(test), QString())); } @@ -1138,7 +1246,7 @@ bool DownloadManager::ServerByPreference(const std::map<QString, int> &preferred int DownloadManager::startDownloadURLs(const QStringList &urls) { - addDownload(urls, -1); + addDownload(urls, -1, -1, nullptr); return m_ActiveDownloads.size() - 1; } @@ -1173,7 +1281,7 @@ void DownloadManager::nxmDownloadURLsAvailable(int modID, int fileID, QVariant u m_RequestIDs.erase(idIter); } - NexusInfo info = userData.value<NexusInfo>(); + ModRepositoryFileInfo *info = qobject_cast<ModRepositoryFileInfo*>(qvariant_cast<QObject*>(userData)); QVariantList resultList = resultData.toList(); if (resultList.length() == 0) { removePending(modID, fileID); @@ -1183,14 +1291,13 @@ void DownloadManager::nxmDownloadURLsAvailable(int modID, int fileID, QVariant u std::sort(resultList.begin(), resultList.end(), boost::bind(&DownloadManager::ServerByPreference, m_PreferredServers, _1, _2)); - info.m_DownloadMap = resultList; + info->userData["downloadMap"] = resultList; QStringList URLs; foreach (const QVariant &server, resultList) { URLs.append(server.toMap()["URI"].toString()); } - addDownload(URLs, modID, fileID, info); } @@ -1208,7 +1315,7 @@ void DownloadManager::nxmRequestFailed(int modID, int fileID, QVariant userData, for (QVector<DownloadInfo*>::iterator iter = m_ActiveDownloads.begin(); iter != m_ActiveDownloads.end(); ++iter, ++index) { DownloadInfo *info = *iter; - if (info->m_ModID == modID) { + if (info->m_FileInfo->modID == modID) { if (info->m_State < STATE_FETCHINGMODINFO) { m_ActiveDownloads.erase(iter); delete info; @@ -1246,7 +1353,7 @@ void DownloadManager::downloadFinished() textData) { if (info->m_Tries == 0) { if (textData && (reply->error() == QNetworkReply::NoError)) { - emit showMessage(tr("Download failed. Server reported: %1").arg(readFileText(info->m_Output.fileName()))); + 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())); } @@ -1279,20 +1386,27 @@ void DownloadManager::downloadFinished() createMetaFile(info); emit update(index); } else { - QString url = info->m_Urls[info->m_CurrentUrl]; - foreach (const QVariant &server, info->m_NexusInfo.m_DownloadMap) { - QVariantMap serverMap = server.toMap(); - if (serverMap["URI"].toString() == url) { - int deltaTime = info->m_StartTime.secsTo(QTime::currentTime()); - if (deltaTime > 5) { - emit downloadSpeed(serverMap["Name"].toString(), (info->m_TotalSize - info->m_PreResumeSize) / deltaTime); - } // no division by zero please! Also, if the download is shorter than a few seconds, the result is way to inprecise - break; + if (info->m_FileInfo->userData.contains("downloadMap")) { + foreach (const QVariant &server, info->m_FileInfo->userData["downloadMap"].toList()) { + QVariantMap serverMap = server.toMap(); + if (serverMap["URI"].toString() == url) { + int deltaTime = info->m_StartTime.secsTo(QTime::currentTime()); + if (deltaTime > 5) { + emit downloadSpeed(serverMap["Name"].toString(), (info->m_TotalSize - info->m_PreResumeSize) / deltaTime); + } // no division by zero please! Also, if the download is shorter than a few seconds, the result is way to inprecise + break; + } } } - setState(info, STATE_FETCHINGMODINFO); // need to set this state before changing the file name, otherwise .unfinished is appended + bool isNexus = info->m_FileInfo->repository == "Nexus"; + // need to change state before changing the file name, otherwise .unfinished is appended + if (isNexus) { + setState(info, STATE_FETCHINGMODINFO); + } else { + setState(info, STATE_NOFETCH); + } QString newName = getFileNameFromNetworkReply(reply); QString oldName = QFileInfo(info->m_Output).fileName(); @@ -1302,6 +1416,10 @@ void DownloadManager::downloadFinished() info->setName(m_OutputDirectory + "/" + info->m_FileName, true); // don't rename but remove the ".unfinished" extension } + if (!isNexus) { + setState(info, STATE_READY); + } + emit update(index); } reply->close(); @@ -1317,6 +1435,14 @@ void DownloadManager::downloadFinished() } +void DownloadManager::downloadError(QNetworkReply::NetworkError error) +{ + if (error != QNetworkReply::OperationCanceledError) { + qWarning("Download error occured: %d", error); + } +} + + void DownloadManager::metaDataChanged() { int index = 0; @@ -1327,7 +1453,7 @@ void DownloadManager::metaDataChanged() if (!newName.isEmpty() && (newName != info->m_FileName)) { info->setName(getDownloadFileName(newName), true); refreshAlphabeticalTranslation(); - if (!info->m_Output.open(QIODevice::WriteOnly | QIODevice::Append)) { + if (!info->m_Output.isOpen() && !info->m_Output.open(QIODevice::WriteOnly | QIODevice::Append)) { reportError(tr("failed to re-open %1").arg(info->m_FileName)); setState(info, STATE_CANCELING); } |
