aboutsummaryrefslogtreecommitdiff
path: root/launcher
diff options
context:
space:
mode:
authorflow <thiagodonato300@gmail.com>2022-04-21 22:12:14 -0300
committerflow <thiagodonato300@gmail.com>2022-05-12 18:11:49 -0300
commit8c8eabf7ac1920b47792b26790f3646cb6693ec0 (patch)
tree4cb5fca254ad911b52f7aaf4b5af6009ea6f6329 /launcher
parent649b8ac7c6e12fcf91d204f908e027d3bfbb6a2a (diff)
downloadPrismLauncher-8c8eabf7ac1920b47792b26790f3646cb6693ec0.tar.gz
PrismLauncher-8c8eabf7ac1920b47792b26790f3646cb6693ec0.tar.bz2
PrismLauncher-8c8eabf7ac1920b47792b26790f3646cb6693ec0.zip
refactor: organize a little more the code in launcher/net/
This also reduces some code duplication by using some Task logic in NetAction.
Diffstat (limited to 'launcher')
-rw-r--r--launcher/InstanceImportTask.cpp14
-rw-r--r--launcher/minecraft/AssetsUtils.cpp2
-rw-r--r--launcher/net/ByteArraySink.h67
-rw-r--r--launcher/net/Download.cpp60
-rw-r--r--launcher/net/Download.h14
-rw-r--r--launcher/net/FileSink.cpp50
-rw-r--r--launcher/net/FileSink.h36
-rw-r--r--launcher/net/MetaCacheSink.cpp22
-rw-r--r--launcher/net/MetaCacheSink.h27
-rw-r--r--launcher/net/NetAction.h127
-rw-r--r--launcher/net/NetJob.cpp270
-rw-r--r--launcher/net/NetJob.h109
-rw-r--r--launcher/net/Sink.h54
-rw-r--r--launcher/screenshots/ImgurAlbumCreation.cpp15
-rw-r--r--launcher/screenshots/ImgurAlbumCreation.h12
-rw-r--r--launcher/screenshots/ImgurUpload.cpp13
-rw-r--r--launcher/screenshots/ImgurUpload.h2
-rw-r--r--launcher/tasks/Task.h4
-rw-r--r--launcher/translations/TranslationsModel.cpp2
19 files changed, 433 insertions, 467 deletions
diff --git a/launcher/InstanceImportTask.cpp b/launcher/InstanceImportTask.cpp
index 1a13c997..fc3432c1 100644
--- a/launcher/InstanceImportTask.cpp
+++ b/launcher/InstanceImportTask.cpp
@@ -14,27 +14,25 @@
*/
#include "InstanceImportTask.h"
+#include <QtConcurrentRun>
+#include "Application.h"
#include "BaseInstance.h"
#include "FileSystem.h"
-#include "Application.h"
#include "MMCZip.h"
#include "NullInstance.h"
-#include "settings/INISettingsObject.h"
+#include "icons/IconList.h"
#include "icons/IconUtils.h"
-#include <QtConcurrentRun>
+#include "settings/INISettingsObject.h"
// FIXME: this does not belong here, it's Minecraft/Flame specific
+#include <quazip/quazipdir.h>
+#include "Json.h"
#include "minecraft/MinecraftInstance.h"
#include "minecraft/PackProfile.h"
#include "modplatform/flame/FileResolvingTask.h"
#include "modplatform/flame/PackManifest.h"
-#include "Json.h"
-#include <quazip/quazipdir.h>
#include "modplatform/technic/TechnicPackProcessor.h"
-#include "icons/IconList.h"
-#include "Application.h"
-
InstanceImportTask::InstanceImportTask(const QUrl sourceUrl)
{
m_sourceUrl = sourceUrl;
diff --git a/launcher/minecraft/AssetsUtils.cpp b/launcher/minecraft/AssetsUtils.cpp
index 7290aeb4..281f730f 100644
--- a/launcher/minecraft/AssetsUtils.cpp
+++ b/launcher/minecraft/AssetsUtils.cpp
@@ -297,7 +297,7 @@ NetAction::Ptr AssetObject::getDownloadAction()
auto rawHash = QByteArray::fromHex(hash.toLatin1());
objectDL->addValidator(new Net::ChecksumValidator(QCryptographicHash::Sha1, rawHash));
}
- objectDL->m_total_progress = size;
+ objectDL->setProgress(objectDL->getProgress(), size);
return objectDL;
}
return nullptr;
diff --git a/launcher/net/ByteArraySink.h b/launcher/net/ByteArraySink.h
index 20e6764c..75a66574 100644
--- a/launcher/net/ByteArraySink.h
+++ b/launcher/net/ByteArraySink.h
@@ -3,60 +3,59 @@
#include "Sink.h"
namespace Net {
+
/*
* Sink object for downloads that uses an external QByteArray it doesn't own as a target.
*/
-class ByteArraySink : public Sink
-{
-public:
- ByteArraySink(QByteArray *output)
- :m_output(output)
- {
- // nil
- };
+class ByteArraySink : public Sink {
+ public:
+ ByteArraySink(QByteArray* output) : m_output(output){};
- virtual ~ByteArraySink()
- {
- // nil
- }
+ virtual ~ByteArraySink() = default;
-public:
- JobStatus init(QNetworkRequest & request) override
+ public:
+ auto init(QNetworkRequest& request) -> Task::State override
{
+ if(!m_output)
+ return Task::State::Failed;
+
m_output->clear();
- if(initAllValidators(request))
- return Job_InProgress;
- return Job_Failed;
+ if (initAllValidators(request))
+ return Task::State::Running;
+ return Task::State::Failed;
};
- JobStatus write(QByteArray & data) override
+ auto write(QByteArray& data) -> Task::State override
{
+ if(!m_output)
+ return Task::State::Failed;
+
m_output->append(data);
- if(writeAllValidators(data))
- return Job_InProgress;
- return Job_Failed;
+ if (writeAllValidators(data))
+ return Task::State::Running;
+ return Task::State::Failed;
}
- JobStatus abort() override
+ auto abort() -> Task::State override
{
+ if(!m_output)
+ return Task::State::Failed;
+
m_output->clear();
failAllValidators();
- return Job_Failed;
+ return Task::State::Failed;
}
- JobStatus finalize(QNetworkReply &reply) override
+ auto finalize(QNetworkReply& reply) -> Task::State override
{
- if(finalizeAllValidators(reply))
- return Job_Finished;
- return Job_Failed;
+ if (finalizeAllValidators(reply))
+ return Task::State::Succeeded;
+ return Task::State::Failed;
}
- bool hasLocalData() override
- {
- return false;
- }
+ auto hasLocalData() -> bool override { return false; }
-private:
- QByteArray * m_output;
+ private:
+ QByteArray* m_output;
};
-}
+} // namespace Net
diff --git a/launcher/net/Download.cpp b/launcher/net/Download.cpp
index 65cc8f67..5b5a04db 100644
--- a/launcher/net/Download.cpp
+++ b/launcher/net/Download.cpp
@@ -30,7 +30,7 @@ namespace Net {
Download::Download() : NetAction()
{
- m_status = Job_NotStarted;
+ m_state = State::Inactive;
}
Download::Ptr Download::makeCached(QUrl url, MetaEntryPtr entry, Options options)
@@ -68,29 +68,29 @@ void Download::addValidator(Validator* v)
m_sink->addValidator(v);
}
-void Download::startImpl()
+void Download::executeTask()
{
- if (m_status == Job_Aborted) {
+ if (getState() == Task::State::AbortedByUser) {
qWarning() << "Attempt to start an aborted Download:" << m_url.toString();
emit aborted(m_index_within_job);
return;
}
+
QNetworkRequest request(m_url);
- m_status = m_sink->init(request);
- switch (m_status) {
- case Job_Finished:
+ m_state = m_sink->init(request);
+ switch (m_state) {
+ case State::Succeeded:
emit succeeded(m_index_within_job);
qDebug() << "Download cache hit " << m_url.toString();
return;
- case Job_InProgress:
+ case State::Running:
qDebug() << "Downloading " << m_url.toString();
break;
- case Job_Failed_Proceed: // this is meaningless in this context. We do need a sink.
- case Job_NotStarted:
- case Job_Failed:
+ case State::Inactive:
+ case State::Failed:
emit failed(m_index_within_job);
return;
- case Job_Aborted:
+ case State::AbortedByUser:
return;
}
@@ -111,8 +111,7 @@ void Download::startImpl()
void Download::downloadProgress(qint64 bytesReceived, qint64 bytesTotal)
{
- m_total_progress = bytesTotal;
- m_progress = bytesReceived;
+ setProgress(bytesReceived, bytesTotal);
emit netActionProgress(m_index_within_job, bytesReceived, bytesTotal);
}
@@ -120,17 +119,17 @@ void Download::downloadError(QNetworkReply::NetworkError error)
{
if (error == QNetworkReply::OperationCanceledError) {
qCritical() << "Aborted " << m_url.toString();
- m_status = Job_Aborted;
+ m_state = State::AbortedByUser;
} else {
if (m_options & Option::AcceptLocalFiles) {
if (m_sink->hasLocalData()) {
- m_status = Job_Failed_Proceed;
+ m_state = State::Succeeded;
return;
}
}
// error happened during download.
qCritical() << "Failed " << m_url.toString() << " with reason " << error;
- m_status = Job_Failed;
+ m_state = State::Failed;
}
}
@@ -194,7 +193,8 @@ bool Download::handleRedirect()
m_url = QUrl(redirect.toString());
qDebug() << "Following redirect to " << m_url.toString();
- start(m_network);
+ startAction(m_network);
+
return true;
}
@@ -207,19 +207,20 @@ void Download::downloadFinished()
}
// if the download failed before this point ...
- if (m_status == Job_Failed_Proceed) {
+ if (m_state == State::Succeeded) // pretend to succeed so we continue processing :)
+ {
qDebug() << "Download failed but we are allowed to proceed:" << m_url.toString();
m_sink->abort();
m_reply.reset();
emit succeeded(m_index_within_job);
return;
- } else if (m_status == Job_Failed) {
+ } else if (m_state == State::Failed) {
qDebug() << "Download failed in previous step:" << m_url.toString();
m_sink->abort();
m_reply.reset();
emit failed(m_index_within_job);
return;
- } else if (m_status == Job_Aborted) {
+ } else if (m_state == State::AbortedByUser) {
qDebug() << "Download aborted in previous step:" << m_url.toString();
m_sink->abort();
m_reply.reset();
@@ -231,12 +232,12 @@ void Download::downloadFinished()
auto data = m_reply->readAll();
if (data.size()) {
qDebug() << "Writing extra" << data.size() << "bytes to" << m_target_path;
- m_status = m_sink->write(data);
+ m_state = m_sink->write(data);
}
// otherwise, finalize the whole graph
- m_status = m_sink->finalize(*m_reply.get());
- if (m_status != Job_Finished) {
+ m_state = m_sink->finalize(*m_reply.get());
+ if (m_state != State::Succeeded) {
qDebug() << "Download failed to finalize:" << m_url.toString();
m_sink->abort();
m_reply.reset();
@@ -250,10 +251,10 @@ void Download::downloadFinished()
void Download::downloadReadyRead()
{
- if (m_status == Job_InProgress) {
+ if (m_state == State::Running) {
auto data = m_reply->readAll();
- m_status = m_sink->write(data);
- if (m_status == Job_Failed) {
+ m_state = m_sink->write(data);
+ if (m_state == State::Failed) {
qCritical() << "Failed to process response chunk for " << m_target_path;
}
// qDebug() << "Download" << m_url.toString() << "gained" << data.size() << "bytes";
@@ -269,12 +270,7 @@ bool Net::Download::abort()
if (m_reply) {
m_reply->abort();
} else {
- m_status = Job_Aborted;
+ m_state = State::AbortedByUser;
}
return true;
}
-
-bool Net::Download::canAbort()
-{
- return true;
-}
diff --git a/launcher/net/Download.h b/launcher/net/Download.h
index 0f9bfe7f..231ad6a7 100644
--- a/launcher/net/Download.h
+++ b/launcher/net/Download.h
@@ -27,7 +27,7 @@ class Download : public NetAction
{
Q_OBJECT
-public: /* types */
+public:
typedef shared_qobject_ptr<class Download> Ptr;
enum class Option
{
@@ -36,7 +36,7 @@ public: /* types */
};
Q_DECLARE_FLAGS(Options, Option)
-protected: /* con/des */
+protected:
explicit Download();
public:
virtual ~Download(){};
@@ -44,16 +44,16 @@ public:
static Download::Ptr makeByteArray(QUrl url, QByteArray *output, Options options = Option::NoOptions);
static Download::Ptr makeFile(QUrl url, QString path, Options options = Option::NoOptions);
-public: /* methods */
+public:
QString getTargetFilepath()
{
return m_target_path;
}
void addValidator(Validator * v);
bool abort() override;
- bool canAbort() override;
+ bool canAbort() const override { return true; };
-private: /* methods */
+private:
bool handleRedirect();
protected slots:
@@ -64,9 +64,9 @@ protected slots:
void downloadReadyRead() override;
public slots:
- void startImpl() override;
+ void executeTask() override;
-private: /* data */
+private:
// FIXME: remove this, it has no business being here.
QString m_target_path;
std::unique_ptr<Sink> m_sink;
diff --git a/launcher/net/FileSink.cpp b/launcher/net/FileSink.cpp
index 7e9b8929..0d8b09bb 100644
--- a/launcher/net/FileSink.cpp
+++ b/launcher/net/FileSink.cpp
@@ -1,25 +1,15 @@
#include "FileSink.h"
+
#include <QFile>
-#include <QFileInfo>
+
#include "FileSystem.h"
namespace Net {
-FileSink::FileSink(QString filename)
- :m_filename(filename)
-{
- // nil
-}
-
-FileSink::~FileSink()
-{
- // nil
-}
-
-JobStatus FileSink::init(QNetworkRequest& request)
+Task::State FileSink::init(QNetworkRequest& request)
{
auto result = initCache(request);
- if(result != Job_InProgress)
+ if(result != Task::State::Running)
{
return result;
}
@@ -27,27 +17,27 @@ JobStatus FileSink::init(QNetworkRequest& request)
if (!FS::ensureFilePathExists(m_filename))
{
qCritical() << "Could not create folder for " + m_filename;
- return Job_Failed;
+ return Task::State::Failed;
}
wroteAnyData = false;
m_output_file.reset(new QSaveFile(m_filename));
if (!m_output_file->open(QIODevice::WriteOnly))
{
qCritical() << "Could not open " + m_filename + " for writing";
- return Job_Failed;
+ return Task::State::Failed;
}
if(initAllValidators(request))
- return Job_InProgress;
- return Job_Failed;
+ return Task::State::Running;
+ return Task::State::Failed;
}
-JobStatus FileSink::initCache(QNetworkRequest &)
+Task::State FileSink::initCache(QNetworkRequest &)
{
- return Job_InProgress;
+ return Task::State::Running;
}
-JobStatus FileSink::write(QByteArray& data)
+Task::State FileSink::write(QByteArray& data)
{
if (!writeAllValidators(data) || m_output_file->write(data) != data.size())
{
@@ -55,20 +45,20 @@ JobStatus FileSink::write(QByteArray& data)
m_output_file->cancelWriting();
m_output_file.reset();
wroteAnyData = false;
- return Job_Failed;
+ return Task::State::Failed;
}
wroteAnyData = true;
- return Job_InProgress;
+ return Task::State::Running;
}
-JobStatus FileSink::abort()
+Task::State FileSink::abort()
{
m_output_file->cancelWriting();
failAllValidators();
- return Job_Failed;
+ return Task::State::Failed;
}
-JobStatus FileSink::finalize(QNetworkReply& reply)
+Task::State FileSink::finalize(QNetworkReply& reply)
{
bool gotFile = false;
QVariant statusCodeV = reply.attribute(QNetworkRequest::HttpStatusCodeAttribute);
@@ -86,13 +76,13 @@ JobStatus FileSink::finalize(QNetworkReply& reply)
// ask validators for data consistency
// we only do this for actual downloads, not 'your data is still the same' cache hits
if(!finalizeAllValidators(reply))
- return Job_Failed;
+ return Task::State::Failed;
// nothing went wrong...
if (!m_output_file->commit())
{
qCritical() << "Failed to commit changes to " << m_filename;
m_output_file->cancelWriting();
- return Job_Failed;
+ return Task::State::Failed;
}
}
// then get rid of the save file
@@ -101,9 +91,9 @@ JobStatus FileSink::finalize(QNetworkReply& reply)
return finalizeCache(reply);
}
-JobStatus FileSink::finalizeCache(QNetworkReply &)
+Task::State FileSink::finalizeCache(QNetworkReply &)
{
- return Job_Finished;
+ return Task::State::Succeeded;
}
bool FileSink::hasLocalData()
diff --git a/launcher/net/FileSink.h b/launcher/net/FileSink.h
index 875fe511..9d77b3d0 100644
--- a/launcher/net/FileSink.h
+++ b/launcher/net/FileSink.h
@@ -1,28 +1,30 @@
#pragma once
-#include "Sink.h"
+
#include <QSaveFile>
+#include "Sink.h"
+
namespace Net {
-class FileSink : public Sink
-{
-public: /* con/des */
- FileSink(QString filename);
- virtual ~FileSink();
+class FileSink : public Sink {
+ public:
+ FileSink(QString filename) : m_filename(filename){};
+ virtual ~FileSink() = default;
+
+ public:
+ auto init(QNetworkRequest& request) -> Task::State override;
+ auto write(QByteArray& data) -> Task::State override;
+ auto abort() -> Task::State override;
+ auto finalize(QNetworkReply& reply) -> Task::State override;
-public: /* methods */
- JobStatus init(QNetworkRequest & request) override;
- JobStatus write(QByteArray & data) override;
- JobStatus abort() override;
- JobStatus finalize(QNetworkReply & reply) override;
- bool hasLocalData() override;
+ auto hasLocalData() -> bool override;
-protected: /* methods */
- virtual JobStatus initCache(QNetworkRequest &);
- virtual JobStatus finalizeCache(QNetworkReply &reply);
+ protected:
+ virtual auto initCache(QNetworkRequest&) -> Task::State;
+ virtual auto finalizeCache(QNetworkReply& reply) -> Task::State;
-protected: /* data */
+ protected:
QString m_filename;
bool wroteAnyData = false;
std::unique_ptr<QSaveFile> m_output_file;
};
-}
+} // namespace Net
diff --git a/launcher/net/MetaCacheSink.cpp b/launcher/net/MetaCacheSink.cpp
index 5cdf0460..34ba9f56 100644
--- a/launcher/net/MetaCacheSink.cpp
+++ b/launcher/net/MetaCacheSink.cpp
@@ -12,17 +12,13 @@ MetaCacheSink::MetaCacheSink(MetaEntryPtr entry, ChecksumValidator * md5sum)
addValidator(md5sum);
}
-MetaCacheSink::~MetaCacheSink()
-{
- // nil
-}
-
-JobStatus MetaCacheSink::initCache(QNetworkRequest& request)
+Task::State MetaCacheSink::initCache(QNetworkRequest& request)
{
if (!m_entry->isStale())
{
- return Job_Finished;
+ return Task::State::Succeeded;
}
+
// check if file exists, if it does, use its information for the request
QFile current(m_filename);
if(current.exists() && current.size() != 0)
@@ -36,25 +32,31 @@ JobStatus MetaCacheSink::initCache(QNetworkRequest& request)
request.setRawHeader(QString("If-None-Match").toLatin1(), m_entry->getETag().toLatin1());
}
}
- return Job_InProgress;
+
+ return Task::State::Running;
}
-JobStatus MetaCacheSink::finalizeCache(QNetworkReply & reply)
+Task::State MetaCacheSink::finalizeCache(QNetworkReply & reply)
{
QFileInfo output_file_info(m_filename);
+
if(wroteAnyData)
{
m_entry->setMD5Sum(m_md5Node->hash().toHex().constData());
}
+
m_entry->setETag(reply.rawHeader("ETag").constData());
+
if (reply.hasRawHeader("Last-Modified"))
{
m_entry->setRemoteChangedTimestamp(reply.rawHeader("Last-Modified").constData());
}
+
m_entry->setLocalChangedTimestamp(output_file_info.lastModified().toUTC().toMSecsSinceEpoch());
m_entry->setStale(false);
APPLICATION->metacache()->updateEntry(m_entry);
- return Job_Finished;
+
+ return Task::State::Succeeded;
}
bool MetaCacheSink::hasLocalData()
diff --git a/launcher/net/MetaCacheSink.h b/launcher/net/MetaCacheSink.h
index edcf7ad1..431e10a8 100644
--- a/launcher/net/MetaCacheSink.h
+++ b/launcher/net/MetaCacheSink.h
@@ -1,22 +1,23 @@
#pragma once
-#include "FileSink.h"
+
#include "ChecksumValidator.h"
+#include "FileSink.h"
#include "net/HttpMetaCache.h"
namespace Net {
-class MetaCacheSink : public FileSink
-{
-public: /* con/des */
- MetaCacheSink(MetaEntryPtr entry, ChecksumValidator * md5sum);
- virtual ~MetaCacheSink();
- bool hasLocalData() override;
+class MetaCacheSink : public FileSink {
+ public:
+ MetaCacheSink(MetaEntryPtr entry, ChecksumValidator* md5sum);
+ virtual ~MetaCacheSink() = default;
+
+ auto hasLocalData() -> bool override;
-protected: /* methods */
- JobStatus initCache(QNetworkRequest & request) override;
- JobStatus finalizeCache(QNetworkReply & reply) override;
+ protected:
+ auto initCache(QNetworkRequest& request) -> Task::State override;
+ auto finalizeCache(QNetworkReply& reply) -> Task::State override;
-private: /* data */
+ private:
MetaEntryPtr m_entry;
- ChecksumValidator * m_md5Node;
+ ChecksumValidator* m_md5Node;
};
-}
+} // namespace Net
diff --git a/launcher/net/NetAction.h b/launcher/net/NetAction.h
index efb20953..e15716f6 100644
--- a/launcher/net/NetAction.h
+++ b/launcher/net/NetAction.h
@@ -1,108 +1,81 @@
-/* Copyright 2013-2021 MultiMC Contributors
+// SPDX-License-Identifier: GPL-3.0-only
+/*
+ * PolyMC - Minecraft Launcher
*
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, version 3.
*
- * http://www.apache.org/licenses/LICENSE-2.0
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
*
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ *
+ * This file incorporates work covered by the following copyright and
+ * permission notice:
+ *
+ * Copyright 2013-2021 MultiMC Contributors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
*/
#pragma once
-#include <QObject>
-#include <QUrl>
-#include <memory>
#include <QNetworkReply>
-#include <QObjectPtr.h>
+#include <QUrl>
-enum JobStatus
-{
- Job_NotStarted,
- Job_InProgress,
- Job_Finished,
- Job_Failed,
- Job_Aborted,
- /*
- * FIXME: @NUKE this confuses the task failing with us having a fallback in the form of local data. Clear up the confusion.
- * Same could be true for aborted task - the presence of pre-existing result is a separate concern
- */
- Job_Failed_Proceed
-};
+#include "QObjectPtr.h"
+#include "tasks/Task.h"
-class NetAction : public QObject
-{
+class NetAction : public Task {
Q_OBJECT
-protected:
- explicit NetAction() : QObject(nullptr) {};
+ protected:
+ explicit NetAction() : Task(nullptr) {};
-public:
+ public:
using Ptr = shared_qobject_ptr<NetAction>;
- virtual ~NetAction() {};
-
- bool isRunning() const
- {
- return m_status == Job_InProgress;
- }
- bool isFinished() const
- {
- return m_status >= Job_Finished;
- }
- bool wasSuccessful() const
- {
- return m_status == Job_Finished || m_status == Job_Failed_Proceed;
- }
+ virtual ~NetAction() = default;
- qint64 totalProgress() const
- {
- return m_total_progress;
- }
- qint64 currentProgress() const
- {
- return m_progress;
- }
- virtual bool abort()
- {
- return false;
- }
- virtual bool canAbort()
- {
- return false;
- }
- QUrl url()
- {
- return m_url;
- }
+ QUrl url() { return m_url; }
-signals:
+ signals:
void started(int index);
void netActionProgress(int index, qint64 current, qint64 total);
void succeeded(int index);
void failed(int index);
void aborted(int index);
-protected slots:
+ protected slots:
virtual void downloadProgress(qint64 bytesReceived, qint64 bytesTotal) = 0;
virtual void downloadError(QNetworkReply::NetworkError error) = 0;
virtual void downloadFinished() = 0;
virtual void downloadReadyRead() = 0;
-public slots:
- void start(shared_qobject_ptr<QNetworkAccessManager> network) {
+ public slots:
+ void startAction(shared_qobject_ptr<QNetworkAccessManager> network)
+ {
m_network = network;
- startImpl();
+ executeTask();
}
-protected:
- virtual void startImpl() = 0;
+ protected:
+ void executeTask() override {};
-public:
+ public:
shared_qobject_ptr<QNetworkAccessManager> m_network;
/// index within the parent job, FIXME: nuke
@@ -113,10 +86,4 @@ public:
/// source URL
QUrl m_url;
-
- qint64 m_progress = 0;
- qint64 m_total_progress = 1;
-
-protected:
- JobStatus m_status = Job_NotStarted;
};
diff --git a/launcher/net/NetJob.cpp b/launcher/net/NetJob.cpp
index 9bad89ed..d08d6c4d 100644
--- a/launcher/net/NetJob.cpp
+++ b/launcher/net/NetJob.cpp
@@ -1,79 +1,170 @@
-/* Copyright 2013-2021 MultiMC Contributors
+// SPDX-License-Identifier: GPL-3.0-only
+/*
+ * PolyMC - Minecraft Launcher
*
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, version 3.
*
- * http://www.apache.org/licenses/LICENSE-2.0
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
*
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ *
+ * This file incorporates work covered by the following copyright and
+ * permission notice:
+ *
+ * Copyright 2013-2021 MultiMC Contributors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
*/
#include "NetJob.h"
#include "Download.h"
-#include <QDebug>
+auto NetJob::addNetAction(NetAction::Ptr action) -> bool
+{
+ action->m_index_within_job = m_downloads.size();
+ m_downloads.append(action);
+ part_info pi;
+ m_parts_progress.append(pi);
+
+ partProgress(m_parts_progress.count() - 1, action->getProgress(), action->getTotalProgress());
+
+ if (action->isRunning()) {
+ connect(action.get(), &NetAction::succeeded, this, &NetJob::partSucceeded);
+ connect(action.get(), &NetAction::failed, this, &NetJob::partFailed);
+ connect(action.get(), &NetAction::netActionProgress, this, &NetJob::partProgress);
+ } else {
+ m_todo.append(m_parts_progress.size() - 1);
+ }
+
+ return true;
+}
+
+auto NetJob::canAbort() const -> bool
+{
+ bool canFullyAbort = true;
+
+ // can abort the downloads on the queue?
+ for (auto index : m_todo) {
+ auto part = m_downloads[index];
+ canFullyAbort &= part->canAbort();
+ }
+ // can abort the active downloads?
+ for (auto index : m_doing) {
+ auto part = m_downloads[index];
+ canFullyAbort &= part->canAbort();
+ }
+
+ return canFullyAbort;
+}
+
+void NetJob::executeTask()
+{
+ // hack that delays early failures so they can be caught easier
+ QMetaObject::invokeMethod(this, "startMoreParts", Qt::QueuedConnection);
+}
+
+auto NetJob::getFailedFiles() -> QStringList
+{
+ QStringList failed;
+ for (auto i