Merge pull request #27 from flowln/ftb_install_improve

This commit is contained in:
Sefa Eyeoglu 2022-10-19 13:51:35 +02:00 committed by GitHub
commit 46c57e120f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 129 additions and 114 deletions

View File

@ -9,9 +9,10 @@ Flame::FileResolvingTask::FileResolvingTask(const shared_qobject_ptr<QNetworkAcc
bool Flame::FileResolvingTask::abort()
{
bool aborted = true;
if (m_dljob)
return m_dljob->abort();
return true;
aborted &= m_dljob->abort();
return aborted ? Task::abort() : false;
}
void Flame::FileResolvingTask::executeTask()

View File

@ -65,48 +65,42 @@ void PackInstallTask::executeTask()
void PackInstallTask::downloadPack()
{
setStatus(tr("Downloading zip for %1").arg(m_pack.name));
setAbortable(false);
archivePath = QString("%1/%2/%3").arg(m_pack.dir, m_version.replace(".", "_"), m_pack.file);
auto packoffset = QString("%1/%2/%3").arg(m_pack.dir, m_version.replace(".", "_"), m_pack.file);
auto entry = APPLICATION->metacache()->resolveEntry("FTBPacks", packoffset);
netJobContainer = new NetJob("Download FTB Pack", m_network);
entry->setStale(true);
QString url;
if(m_pack.type == PackType::Private)
{
url = QString(BuildConfig.LEGACY_FTB_CDN_BASE_URL + "privatepacks/%1").arg(packoffset);
if (m_pack.type == PackType::Private) {
url = QString(BuildConfig.LEGACY_FTB_CDN_BASE_URL + "privatepacks/%1").arg(archivePath);
} else {
url = QString(BuildConfig.LEGACY_FTB_CDN_BASE_URL + "modpacks/%1").arg(archivePath);
}
else
{
url = QString(BuildConfig.LEGACY_FTB_CDN_BASE_URL + "modpacks/%1").arg(packoffset);
}
netJobContainer->addNetAction(Net::Download::makeCached(url, entry));
archivePath = entry->getFullPath();
netJobContainer->addNetAction(Net::Download::makeFile(url, archivePath));
connect(netJobContainer.get(), &NetJob::succeeded, this, &PackInstallTask::onDownloadSucceeded);
connect(netJobContainer.get(), &NetJob::failed, this, &PackInstallTask::onDownloadFailed);
connect(netJobContainer.get(), &NetJob::progress, this, &PackInstallTask::onDownloadProgress);
connect(netJobContainer.get(), &NetJob::aborted, this, &PackInstallTask::onDownloadAborted);
netJobContainer->start();
setAbortable(true);
progress(1, 4);
}
void PackInstallTask::onDownloadSucceeded()
{
abortable = false;
unzip();
}
void PackInstallTask::onDownloadFailed(QString reason)
{
abortable = false;
emitFailed(reason);
}
void PackInstallTask::onDownloadProgress(qint64 current, qint64 total)
{
abortable = true;
progress(current, total * 4);
setStatus(tr("Downloading zip for %1 (%2%)").arg(m_pack.name).arg(current / 10));
}
@ -118,8 +112,10 @@ void PackInstallTask::onDownloadAborted()
void PackInstallTask::unzip()
{
progress(2, 4);
setStatus(tr("Extracting modpack"));
setAbortable(false);
progress(2, 4);
QDir extractDir(m_stagingPath);
m_packZip.reset(new QuaZip(archivePath));
@ -151,8 +147,8 @@ void PackInstallTask::onUnzipCanceled()
void PackInstallTask::install()
{
progress(3, 4);
setStatus(tr("Installing modpack"));
progress(3, 4);
QDir unzipMcDir(m_stagingPath + "/unzip/minecraft");
if(unzipMcDir.exists())
{
@ -247,11 +243,12 @@ void PackInstallTask::install()
bool PackInstallTask::abort()
{
if(abortable)
{
return netJobContainer->abort();
}
if (!canAbort()) {
return false;
}
netJobContainer->abort();
return InstanceTask::abort();
}
}

View File

@ -58,6 +58,9 @@ PackInstallTask::PackInstallTask(Modpack pack, QString version, QWidget* parent)
bool PackInstallTask::abort()
{
if (!canAbort())
return false;
bool aborted = true;
if (m_net_job)
@ -65,15 +68,13 @@ bool PackInstallTask::abort()
if (m_mod_id_resolver_task)
aborted &= m_mod_id_resolver_task->abort();
if (aborted)
emitAborted();
return aborted;
return aborted ? InstanceTask::abort() : false;
}
void PackInstallTask::executeTask()
{
setStatus(tr("Getting the manifest..."));
setAbortable(false);
// Find pack version
auto version_it = std::find_if(m_pack.versions.constBegin(), m_pack.versions.constEnd(),
@ -93,10 +94,12 @@ void PackInstallTask::executeTask()
QObject::connect(netJob, &NetJob::succeeded, this, &PackInstallTask::onManifestDownloadSucceeded);
QObject::connect(netJob, &NetJob::failed, this, &PackInstallTask::onManifestDownloadFailed);
QObject::connect(netJob, &NetJob::aborted, this, &PackInstallTask::abort);
QObject::connect(netJob, &NetJob::progress, this, &PackInstallTask::setProgress);
m_net_job = netJob;
setAbortable(true);
netJob->start();
}
@ -130,6 +133,7 @@ void PackInstallTask::onManifestDownloadSucceeded()
void PackInstallTask::resolveMods()
{
setStatus(tr("Resolving mods..."));
setAbortable(false);
setProgress(0, 100);
m_file_id_map.clear();
@ -162,15 +166,16 @@ void PackInstallTask::resolveMods()
connect(m_mod_id_resolver_task.get(), &Flame::FileResolvingTask::succeeded, this, &PackInstallTask::onResolveModsSucceeded);
connect(m_mod_id_resolver_task.get(), &Flame::FileResolvingTask::failed, this, &PackInstallTask::onResolveModsFailed);
connect(m_mod_id_resolver_task.get(), &Flame::FileResolvingTask::aborted, this, &PackInstallTask::abort);
connect(m_mod_id_resolver_task.get(), &Flame::FileResolvingTask::progress, this, &PackInstallTask::setProgress);
setAbortable(true);
m_mod_id_resolver_task->start();
}
void PackInstallTask::onResolveModsSucceeded()
{
m_abortable = false;
QString text;
QList<QUrl> urls;
auto anyBlocked = false;
@ -209,94 +214,23 @@ void PackInstallTask::onResolveModsSucceeded()
urls);
if (message_dialog->exec() == QDialog::Accepted)
downloadPack();
createInstance();
else
abort();
} else {
downloadPack();
createInstance();
}
}
void PackInstallTask::downloadPack()
void PackInstallTask::createInstance()
{
setStatus(tr("Downloading mods..."));
setAbortable(false);
auto* jobPtr = new NetJob(tr("Mod download"), APPLICATION->network());
for (auto const& file : m_version.files) {
if (file.serverOnly || file.url.isEmpty())
continue;
QFileInfo file_info(file.name);
auto cacheName = file_info.completeBaseName() + "-" + file.sha1 + "." + file_info.suffix();
auto entry = APPLICATION->metacache()->resolveEntry("ModpacksCHPacks", cacheName);
entry->setStale(true);
auto relpath = FS::PathCombine("minecraft", file.path, file.name);
auto path = FS::PathCombine(m_stagingPath, relpath);
if (m_files_to_copy.contains(path)) {
qWarning() << "Ignoring" << file.url << "as a file of that path is already downloading.";
continue;
}
qDebug() << "Will download" << file.url << "to" << path;
m_files_to_copy[path] = entry->getFullPath();
auto dl = Net::Download::makeCached(file.url, entry);
if (!file.sha1.isEmpty()) {
auto rawSha1 = QByteArray::fromHex(file.sha1.toLatin1());
dl->addValidator(new Net::ChecksumValidator(QCryptographicHash::Sha1, rawSha1));
}
jobPtr->addNetAction(dl);
}
connect(jobPtr, &NetJob::succeeded, this, &PackInstallTask::onModDownloadSucceeded);
connect(jobPtr, &NetJob::failed, this, &PackInstallTask::onModDownloadFailed);
connect(jobPtr, &NetJob::progress, this, &PackInstallTask::setProgress);
m_net_job = jobPtr;
jobPtr->start();
m_abortable = true;
}
void PackInstallTask::onModDownloadSucceeded()
{
m_net_job.reset();
install();
}
void PackInstallTask::install()
{
setStatus(tr("Copying modpack files..."));
setProgress(0, m_files_to_copy.size());
QCoreApplication::processEvents();
m_abortable = false;
int i = 0;
for (auto iter = m_files_to_copy.constBegin(); iter != m_files_to_copy.constEnd(); iter++) {
auto& to = iter.key();
auto& from = iter.value();
FS::copy fileCopyOperation(from, to);
if (!fileCopyOperation()) {
qWarning() << "Failed to copy" << from << "to" << to;
emitFailed(tr("Failed to copy files"));
return;
}
setProgress(i++, m_files_to_copy.size());
QCoreApplication::processEvents();
}
setStatus(tr("Installing modpack..."));
setStatus(tr("Creating the instance..."));
QCoreApplication::processEvents();
auto instanceConfigPath = FS::PathCombine(m_stagingPath, "instance.cfg");
auto instanceSettings = std::make_shared<INISettingsObject>(instanceConfigPath);
instanceSettings->suspendSave();
MinecraftInstance instance(m_globalSettings, instanceSettings, m_stagingPath);
auto components = instance.getPackProfile();
@ -337,8 +271,55 @@ void PackInstallTask::install()
instance.setName(name());
instance.setIconKey(m_instIcon);
instance.setManagedPack("modpacksch", QString::number(m_pack.id), m_pack.name, QString::number(m_version.id), m_version.name);
instanceSettings->resumeSave();
instance.saveNow();
onCreateInstanceSucceeded();
}
void PackInstallTask::onCreateInstanceSucceeded()
{
downloadPack();
}
void PackInstallTask::downloadPack()
{
setStatus(tr("Downloading mods..."));
setAbortable(false);
auto* jobPtr = new NetJob(tr("Mod download"), APPLICATION->network());
for (auto const& file : m_version.files) {
if (file.serverOnly || file.url.isEmpty())
continue;
auto path = FS::PathCombine(m_stagingPath, ".minecraft", file.path, file.name);
qDebug() << "Will try to download" << file.url << "to" << path;
QFileInfo file_info(file.name);
auto dl = Net::Download::makeFile(file.url, path);
if (!file.sha1.isEmpty()) {
auto rawSha1 = QByteArray::fromHex(file.sha1.toLatin1());
dl->addValidator(new Net::ChecksumValidator(QCryptographicHash::Sha1, rawSha1));
}
jobPtr->addNetAction(dl);
}
connect(jobPtr, &NetJob::succeeded, this, &PackInstallTask::onModDownloadSucceeded);
connect(jobPtr, &NetJob::failed, this, &PackInstallTask::onModDownloadFailed);
connect(jobPtr, &NetJob::aborted, this, &PackInstallTask::abort);
connect(jobPtr, &NetJob::progress, this, &PackInstallTask::setProgress);
m_net_job = jobPtr;
setAbortable(true);
jobPtr->start();
}
void PackInstallTask::onModDownloadSucceeded()
{
m_net_job.reset();
emitSucceeded();
}
@ -352,6 +333,10 @@ void PackInstallTask::onResolveModsFailed(QString reason)
m_net_job.reset();
emitFailed(reason);
}
void PackInstallTask::onCreateInstanceFailed(QString reason)
{
emitFailed(reason);
}
void PackInstallTask::onModDownloadFailed(QString reason)
{
m_net_job.reset();

View File

@ -56,7 +56,6 @@ public:
explicit PackInstallTask(Modpack pack, QString version, QWidget* parent = nullptr);
~PackInstallTask() override = default;
bool canAbort() const override { return m_abortable; }
bool abort() override;
protected:
@ -65,20 +64,20 @@ protected:
private slots:
void onManifestDownloadSucceeded();
void onResolveModsSucceeded();
void onCreateInstanceSucceeded();
void onModDownloadSucceeded();
void onManifestDownloadFailed(QString reason);
void onResolveModsFailed(QString reason);
void onCreateInstanceFailed(QString reason);
void onModDownloadFailed(QString reason);
private:
void resolveMods();
void createInstance();
void downloadPack();
void install();
private:
bool m_abortable = true;
NetJob::Ptr m_net_job = nullptr;
shared_qobject_ptr<Flame::FileResolvingTask> m_mod_id_resolver_task = nullptr;

View File

@ -139,6 +139,10 @@ NewInstanceDialog::NewInstanceDialog(const QString & initialGroup, const QString
void NewInstanceDialog::reject()
{
APPLICATION->settings()->set("NewInstanceGeometry", saveGeometry().toBase64());
// This is just so that the pages get the close() call and can react to it, if needed.
m_container->prepareToClose();
QDialog::reject();
}
@ -146,6 +150,10 @@ void NewInstanceDialog::accept()
{
APPLICATION->settings()->set("NewInstanceGeometry", saveGeometry().toBase64());
importIconNow();
// This is just so that the pages get the close() call and can react to it, if needed.
m_container->prepareToClose();
QDialog::accept();
}

View File

@ -25,6 +25,7 @@ ProgressDialog::ProgressDialog(QWidget* parent) : QDialog(parent), ui(new Ui::Pr
{
ui->setupUi(this);
this->setWindowFlags(this->windowFlags() & ~Qt::WindowContextHelpButtonHint);
setAttribute(Qt::WidgetAttribute::WA_QuitOnClose, true);
setSkipButton(false);
changeProgress(0, 100);
}
@ -67,7 +68,7 @@ int ProgressDialog::execWithTask(Task* task)
return QDialog::DialogCode::Accepted;
}
QDialog::DialogCode result;
QDialog::DialogCode result {};
if (handleImmediateResult(result)) {
return result;
}
@ -80,7 +81,7 @@ int ProgressDialog::execWithTask(Task* task)
connect(task, &Task::stepStatus, this, &ProgressDialog::changeStatus);
connect(task, &Task::progress, this, &ProgressDialog::changeProgress);
connect(task, &Task::aborted, [this] { QDialog::reject(); });
connect(task, &Task::aborted, this, &ProgressDialog::hide);
connect(task, &Task::abortStatusChanged, ui->skipButton, &QPushButton::setEnabled);
m_is_multi_step = task->isMultiStep();

View File

@ -103,6 +103,8 @@ void ListModel::getLogo(const QString &logo, const QString &logoUrl, LogoCallbac
void ListModel::request()
{
m_aborted = false;
beginResetModel();
modpacks.clear();
endResetModel();
@ -117,6 +119,12 @@ void ListModel::request()
QObject::connect(netJob, &NetJob::failed, this, &ListModel::requestFailed);
}
void ListModel::abortRequest()
{
m_aborted = jobPtr->abort();
jobPtr.reset();
}
void ListModel::requestFinished()
{
jobPtr.reset();
@ -162,6 +170,9 @@ void ListModel::requestPack()
void ListModel::packRequestFinished()
{
if (!jobPtr || m_aborted)
return;
jobPtr.reset();
remainingPacks.removeOne(currentPack);

View File

@ -47,9 +47,13 @@ public:
QVariant data(const QModelIndex &index, int role) const override;
void request();
void abortRequest();
void getLogo(const QString &logo, const QString &logoUrl, LogoCallback callback);
[[nodiscard]] bool isMakingRequest() const { return jobPtr.get(); }
[[nodiscard]] bool wasAborted() const { return m_aborted; }
private slots:
void requestFinished();
void requestFailed(QString reason);
@ -65,6 +69,8 @@ private:
void requestLogo(QString file, QString url);
private:
bool m_aborted = false;
QList<ModpacksCH::Modpack> modpacks;
LogoMap m_logoMap;

View File

@ -105,7 +105,7 @@ void FtbPage::retranslate()
void FtbPage::openedImpl()
{
if(!initialised)
if(!initialised || listModel->wasAborted())
{
listModel->request();
initialised = true;
@ -114,6 +114,12 @@ void FtbPage::openedImpl()
suggestCurrent();
}
void FtbPage::closedImpl()
{
if (listModel->isMakingRequest())
listModel->abortRequest();
}
void FtbPage::suggestCurrent()
{
if(!isOpened)

View File

@ -78,6 +78,7 @@ public:
void retranslate() override;
void openedImpl() override;
void closedImpl() override;
bool eventFilter(QObject * watched, QEvent * event) override;