summaryrefslogtreecommitdiff
path: root/src/downloadmanager.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/downloadmanager.cpp')
-rw-r--r--src/downloadmanager.cpp199
1 files changed, 129 insertions, 70 deletions
diff --git a/src/downloadmanager.cpp b/src/downloadmanager.cpp
index c8f118f6..676cd7ef 100644
--- a/src/downloadmanager.cpp
+++ b/src/downloadmanager.cpp
@@ -48,7 +48,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++;
@@ -56,9 +56,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;
@@ -100,16 +98,21 @@ 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_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();
+ info->m_FileInfo = new ModRepositoryFileInfo();
+ info->m_FileInfo->name = metaFile.value("name", "").toString();
+ info->m_FileInfo->modName = metaFile.value("modName", "").toString();
+ info->m_FileInfo->modID = metaFile.value("modID", 0).toInt();
+ info->m_FileInfo->fileID = metaFile.value("fileID", 0).toInt();
+ 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;
}
@@ -184,8 +187,11 @@ void DownloadManager::pauseAll()
::Sleep(100);
bool done = false;
+
+ int tries = 20;
+
// further loops: busy waiting for all downloads to complete. This could be neater...
- while (!done) {
+ while (!done && (tries > 0)) {
QCoreApplication::processEvents();
done = true;
foreach (DownloadInfo *info, m_ActiveDownloads) {
@@ -197,6 +203,7 @@ void DownloadManager::pauseAll()
}
if (!done) {
::Sleep(100);
+ --tries;
}
}
}
@@ -273,8 +280,7 @@ void DownloadManager::refreshList()
}
-bool DownloadManager::addDownload(const QStringList &URLs,
- int modID, int fileID, const NexusInfo &nexusInfo)
+bool DownloadManager::addDownload(const QStringList &URLs, const ModRepositoryFileInfo *fileInfo)
{
QString fileName = QFileInfo(URLs.first()).fileName();
if (fileName.isEmpty()) {
@@ -282,20 +288,30 @@ 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, fileInfo);
}
-bool DownloadManager::addDownload(QNetworkReply *reply, const QStringList &URLs, const QString &fileName,
- int modID, int fileID, const NexusInfo &nexusInfo)
+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);
+}
+
+
+bool DownloadManager::addDownload(QNetworkReply *reply, const QStringList &URLs, const QString &fileName, const ModRepositoryFileInfo *fileInfo)
{
// 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);
@@ -548,16 +564,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,
@@ -570,7 +591,7 @@ 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;
@@ -655,7 +676,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();
}
@@ -664,17 +689,17 @@ 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;
}
-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;
}
@@ -756,10 +781,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));
} 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));
} break;
case STATE_READY: {
createMetaFile(info);
@@ -825,15 +850,18 @@ 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("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("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) ||
@@ -862,11 +890,11 @@ 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();
+ 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_FileID != 0) {
+ if (info->m_FileInfo->fileID != 0) {
setState(info, STATE_READY);
} else {
setState(info, STATE_FETCHINGFILEINFO);
@@ -874,6 +902,18 @@ void DownloadManager::nxmDescriptionAvailable(int, QVariant userData, QVariant r
}
+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);
@@ -905,10 +945,10 @@ 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();
- 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();
found = true;
break;
}
@@ -927,16 +967,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);
}
@@ -955,15 +995,22 @@ void DownloadManager::nxmFileInfoAvailable(int modID, int fileID, QVariant, QVar
m_RequestIDs.erase(idIter);
}
- NexusInfo info;
+ ModRepositoryFileInfo *info = new ModRepositoryFileInfo();
QVariantMap result = resultData.toMap();
- info.m_Name = result["name"].toString();
- info.m_Version = result["version"].toString();
- info.m_FileName = result["uri"].toString();
+ info->name = result["name"].toString();
+ info->version.parse(result["version"].toString());
+ info->fileName = result["uri"].toString();
+ info->fileCategory = result["category_id"].toInt();
+ info->description = result["description"].toString();
- m_RequestIDs.insert(m_NexusInterface->requestDownloadURL(modID, fileID, this, qVariantFromValue(info)));
+ info->repository = "Nexus";
+ info->modID = modID;
+ info->fileID = fileID;
+
+ QObject *test = info;
+ m_RequestIDs.insert(m_NexusInterface->requestDownloadURL(modID, fileID, this, qVariantFromValue(test)));
}
@@ -1011,7 +1058,7 @@ bool DownloadManager::ServerByPreference(const std::map<QString, int> &preferred
int DownloadManager::startDownloadURLs(const QStringList &urls)
{
- addDownload(urls, -1);
+ addDownload(urls, NULL);
return m_ActiveDownloads.size() - 1;
}
@@ -1046,7 +1093,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) {
emit showMessage(tr("No download server available. Please try again later."));
@@ -1055,7 +1102,7 @@ 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;
@@ -1063,7 +1110,7 @@ void DownloadManager::nxmDownloadURLsAvailable(int modID, int fileID, QVariant u
URLs.append(server.toMap()["URI"].toString());
}
- addDownload(URLs, modID, fileID, info);
+ addDownload(URLs, info);
}
@@ -1080,7 +1127,7 @@ void DownloadManager::nxmRequestFailed(int modID, QVariant, int requestID, const
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;
@@ -1146,18 +1193,26 @@ void DownloadManager::downloadFinished()
} 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();
@@ -1167,6 +1222,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();