Merge pull request #1391 from Trial97/prism_export2
This commit is contained in:
commit
01e17806f6
@ -26,6 +26,7 @@
|
|||||||
#include <QMessageBox>
|
#include <QMessageBox>
|
||||||
#include <QtConcurrentRun>
|
#include <QtConcurrentRun>
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
#include <iterator>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include "Json.h"
|
#include "Json.h"
|
||||||
#include "MMCZip.h"
|
#include "MMCZip.h"
|
||||||
@ -64,20 +65,11 @@ void FlamePackExportTask::executeTask()
|
|||||||
|
|
||||||
bool FlamePackExportTask::abort()
|
bool FlamePackExportTask::abort()
|
||||||
{
|
{
|
||||||
if (task != nullptr) {
|
if (task) {
|
||||||
task->abort();
|
task->abort();
|
||||||
task = nullptr;
|
|
||||||
emitAborted();
|
emitAborted();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (buildZipFuture.isRunning()) {
|
|
||||||
buildZipFuture.cancel();
|
|
||||||
// NOTE: Here we don't do `emitAborted()` because it will be done when `buildZipFuture` actually cancels, which may not occur
|
|
||||||
// immediately.
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -336,89 +328,40 @@ void FlamePackExportTask::buildZip()
|
|||||||
setStatus(tr("Adding files..."));
|
setStatus(tr("Adding files..."));
|
||||||
setProgress(4, 5);
|
setProgress(4, 5);
|
||||||
|
|
||||||
buildZipFuture = QtConcurrent::run(QThreadPool::globalInstance(), [this]() {
|
auto zipTask = makeShared<MMCZip::ExportToZipTask>(output, gameRoot, files, "overrides/", true);
|
||||||
QuaZip zip(output);
|
zipTask->addExtraFile("manifest.json", generateIndex());
|
||||||
if (!zip.open(QuaZip::mdCreate)) {
|
zipTask->addExtraFile("modlist.html", generateHTML());
|
||||||
QFile::remove(output);
|
|
||||||
return BuildZipResult(tr("Could not create file"));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (buildZipFuture.isCanceled())
|
QStringList exclude;
|
||||||
return BuildZipResult();
|
std::transform(resolvedFiles.keyBegin(), resolvedFiles.keyEnd(), std::back_insert_iterator(exclude),
|
||||||
|
[this](QString file) { return gameRoot.relativeFilePath(file); });
|
||||||
|
zipTask->setExcludeFiles(exclude);
|
||||||
|
|
||||||
QuaZipFile indexFile(&zip);
|
auto progressStep = std::make_shared<TaskStepProgress>();
|
||||||
if (!indexFile.open(QIODevice::WriteOnly, QuaZipNewInfo("manifest.json"))) {
|
connect(zipTask.get(), &Task::finished, this, [this, progressStep] {
|
||||||
QFile::remove(output);
|
|
||||||
return BuildZipResult(tr("Could not create index"));
|
|
||||||
}
|
|
||||||
indexFile.write(generateIndex());
|
|
||||||
|
|
||||||
QuaZipFile modlist(&zip);
|
|
||||||
if (!modlist.open(QIODevice::WriteOnly, QuaZipNewInfo("modlist.html"))) {
|
|
||||||
QFile::remove(output);
|
|
||||||
return BuildZipResult(tr("Could not create index"));
|
|
||||||
}
|
|
||||||
QString content = "";
|
|
||||||
for (auto mod : resolvedFiles) {
|
|
||||||
if (mod.isMod) {
|
|
||||||
content += QString(TEMPLATE)
|
|
||||||
.replace("{name}", mod.name.toHtmlEscaped())
|
|
||||||
.replace("{url}", ModPlatform::getMetaURL(ModPlatform::ResourceProvider::FLAME, mod.addonId).toHtmlEscaped())
|
|
||||||
.replace("{authors}", !mod.authors.isEmpty() ? QString(" (by %1)").arg(mod.authors).toHtmlEscaped() : "");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
content = "<ul>" + content + "</ul>";
|
|
||||||
modlist.write(content.toUtf8());
|
|
||||||
|
|
||||||
auto progressStep = std::make_shared<TaskStepProgress>();
|
|
||||||
|
|
||||||
size_t progress = 0;
|
|
||||||
for (const QFileInfo& file : files) {
|
|
||||||
if (buildZipFuture.isCanceled()) {
|
|
||||||
QFile::remove(output);
|
|
||||||
progressStep->state = TaskStepState::Failed;
|
|
||||||
stepProgress(*progressStep);
|
|
||||||
return BuildZipResult();
|
|
||||||
}
|
|
||||||
progressStep->update(progress, files.length());
|
|
||||||
stepProgress(*progressStep);
|
|
||||||
|
|
||||||
const QString relative = gameRoot.relativeFilePath(file.absoluteFilePath());
|
|
||||||
if (!resolvedFiles.contains(file.absoluteFilePath()) &&
|
|
||||||
!JlCompress::compressFile(&zip, file.absoluteFilePath(), "overrides/" + relative)) {
|
|
||||||
QFile::remove(output);
|
|
||||||
return BuildZipResult(tr("Could not read and compress %1").arg(relative));
|
|
||||||
}
|
|
||||||
progress++;
|
|
||||||
}
|
|
||||||
|
|
||||||
zip.close();
|
|
||||||
|
|
||||||
if (zip.getZipError() != 0) {
|
|
||||||
QFile::remove(output);
|
|
||||||
progressStep->state = TaskStepState::Failed;
|
|
||||||
stepProgress(*progressStep);
|
|
||||||
return BuildZipResult(tr("A zip error occurred"));
|
|
||||||
}
|
|
||||||
progressStep->state = TaskStepState::Succeeded;
|
progressStep->state = TaskStepState::Succeeded;
|
||||||
stepProgress(*progressStep);
|
stepProgress(*progressStep);
|
||||||
return BuildZipResult();
|
|
||||||
});
|
});
|
||||||
connect(&buildZipWatcher, &QFutureWatcher<BuildZipResult>::finished, this, &FlamePackExportTask::finish);
|
|
||||||
buildZipWatcher.setFuture(buildZipFuture);
|
|
||||||
}
|
|
||||||
|
|
||||||
void FlamePackExportTask::finish()
|
connect(zipTask.get(), &Task::succeeded, this, &FlamePackExportTask::emitSucceeded);
|
||||||
{
|
connect(zipTask.get(), &Task::aborted, this, &FlamePackExportTask::emitAborted);
|
||||||
if (buildZipFuture.isCanceled())
|
connect(zipTask.get(), &Task::failed, this, [this, progressStep](QString reason) {
|
||||||
emitAborted();
|
progressStep->state = TaskStepState::Failed;
|
||||||
else {
|
stepProgress(*progressStep);
|
||||||
const BuildZipResult result = buildZipFuture.result();
|
emitFailed(reason);
|
||||||
if (result.has_value())
|
});
|
||||||
emitFailed(result.value());
|
connect(zipTask.get(), &Task::stepProgress, this, &FlamePackExportTask::propagateStepProgress);
|
||||||
else
|
|
||||||
emitSucceeded();
|
connect(zipTask.get(), &Task::progress, this, [this, progressStep](qint64 current, qint64 total) {
|
||||||
}
|
progressStep->update(current, total);
|
||||||
|
stepProgress(*progressStep);
|
||||||
|
});
|
||||||
|
connect(zipTask.get(), &Task::status, this, [this, progressStep](QString status) {
|
||||||
|
progressStep->status = status;
|
||||||
|
stepProgress(*progressStep);
|
||||||
|
});
|
||||||
|
task.reset(zipTask);
|
||||||
|
zipTask->start();
|
||||||
}
|
}
|
||||||
|
|
||||||
QByteArray FlamePackExportTask::generateIndex()
|
QByteArray FlamePackExportTask::generateIndex()
|
||||||
@ -471,3 +414,18 @@ QByteArray FlamePackExportTask::generateIndex()
|
|||||||
|
|
||||||
return QJsonDocument(obj).toJson(QJsonDocument::Compact);
|
return QJsonDocument(obj).toJson(QJsonDocument::Compact);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QByteArray FlamePackExportTask::generateHTML()
|
||||||
|
{
|
||||||
|
QString content = "";
|
||||||
|
for (auto mod : resolvedFiles) {
|
||||||
|
if (mod.isMod) {
|
||||||
|
content += QString(TEMPLATE)
|
||||||
|
.replace("{name}", mod.name.toHtmlEscaped())
|
||||||
|
.replace("{url}", ModPlatform::getMetaURL(ModPlatform::ResourceProvider::FLAME, mod.addonId).toHtmlEscaped())
|
||||||
|
.replace("{authors}", !mod.authors.isEmpty() ? QString(" (by %1)").arg(mod.authors).toHtmlEscaped() : "");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
content = "<ul>" + content + "</ul>";
|
||||||
|
return content.toUtf8();
|
||||||
|
}
|
@ -19,8 +19,6 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <QFuture>
|
|
||||||
#include <QFutureWatcher>
|
|
||||||
#include "BaseInstance.h"
|
#include "BaseInstance.h"
|
||||||
#include "MMCZip.h"
|
#include "MMCZip.h"
|
||||||
#include "minecraft/MinecraftInstance.h"
|
#include "minecraft/MinecraftInstance.h"
|
||||||
@ -52,7 +50,6 @@ class FlamePackExportTask : public Task {
|
|||||||
const QString output;
|
const QString output;
|
||||||
const MMCZip::FilterFunction filter;
|
const MMCZip::FilterFunction filter;
|
||||||
|
|
||||||
typedef std::optional<QString> BuildZipResult;
|
|
||||||
struct ResolvedFile {
|
struct ResolvedFile {
|
||||||
int addonId;
|
int addonId;
|
||||||
int version;
|
int version;
|
||||||
@ -76,15 +73,13 @@ class FlamePackExportTask : public Task {
|
|||||||
QMap<QString, HashInfo> pendingHashes{};
|
QMap<QString, HashInfo> pendingHashes{};
|
||||||
QMap<QString, ResolvedFile> resolvedFiles{};
|
QMap<QString, ResolvedFile> resolvedFiles{};
|
||||||
Task::Ptr task;
|
Task::Ptr task;
|
||||||
QFuture<BuildZipResult> buildZipFuture;
|
|
||||||
QFutureWatcher<BuildZipResult> buildZipWatcher;
|
|
||||||
|
|
||||||
void collectFiles();
|
void collectFiles();
|
||||||
void collectHashes();
|
void collectHashes();
|
||||||
void makeApiRequest();
|
void makeApiRequest();
|
||||||
void getProjectsInfo();
|
void getProjectsInfo();
|
||||||
void buildZip();
|
void buildZip();
|
||||||
void finish();
|
|
||||||
|
|
||||||
QByteArray generateIndex();
|
QByteArray generateIndex();
|
||||||
|
QByteArray generateHTML();
|
||||||
};
|
};
|
||||||
|
@ -55,20 +55,11 @@ void ModrinthPackExportTask::executeTask()
|
|||||||
|
|
||||||
bool ModrinthPackExportTask::abort()
|
bool ModrinthPackExportTask::abort()
|
||||||
{
|
{
|
||||||
if (task != nullptr) {
|
if (task) {
|
||||||
task->abort();
|
task->abort();
|
||||||
task = nullptr;
|
|
||||||
emitAborted();
|
emitAborted();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (buildZipFuture.isRunning()) {
|
|
||||||
buildZipFuture.cancel();
|
|
||||||
// NOTE: Here we don't do `emitAborted()` because it will be done when `buildZipFuture` actually cancels, which may not occur
|
|
||||||
// immediately.
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -205,63 +196,36 @@ void ModrinthPackExportTask::buildZip()
|
|||||||
{
|
{
|
||||||
setStatus(tr("Adding files..."));
|
setStatus(tr("Adding files..."));
|
||||||
|
|
||||||
buildZipFuture = QtConcurrent::run(QThreadPool::globalInstance(), [this]() {
|
auto zipTask = makeShared<MMCZip::ExportToZipTask>(output, gameRoot, files, "overrides/", true);
|
||||||
QuaZip zip(output);
|
zipTask->addExtraFile("modrinth.index.json", generateIndex());
|
||||||
if (!zip.open(QuaZip::mdCreate)) {
|
|
||||||
QFile::remove(output);
|
|
||||||
return BuildZipResult(tr("Could not create file"));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (buildZipFuture.isCanceled())
|
zipTask->setExcludeFiles(resolvedFiles.keys());
|
||||||
return BuildZipResult();
|
|
||||||
|
|
||||||
QuaZipFile indexFile(&zip);
|
auto progressStep = std::make_shared<TaskStepProgress>();
|
||||||
if (!indexFile.open(QIODevice::WriteOnly, QuaZipNewInfo("modrinth.index.json"))) {
|
connect(zipTask.get(), &Task::finished, this, [this, progressStep] {
|
||||||
QFile::remove(output);
|
progressStep->state = TaskStepState::Succeeded;
|
||||||
return BuildZipResult(tr("Could not create index"));
|
stepProgress(*progressStep);
|
||||||
}
|
|
||||||
indexFile.write(generateIndex());
|
|
||||||
|
|
||||||
size_t progress = 0;
|
|
||||||
for (const QFileInfo& file : files) {
|
|
||||||
if (buildZipFuture.isCanceled()) {
|
|
||||||
QFile::remove(output);
|
|
||||||
return BuildZipResult();
|
|
||||||
}
|
|
||||||
|
|
||||||
setProgress(progress, files.length());
|
|
||||||
const QString relative = gameRoot.relativeFilePath(file.absoluteFilePath());
|
|
||||||
if (!resolvedFiles.contains(relative) && !JlCompress::compressFile(&zip, file.absoluteFilePath(), "overrides/" + relative)) {
|
|
||||||
QFile::remove(output);
|
|
||||||
return BuildZipResult(tr("Could not read and compress %1").arg(relative));
|
|
||||||
}
|
|
||||||
progress++;
|
|
||||||
}
|
|
||||||
|
|
||||||
zip.close();
|
|
||||||
|
|
||||||
if (zip.getZipError() != 0) {
|
|
||||||
QFile::remove(output);
|
|
||||||
return BuildZipResult(tr("A zip error occurred"));
|
|
||||||
}
|
|
||||||
|
|
||||||
return BuildZipResult();
|
|
||||||
});
|
});
|
||||||
connect(&buildZipWatcher, &QFutureWatcher<BuildZipResult>::finished, this, &ModrinthPackExportTask::finish);
|
|
||||||
buildZipWatcher.setFuture(buildZipFuture);
|
|
||||||
}
|
|
||||||
|
|
||||||
void ModrinthPackExportTask::finish()
|
connect(zipTask.get(), &Task::succeeded, this, &ModrinthPackExportTask::emitSucceeded);
|
||||||
{
|
connect(zipTask.get(), &Task::aborted, this, &ModrinthPackExportTask::emitAborted);
|
||||||
if (buildZipFuture.isCanceled())
|
connect(zipTask.get(), &Task::failed, this, [this, progressStep](QString reason) {
|
||||||
emitAborted();
|
progressStep->state = TaskStepState::Failed;
|
||||||
else {
|
stepProgress(*progressStep);
|
||||||
const BuildZipResult result = buildZipFuture.result();
|
emitFailed(reason);
|
||||||
if (result.has_value())
|
});
|
||||||
emitFailed(result.value());
|
connect(zipTask.get(), &Task::stepProgress, this, &ModrinthPackExportTask::propagateStepProgress);
|
||||||
else
|
|
||||||
emitSucceeded();
|
connect(zipTask.get(), &Task::progress, this, [this, progressStep](qint64 current, qint64 total) {
|
||||||
}
|
progressStep->update(current, total);
|
||||||
|
stepProgress(*progressStep);
|
||||||
|
});
|
||||||
|
connect(zipTask.get(), &Task::status, this, [this, progressStep](QString status) {
|
||||||
|
progressStep->status = status;
|
||||||
|
stepProgress(*progressStep);
|
||||||
|
});
|
||||||
|
task.reset(zipTask);
|
||||||
|
zipTask->start();
|
||||||
}
|
}
|
||||||
|
|
||||||
QByteArray ModrinthPackExportTask::generateIndex()
|
QByteArray ModrinthPackExportTask::generateIndex()
|
||||||
|
@ -56,22 +56,17 @@ class ModrinthPackExportTask : public Task {
|
|||||||
const QString output;
|
const QString output;
|
||||||
const MMCZip::FilterFunction filter;
|
const MMCZip::FilterFunction filter;
|
||||||
|
|
||||||
typedef std::optional<QString> BuildZipResult;
|
|
||||||
|
|
||||||
ModrinthAPI api;
|
ModrinthAPI api;
|
||||||
QFileInfoList files;
|
QFileInfoList files;
|
||||||
QMap<QString, QString> pendingHashes;
|
QMap<QString, QString> pendingHashes;
|
||||||
QMap<QString, ResolvedFile> resolvedFiles;
|
QMap<QString, ResolvedFile> resolvedFiles;
|
||||||
Task::Ptr task;
|
Task::Ptr task;
|
||||||
QFuture<BuildZipResult> buildZipFuture;
|
|
||||||
QFutureWatcher<BuildZipResult> buildZipWatcher;
|
|
||||||
|
|
||||||
void collectFiles();
|
void collectFiles();
|
||||||
void collectHashes();
|
void collectHashes();
|
||||||
void makeApiRequest();
|
void makeApiRequest();
|
||||||
void parseApiResponse(const std::shared_ptr<QByteArray> response);
|
void parseApiResponse(const std::shared_ptr<QByteArray> response);
|
||||||
void buildZip();
|
void buildZip();
|
||||||
void finish();
|
|
||||||
|
|
||||||
QByteArray generateIndex();
|
QByteArray generateIndex();
|
||||||
};
|
};
|
||||||
|
Loading…
Reference in New Issue
Block a user