diff options
Diffstat (limited to 'logic')
-rw-r--r-- | logic/BaseInstance.h | 2 | ||||
-rw-r--r-- | logic/OneSixUpdate.cpp | 9 | ||||
-rw-r--r-- | logic/auth/MojangAccountList.cpp | 27 | ||||
-rw-r--r-- | logic/auth/MojangAccountList.h | 5 | ||||
-rw-r--r-- | logic/lists/InstanceList.cpp | 14 | ||||
-rw-r--r-- | logic/lists/InstanceList.h | 5 | ||||
-rw-r--r-- | logic/net/ByteArrayDownload.cpp | 8 | ||||
-rw-r--r-- | logic/net/CacheDownload.cpp | 14 | ||||
-rw-r--r-- | logic/net/ForgeMirrors.cpp | 8 | ||||
-rw-r--r-- | logic/net/ForgeXzDownload.cpp | 18 | ||||
-rw-r--r-- | logic/net/MD5EtagDownload.cpp | 16 | ||||
-rw-r--r-- | logic/net/NetAction.h | 23 | ||||
-rw-r--r-- | logic/net/NetJob.h | 12 | ||||
-rw-r--r-- | logic/net/PasteUpload.cpp | 2 | ||||
-rw-r--r-- | logic/net/S3ListBucket.cpp | 175 | ||||
-rw-r--r-- | logic/net/S3ListBucket.h | 57 |
16 files changed, 117 insertions, 278 deletions
diff --git a/logic/BaseInstance.h b/logic/BaseInstance.h index 93e57414..5f426676 100644 --- a/logic/BaseInstance.h +++ b/logic/BaseInstance.h @@ -149,7 +149,7 @@ public: */ virtual SettingsObject &settings() const; - /// returns a valid update task if update is needed, NULL otherwise + /// returns a valid update task virtual std::shared_ptr<Task> doUpdate(bool only_prepare) = 0; /// returns a valid minecraft process, ready for launch with the given account. diff --git a/logic/OneSixUpdate.cpp b/logic/OneSixUpdate.cpp index 66950fc4..696eeff0 100644 --- a/logic/OneSixUpdate.cpp +++ b/logic/OneSixUpdate.cpp @@ -54,11 +54,9 @@ void OneSixUpdate::executeTask() if (m_only_prepare) { - if (m_inst->shouldUpdate()) - { - emitFailed("Unable to update instance in offline mode."); - return; - } + /* + * FIXME: in offline mode, do not proceed! + */ setStatus("Testing the Java installation."); QString java_path = m_inst->settings().get("JavaPath").toString(); @@ -243,6 +241,7 @@ void OneSixUpdate::assetIndexFinished() auto objectDL = MD5EtagDownload::make( QUrl("http://" + URLConstants::RESOURCE_BASE + objectName), objectFile.filePath()); + objectDL->m_total_progress = object.size; dls.append(objectDL); } } diff --git a/logic/auth/MojangAccountList.cpp b/logic/auth/MojangAccountList.cpp index 33990662..70bc0cf2 100644 --- a/logic/auth/MojangAccountList.cpp +++ b/logic/auth/MojangAccountList.cpp @@ -27,6 +27,7 @@ #include "logger/QsLog.h" #include "logic/auth/MojangAccount.h" +#include <pathutils.h> #define ACCOUNT_LIST_FORMAT_VERSION 2 @@ -265,11 +266,6 @@ bool MojangAccountList::loadList(const QString &filePath) return false; } - if (!QDir::current().exists(path)) - { - QDir::current().mkpath(path); - } - QFile file(path); // Try to open the file and fail if we can't. @@ -351,9 +347,16 @@ bool MojangAccountList::saveList(const QString &filePath) return false; } - if (!QDir::current().exists(path)) + // make sure the parent folder exists + if(!ensureFilePathExists(path)) + return false; + + // make sure the file wasn't overwritten with a folder before (fixes a bug) + QFileInfo finfo(path); + if(finfo.isDir()) { - QDir::current().mkpath(path); + QDir badDir(path); + badDir.removeRecursively(); } QLOG_INFO() << "Writing account list to" << path; @@ -411,3 +414,13 @@ void MojangAccountList::setListFilePath(QString path, bool autosave) m_listFilePath = path; m_autosave = autosave; } + +bool MojangAccountList::anyAccountIsValid() +{ + for(auto account:m_accounts) + { + if(account->accountStatus() != NotVerified) + return true; + } + return false; +} diff --git a/logic/auth/MojangAccountList.h b/logic/auth/MojangAccountList.h index c7e30958..6f4fbb17 100644 --- a/logic/auth/MojangAccountList.h +++ b/logic/auth/MojangAccountList.h @@ -126,6 +126,11 @@ public: * If the username given is an empty string, sets the active account to nothing. */ virtual void setActiveAccount(const QString &username); + + /*! + * Returns true if any of the account is at least Validated + */ + bool anyAccountIsValid(); signals: /*! diff --git a/logic/lists/InstanceList.cpp b/logic/lists/InstanceList.cpp index 94481fb9..15fd10ba 100644 --- a/logic/lists/InstanceList.cpp +++ b/logic/lists/InstanceList.cpp @@ -117,6 +117,11 @@ void InstanceList::groupChanged() saveGroupList(); } +QStringList InstanceList::getGroups() +{ + return m_groups.toList(); +} + void InstanceList::saveGroupList() { QString groupFileName = m_instDir + "/instgroups.json"; @@ -126,7 +131,7 @@ void InstanceList::saveGroupList() if (!groupFile.open(QIODevice::WriteOnly | QIODevice::Truncate)) { // An error occurred. Ignore it. - QLOG_ERROR() << "Failed to read instance group file."; + QLOG_ERROR() << "Failed to save instance group file."; return; } QTextStream out(&groupFile); @@ -137,6 +142,10 @@ void InstanceList::saveGroupList() QString group = instance->group(); if (group.isEmpty()) continue; + + // keep a list/set of groups for choosing + m_groups.insert(group); + if (!groupMap.count(group)) { QSet<QString> set; @@ -253,6 +262,9 @@ void InstanceList::loadGroupList(QMap<QString, QString> &groupMap) continue; } + // keep a list/set of groups for choosing + m_groups.insert(groupName); + // Iterate through the list of instances in the group. QJsonArray instancesArray = groupObj.value("instances").toArray(); diff --git a/logic/lists/InstanceList.h b/logic/lists/InstanceList.h index c3bb74cd..f23b7763 100644 --- a/logic/lists/InstanceList.h +++ b/logic/lists/InstanceList.h @@ -17,6 +17,7 @@ #include <QObject> #include <QAbstractListModel> +#include <QSet> #include "categorizedsortfilterproxymodel.h" #include <QIcon> @@ -97,6 +98,9 @@ public: InstancePtr getInstanceById(QString id) const; QModelIndex getInstanceIndexById(const QString &id) const; + + // FIXME: instead of iterating through all instances and forming a set, keep the set around + QStringList getGroups(); signals: void dataIsInvalid(); @@ -116,6 +120,7 @@ private: protected: QString m_instDir; QList<InstancePtr> m_instances; + QSet<QString> m_groups; }; class InstanceProxyModel : public KCategorizedSortFilterProxyModel diff --git a/logic/net/ByteArrayDownload.cpp b/logic/net/ByteArrayDownload.cpp index af5af8e9..27d2a250 100644 --- a/logic/net/ByteArrayDownload.cpp +++ b/logic/net/ByteArrayDownload.cpp @@ -42,7 +42,9 @@ void ByteArrayDownload::start() void ByteArrayDownload::downloadProgress(qint64 bytesReceived, qint64 bytesTotal) { - emit progress(index_within_job, bytesReceived, bytesTotal); + m_total_progress = bytesTotal; + m_progress = bytesReceived; + emit progress(m_index_within_job, bytesReceived, bytesTotal); } void ByteArrayDownload::downloadError(QNetworkReply::NetworkError error) @@ -62,14 +64,14 @@ void ByteArrayDownload::downloadFinished() m_status = Job_Finished; m_data = m_reply->readAll(); m_reply.reset(); - emit succeeded(index_within_job); + emit succeeded(m_index_within_job); return; } // else the download failed else { m_reply.reset(); - emit failed(index_within_job); + emit failed(m_index_within_job); return; } } diff --git a/logic/net/CacheDownload.cpp b/logic/net/CacheDownload.cpp index 873d3a2e..6eadae39 100644 --- a/logic/net/CacheDownload.cpp +++ b/logic/net/CacheDownload.cpp @@ -35,14 +35,14 @@ void CacheDownload::start() { if (!m_entry->stale) { - emit succeeded(index_within_job); + emit succeeded(m_index_within_job); return; } m_output_file.setFileName(m_target_path); // if there already is a file and md5 checking is in effect and it can be opened if (!ensureFilePathExists(m_target_path)) { - emit failed(index_within_job); + emit failed(m_index_within_job); return; } QLOG_INFO() << "Downloading " << m_url.toString(); @@ -69,7 +69,9 @@ void CacheDownload::start() void CacheDownload::downloadProgress(qint64 bytesReceived, qint64 bytesTotal) { - emit progress(index_within_job, bytesReceived, bytesTotal); + m_total_progress = bytesTotal; + m_progress = bytesReceived; + emit progress(m_index_within_job, bytesReceived, bytesTotal); } void CacheDownload::downloadError(QNetworkReply::NetworkError error) @@ -116,7 +118,7 @@ void CacheDownload::downloadFinished() MMC->metacache()->updateEntry(m_entry); m_reply.reset(); - emit succeeded(index_within_job); + emit succeeded(m_index_within_job); return; } // else the download failed @@ -125,7 +127,7 @@ void CacheDownload::downloadFinished() m_output_file.close(); m_output_file.remove(); m_reply.reset(); - emit failed(index_within_job); + emit failed(m_index_within_job); return; } } @@ -140,7 +142,7 @@ void CacheDownload::downloadReadyRead() * Can't open the file... the job failed */ m_reply->abort(); - emit failed(index_within_job); + emit failed(m_index_within_job); return; } } diff --git a/logic/net/ForgeMirrors.cpp b/logic/net/ForgeMirrors.cpp index fd7eccca..b224306f 100644 --- a/logic/net/ForgeMirrors.cpp +++ b/logic/net/ForgeMirrors.cpp @@ -68,7 +68,7 @@ void ForgeMirrors::deferToFixedList() "https://www.creeperhost.net/link.php?id=1", "http://new.creeperrepo.net/forge/maven/"}); injectDownloads(); - emit succeeded(index_within_job); + emit succeeded(m_index_within_job); } void ForgeMirrors::parseMirrorList() @@ -88,7 +88,7 @@ void ForgeMirrors::parseMirrorList() if(!m_mirrors.size()) deferToFixedList(); injectDownloads(); - emit succeeded(index_within_job); + emit succeeded(m_index_within_job); } void ForgeMirrors::injectDownloads() @@ -108,7 +108,9 @@ void ForgeMirrors::injectDownloads() void ForgeMirrors::downloadProgress(qint64 bytesReceived, qint64 bytesTotal) { - emit progress(index_within_job, bytesReceived, bytesTotal); + m_total_progress = bytesTotal; + m_progress = bytesReceived; + emit progress(m_index_within_job, bytesReceived, bytesTotal); } void ForgeMirrors::downloadReadyRead() diff --git a/logic/net/ForgeXzDownload.cpp b/logic/net/ForgeXzDownload.cpp index f119878a..1771d304 100644 --- a/logic/net/ForgeXzDownload.cpp +++ b/logic/net/ForgeXzDownload.cpp @@ -44,20 +44,20 @@ void ForgeXzDownload::start() if (!m_entry->stale) { m_status = Job_Finished; - emit succeeded(index_within_job); + emit succeeded(m_index_within_job); return; } // can we actually create the real, final file? if (!ensureFilePathExists(m_target_path)) { m_status = Job_Failed; - emit failed(index_within_job); + emit failed(m_index_within_job); return; } if (m_mirrors.empty()) { m_status = Job_Failed; - emit failed(index_within_job); + emit failed(m_index_within_job); return; } @@ -80,7 +80,9 @@ void ForgeXzDownload::start() void ForgeXzDownload::downloadProgress(qint64 bytesReceived, qint64 bytesTotal) { - emit progress(index_within_job, bytesReceived, bytesTotal); + m_total_progress = bytesTotal; + m_progress = bytesReceived; + emit progress(m_index_within_job, bytesReceived, bytesTotal); } void ForgeXzDownload::downloadError(QNetworkReply::NetworkError error) @@ -100,7 +102,7 @@ void ForgeXzDownload::failAndTryNextMirror() m_mirror_index = next; updateUrl(); - emit failed(index_within_job); + emit failed(m_index_within_job); } void ForgeXzDownload::updateUrl() @@ -148,7 +150,7 @@ void ForgeXzDownload::downloadFinished() m_status = Job_Failed; m_pack200_xz_file.remove(); m_reply.reset(); - emit failed(index_within_job); + emit failed(m_index_within_job); return; } } @@ -175,7 +177,7 @@ void ForgeXzDownload::downloadReadyRead() * Can't open the file... the job failed */ m_reply->abort(); - emit failed(index_within_job); + emit failed(m_index_within_job); return; } } @@ -347,5 +349,5 @@ void ForgeXzDownload::decompressAndInstall() MMC->metacache()->updateEntry(m_entry); m_reply.reset(); - emit succeeded(index_within_job); + emit succeeded(m_index_within_job); } diff --git a/logic/net/MD5EtagDownload.cpp b/logic/net/MD5EtagDownload.cpp index 4b9f52af..435e854e 100644 --- a/logic/net/MD5EtagDownload.cpp +++ b/logic/net/MD5EtagDownload.cpp @@ -44,7 +44,7 @@ void MD5EtagDownload::start() if (m_check_md5 && hash == m_expected_md5) { QLOG_INFO() << "Skipping " << m_url.toString() << ": md5 match."; - emit succeeded(index_within_job); + emit succeeded(m_index_within_job); return; } else @@ -54,7 +54,7 @@ void MD5EtagDownload::start() } if (!ensureFilePathExists(filename)) { - emit failed(index_within_job); + emit failed(m_index_within_job); return; } @@ -68,7 +68,7 @@ void MD5EtagDownload::start() // Plus, this way, we don't end up starting a download for a file we can't open. if (!m_output_file.open(QIODevice::WriteOnly)) { - emit failed(index_within_job); + emit failed(m_index_within_job); return; } @@ -86,7 +86,9 @@ void MD5EtagDownload::start() void MD5EtagDownload::downloadProgress(qint64 bytesReceived, qint64 bytesTotal) { - emit progress(index_within_job, bytesReceived, bytesTotal); + m_total_progress = bytesTotal; + m_progress = bytesReceived; + emit progress(m_index_within_job, bytesReceived, bytesTotal); } void MD5EtagDownload::downloadError(QNetworkReply::NetworkError error) @@ -107,7 +109,7 @@ void MD5EtagDownload::downloadFinished() QLOG_INFO() << "Finished " << m_url.toString() << " got " << m_reply->rawHeader("ETag").constData(); m_reply.reset(); - emit succeeded(index_within_job); + emit succeeded(m_index_within_job); return; } // else the download failed @@ -115,7 +117,7 @@ void MD5EtagDownload::downloadFinished() { m_output_file.close(); m_reply.reset(); - emit failed(index_within_job); + emit failed(m_index_within_job); return; } } @@ -130,7 +132,7 @@ void MD5EtagDownload::downloadReadyRead() * Can't open the file... the job failed */ m_reply->abort(); - emit failed(index_within_job); + emit failed(m_index_within_job); return; } } diff --git a/logic/net/NetAction.h b/logic/net/NetAction.h index c96d8f8f..97c96e5d 100644 --- a/logic/net/NetAction.h +++ b/logic/net/NetAction.h @@ -39,6 +39,19 @@ public: virtual ~NetAction() {}; public: + virtual qint64 totalProgress() const + { + return m_total_progress; + } + virtual qint64 currentProgress() const + { + return m_progress; + } + virtual qint64 numberOfFailures() const + { + return m_failures; + } +public: /// the network reply std::shared_ptr<QNetworkReply> m_reply; @@ -46,10 +59,16 @@ public: QUrl m_url; /// The file's status - JobStatus m_status; + JobStatus m_status = Job_NotStarted; /// index within the parent job - int index_within_job = 0; + int m_index_within_job = 0; + + qint64 m_progress = 0; + qint64 m_total_progress = 1; + + /// number of failures up to this point + int m_failures = 0; signals: void started(int index); diff --git a/logic/net/NetJob.h b/logic/net/NetJob.h index 6e2e7607..68c4c408 100644 --- a/logic/net/NetJob.h +++ b/logic/net/NetJob.h @@ -36,10 +36,16 @@ public: template <typename T> bool addNetAction(T action) { NetActionPtr base = std::static_pointer_cast<NetAction>(action); - base->index_within_job = downloads.size(); + base->m_index_within_job = downloads.size(); downloads.append(action); - parts_progress.append(part_info()); - total_progress++; + part_info pi; + { + pi.current_progress = base->currentProgress(); + pi.total_progress = base->totalProgress(); + pi.failures = base->numberOfFailures(); + } + parts_progress.append(pi); + total_progress += pi.total_progress; // if this is already running, the action needs to be started right away! if (isRunning()) { diff --git a/logic/net/PasteUpload.cpp b/logic/net/PasteUpload.cpp index acf09291..fa54d084 100644 --- a/logic/net/PasteUpload.cpp +++ b/logic/net/PasteUpload.cpp @@ -78,7 +78,9 @@ bool PasteUpload::parseResult(QJsonDocument doc, QString *parseError) parseError = new QString(object.value("error").toString()); return false; } + // FIXME: not the place for GUI things. QString pasteUrl = object.value("paste").toObject().value("link").toString(); QDesktopServices::openUrl(pasteUrl); return true; } + diff --git a/logic/net/S3ListBucket.cpp b/logic/net/S3ListBucket.cpp deleted file mode 100644 index 439b7086..00000000 --- a/logic/net/S3ListBucket.cpp +++ /dev/null @@ -1,175 +0,0 @@ -/* Copyright 2013 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 "S3ListBucket.h" -#include "MultiMC.h" -#include "logger/QsLog.h" -#include <QUrlQuery> -#include <qxmlstream.h> -#include <QDomDocument> - -inline QDomElement getDomElementByTagName(QDomElement parent, QString tagname) -{ - QDomNodeList elementList = parent.elementsByTagName(tagname); - if (elementList.count()) - return elementList.at(0).toElement(); - else - return QDomElement(); -} - -S3ListBucket::S3ListBucket(QUrl url) : NetAction() -{ - m_url = url; - m_status = Job_NotStarted; -} - -void S3ListBucket::start() -{ - QUrl finalUrl = m_url; - if (current_marker.size()) - { - QUrlQuery query; - query.addQueryItem("marker", current_marker); - finalUrl.setQuery(query); - } - QNetworkRequest request(finalUrl); - request.setHeader(QNetworkRequest::UserAgentHeader, "MultiMC/5.0 (Uncached)"); - auto worker = MMC->qnam(); - QNetworkReply *rep = worker->get(request); - - m_reply = std::shared_ptr<QNetworkReply>(rep); - connect(rep, SIGNAL(downloadProgress(qint64, qint64)), - SLOT(downloadProgress(qint64, qint64))); - connect(rep, SIGNAL(finished()), SLOT(downloadFinished())); - connect(rep, SIGNAL(error(QNetworkReply::NetworkError)), - SLOT(downloadError(QNetworkReply::NetworkError))); - connect(rep, SIGNAL(readyRead()), SLOT(downloadReadyRead())); -} - -void S3ListBucket::downloadProgress(qint64 bytesReceived, qint64 bytesTotal) -{ - emit progress(index_within_job, bytesSoFar + bytesReceived, bytesSoFar + bytesTotal); -} - -void S3ListBucket::downloadError(QNetworkReply::NetworkError error) -{ - // error happened during download. - QLOG_ERROR() << "Error getting URL:" << m_url.toString().toLocal8Bit() - << "Network error: " << error; - m_status = Job_Failed; -} - -void S3ListBucket::processValidReply() -{ - QLOG_TRACE() << "GOT: " << m_url.toString() << " marker:" << current_marker; - auto readContents = [&](QXmlStreamReader & xml) - { - QString Key, ETag, Size; - while (!(xml.tokenType() == QXmlStreamReader::EndElement && xml.name() == "Contents")) - { - if (xml.tokenType() == QXmlStreamReader::StartElement) - { - if (xml.name() == "Key") - { - Key = xml.readElementText(); - } - if (xml.name() == "ETag") - { - ETag = xml.readElementText(); - } - if (xml.name() == "Size") - { - Size = xml.readElementText(); - } - } - xml.readNext(); - } - if (xml.error() != QXmlStreamReader::NoError) - return; - objects.append({Key, ETag, Size.toLongLong()}); - }; - - // nothing went wrong... - QByteArray ba = m_reply->readAll(); - - QString xmlErrorMsg; - - bool is_truncated = false; - QXmlStreamReader xml(ba); - while (!xml.atEnd() && !xml.hasError()) - { - /* Read next element.*/ - QXmlStreamReader::TokenType token = xml.readNext(); - /* If token is just StartDocument, we'll go to next.*/ - if (token == QXmlStreamReader::StartDocument) - { - continue; - } - if (token == QXmlStreamReader::StartElement) - { - /* If it's named person, we'll dig the information from there.*/ - if (xml.name() == "Contents") - { - readContents(xml); - } - else if (xml.name() == "IsTruncated") - { - is_truncated = (xml.readElementText() == "true"); - } - } - } - if (xml.hasError()) - { - QLOG_ERROR() << "Failed to process s3.amazonaws.com/Minecraft.Resources. XML error:" - << xml.errorString() << ba; - emit failed(index_within_job); - return; - } - if (is_truncated) - { - current_marker = objects.last().Key; - bytesSoFar += m_reply->size(); - m_reply.reset(); - start(); - } - else - { - m_status = Job_Finished; - m_reply.reset(); - emit succeeded(index_within_job); - } - return; -} - -void S3ListBucket::downloadFinished() -{ - // if the download succeeded - if (m_status != Job_Failed) - { - processValidReply(); - } - // else the download failed - else - { - m_reply.reset(); - emit failed(index_within_job); - return; - } -} - -void S3ListBucket::downloadReadyRead() -{ - // ~_~ -} diff --git a/logic/net/S3ListBucket.h b/logic/net/S3ListBucket.h deleted file mode 100644 index e7c5e05c..00000000 --- a/logic/net/S3ListBucket.h +++ /dev/null @@ -1,57 +0,0 @@ -/* Copyright 2013 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 "NetAction.h" - -struct S3Object -{ - QString Key; - QString ETag; - qlonglong size; -}; - -typedef std::shared_ptr<class S3ListBucket> S3ListBucketPtr; -class S3ListBucket : public NetAction -{ - Q_OBJECT -public: - S3ListBucket(QUrl url); - static S3ListBucketPtr make(QUrl url) - { - return S3ListBucketPtr(new S3ListBucket(url)); - } - -public: - QList<S3Object> objects; - -public -slots: - virtual void start() override; - -protected -slots: - virtual void downloadProgress(qint64 bytesReceived, qint64 bytesTotal) override; - virtual void downloadError(QNetworkReply::NetworkError error) override; - virtual void downloadFinished() override; - virtual void downloadReadyRead() override; - -private: - void processValidReply(); - -private: - qint64 bytesSoFar = 0; - QString current_marker; -}; |