From 042f3ef55c0b469f438542152c4eb02b0789ea3c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Petr=20Mr=C3=A1zek?= Date: Sun, 14 Aug 2016 02:33:31 +0200 Subject: GH-352 Make OneSix instance update downloads cancellable --- api/logic/net/Download.cpp | 48 ++++++++++++++++++++++++++++++++++++++++++--- api/logic/net/Download.h | 14 ++++++------- api/logic/net/NetAction.h | 12 +++++++++++- api/logic/net/NetJob.cpp | 49 ++++++++++++++++++++++++++++++++++++++++++++++ api/logic/net/NetJob.h | 11 +++++++---- 5 files changed, 119 insertions(+), 15 deletions(-) (limited to 'api/logic/net') diff --git a/api/logic/net/Download.cpp b/api/logic/net/Download.cpp index 70fe7608..7610cae3 100644 --- a/api/logic/net/Download.cpp +++ b/api/logic/net/Download.cpp @@ -65,6 +65,12 @@ void Download::addValidator(Validator * v) void Download::start() { + if(m_status == Job_Aborted) + { + 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) @@ -80,6 +86,8 @@ void Download::start() case Job_Failed: emit failed(m_index_within_job); return; + case Job_Aborted: + return; } request.setHeader(QNetworkRequest::UserAgentHeader, "MultiMC/5.0"); @@ -103,9 +111,17 @@ void Download::downloadProgress(qint64 bytesReceived, qint64 bytesTotal) void Download::downloadError(QNetworkReply::NetworkError error) { - // error happened during download. - qCritical() << "Failed " << m_url.toString() << " with reason " << error; - m_status = Job_Failed; + if(error == QNetworkReply::OperationCanceledError) + { + qCritical() << "Aborted " << m_url.toString(); + m_status = Job_Aborted; + } + else + { + // error happened during download. + qCritical() << "Failed " << m_url.toString() << " with reason " << error; + m_status = Job_Failed; + } } bool Download::handleRedirect() @@ -154,6 +170,14 @@ void Download::downloadFinished() emit failed(m_index_within_job); return; } + else if(m_status == Job_Aborted) + { + qDebug() << "Download aborted in previous step:" << m_url.toString(); + m_sink->abort(); + m_reply.reset(); + emit aborted(m_index_within_job); + return; + } // make sure we got all the remaining data, if any auto data = m_reply->readAll(); @@ -197,3 +221,21 @@ void Download::downloadReadyRead() } } + +bool Net::Download::abort() +{ + if(m_reply) + { + m_reply->abort(); + } + else + { + m_status = Job_Aborted; + } + return true; +} + +bool Net::Download::canAbort() +{ + return true; +} diff --git a/api/logic/net/Download.h b/api/logic/net/Download.h index 8e38dfc9..fab39ffe 100644 --- a/api/logic/net/Download.h +++ b/api/logic/net/Download.h @@ -38,25 +38,25 @@ public: static Download::Ptr makeFile(QUrl url, QString path); public: /* methods */ - // FIXME: remove this QString getTargetFilepath() { return m_target_path; } - // FIXME: remove this void addValidator(Validator * v); + bool abort() override; + bool canAbort() override; private: /* methods */ bool handleRedirect(); protected slots: - virtual void downloadProgress(qint64 bytesReceived, qint64 bytesTotal); - virtual void downloadError(QNetworkReply::NetworkError error); - virtual void downloadFinished(); - virtual void downloadReadyRead(); + void downloadProgress(qint64 bytesReceived, qint64 bytesTotal) override; + void downloadError(QNetworkReply::NetworkError error) override; + void downloadFinished() override; + void downloadReadyRead() override; public slots: - virtual void start(); + void start() override; private: /* data */ // FIXME: remove this, it has no business being here. diff --git a/api/logic/net/NetAction.h b/api/logic/net/NetAction.h index 2b3f1b7b..07456ce1 100644 --- a/api/logic/net/NetAction.h +++ b/api/logic/net/NetAction.h @@ -28,7 +28,8 @@ enum JobStatus Job_NotStarted, Job_InProgress, Job_Finished, - Job_Failed + Job_Failed, + Job_Aborted }; typedef std::shared_ptr NetActionPtr; @@ -54,6 +55,14 @@ public: { return m_failures; } + virtual bool abort() + { + return false; + } + virtual bool canAbort() + { + return false; + } public: /// the network reply @@ -79,6 +88,7 @@ signals: void netActionProgress(int index, qint64 current, qint64 total); void succeeded(int index); void failed(int index); + void aborted(int index); protected slots: diff --git a/api/logic/net/NetJob.cpp b/api/logic/net/NetJob.cpp index ca86242a..2e375760 100644 --- a/api/logic/net/NetJob.cpp +++ b/api/logic/net/NetJob.cpp @@ -47,6 +47,15 @@ void NetJob::partFailed(int index) startMoreParts(); } +void NetJob::partAborted(int index) +{ + m_aborted = true; + m_doing.remove(index); + m_failed.insert(index); + downloads[index].get()->disconnect(this); + startMoreParts(); +} + void NetJob::partProgress(int index, qint64 bytesReceived, qint64 bytesTotal) { auto &slot = parts_progress[index]; @@ -85,6 +94,11 @@ void NetJob::startMoreParts() qDebug() << m_job_name << "succeeded."; emitSucceeded(); } + else if(m_aborted) + { + qDebug() << m_job_name << "aborted."; + emitFailed(tr("Job '%1' aborted.").arg(m_job_name)); + } else { qCritical() << m_job_name << "failed."; @@ -104,6 +118,7 @@ void NetJob::startMoreParts() // connect signals :D connect(part.get(), SIGNAL(succeeded(int)), SLOT(partSucceeded(int))); connect(part.get(), SIGNAL(failed(int)), SLOT(partFailed(int))); + connect(part.get(), SIGNAL(aborted(int)), SLOT(partAborted(int))); connect(part.get(), SIGNAL(netActionProgress(int, qint64, qint64)), SLOT(partProgress(int, qint64, qint64))); part->start(); @@ -121,3 +136,37 @@ QStringList NetJob::getFailedFiles() failed.sort(); return failed; } + +bool NetJob::canAbort() const +{ + bool canFullyAbort = true; + // can abort the waiting? + for(auto index: m_todo) + { + auto part = downloads[index]; + canFullyAbort &= part->canAbort(); + } + // can abort the active? + for(auto index: m_doing) + { + auto part = downloads[index]; + canFullyAbort &= part->canAbort(); + } + return canFullyAbort; +} + +bool NetJob::abort() +{ + bool fullyAborted = true; + // fail all waiting + m_failed.unite(m_todo.toSet()); + m_todo.clear(); + // abort active + auto toKill = m_doing.toList(); + for(auto index: toKill) + { + auto part = downloads[index]; + fullyAborted &= part->abort(); + } + return fullyAborted; +} diff --git a/api/logic/net/NetJob.h b/api/logic/net/NetJob.h index 3d16b21f..e1c266dd 100644 --- a/api/logic/net/NetJob.h +++ b/api/logic/net/NetJob.h @@ -75,24 +75,26 @@ public: { return downloads.size(); } - virtual bool isRunning() const + virtual bool isRunning() const override { return m_running; } QStringList getFailedFiles(); + bool canAbort() const override; + private slots: void startMoreParts(); public slots: - virtual void executeTask(); - // FIXME: implement - virtual bool abort() {return false;}; + virtual void executeTask() override; + virtual bool abort() override; private slots: void partProgress(int index, qint64 bytesReceived, qint64 bytesTotal); void partSucceeded(int index); void partFailed(int index); + void partAborted(int index); private: struct part_info @@ -112,4 +114,5 @@ private: qint64 current_progress = 0; qint64 total_progress = 0; bool m_running = false; + bool m_aborted = false; }; -- cgit v1.2.3