diff options
Diffstat (limited to 'logic/wonko')
| -rw-r--r-- | logic/wonko/BaseWonkoEntity.cpp | 39 | ||||
| -rw-r--r-- | logic/wonko/BaseWonkoEntity.h | 51 | ||||
| -rw-r--r-- | logic/wonko/WonkoIndex.cpp | 147 | ||||
| -rw-r--r-- | logic/wonko/WonkoIndex.h | 68 | ||||
| -rw-r--r-- | logic/wonko/WonkoReference.cpp | 44 | ||||
| -rw-r--r-- | logic/wonko/WonkoReference.h | 41 | ||||
| -rw-r--r-- | logic/wonko/WonkoUtil.cpp | 47 | ||||
| -rw-r--r-- | logic/wonko/WonkoUtil.h | 31 | ||||
| -rw-r--r-- | logic/wonko/WonkoVersion.cpp | 102 | ||||
| -rw-r--r-- | logic/wonko/WonkoVersion.h | 83 | ||||
| -rw-r--r-- | logic/wonko/WonkoVersionList.cpp | 283 | ||||
| -rw-r--r-- | logic/wonko/WonkoVersionList.h | 92 | ||||
| -rw-r--r-- | logic/wonko/format/WonkoFormat.cpp | 80 | ||||
| -rw-r--r-- | logic/wonko/format/WonkoFormat.h | 54 | ||||
| -rw-r--r-- | logic/wonko/format/WonkoFormatV1.cpp | 156 | ||||
| -rw-r--r-- | logic/wonko/format/WonkoFormatV1.h | 30 | ||||
| -rw-r--r-- | logic/wonko/tasks/BaseWonkoEntityLocalLoadTask.cpp | 117 | ||||
| -rw-r--r-- | logic/wonko/tasks/BaseWonkoEntityLocalLoadTask.h | 81 | ||||
| -rw-r--r-- | logic/wonko/tasks/BaseWonkoEntityRemoteLoadTask.cpp | 126 | ||||
| -rw-r--r-- | logic/wonko/tasks/BaseWonkoEntityRemoteLoadTask.h | 85 |
20 files changed, 1757 insertions, 0 deletions
diff --git a/logic/wonko/BaseWonkoEntity.cpp b/logic/wonko/BaseWonkoEntity.cpp new file mode 100644 index 00000000..f5c59363 --- /dev/null +++ b/logic/wonko/BaseWonkoEntity.cpp @@ -0,0 +1,39 @@ +/* Copyright 2015 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 "BaseWonkoEntity.h" + +#include "Json.h" +#include "WonkoUtil.h" + +BaseWonkoEntity::~BaseWonkoEntity() +{ +} + +void BaseWonkoEntity::store() const +{ + Json::write(serialized(), Wonko::localWonkoDir().absoluteFilePath(localFilename())); +} + +void BaseWonkoEntity::notifyLocalLoadComplete() +{ + m_localLoaded = true; + store(); +} +void BaseWonkoEntity::notifyRemoteLoadComplete() +{ + m_remoteLoaded = true; + store(); +} diff --git a/logic/wonko/BaseWonkoEntity.h b/logic/wonko/BaseWonkoEntity.h new file mode 100644 index 00000000..191b4184 --- /dev/null +++ b/logic/wonko/BaseWonkoEntity.h @@ -0,0 +1,51 @@ +/* Copyright 2015 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 <memory> + +#include "multimc_logic_export.h" + +class Task; + +class MULTIMC_LOGIC_EXPORT BaseWonkoEntity +{ +public: + virtual ~BaseWonkoEntity(); + + using Ptr = std::shared_ptr<BaseWonkoEntity>; + + virtual std::unique_ptr<Task> remoteUpdateTask() = 0; + virtual std::unique_ptr<Task> localUpdateTask() = 0; + virtual void merge(const std::shared_ptr<BaseWonkoEntity> &other) = 0; + + void store() const; + virtual QString localFilename() const = 0; + virtual QJsonObject serialized() const = 0; + + bool isComplete() const { return m_localLoaded || m_remoteLoaded; } + + bool isLocalLoaded() const { return m_localLoaded; } + bool isRemoteLoaded() const { return m_remoteLoaded; } + + void notifyLocalLoadComplete(); + void notifyRemoteLoadComplete(); + +private: + bool m_localLoaded = false; + bool m_remoteLoaded = false; +}; diff --git a/logic/wonko/WonkoIndex.cpp b/logic/wonko/WonkoIndex.cpp new file mode 100644 index 00000000..8306af84 --- /dev/null +++ b/logic/wonko/WonkoIndex.cpp @@ -0,0 +1,147 @@ +/* Copyright 2015 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 "WonkoIndex.h" + +#include "WonkoVersionList.h" +#include "tasks/BaseWonkoEntityLocalLoadTask.h" +#include "tasks/BaseWonkoEntityRemoteLoadTask.h" +#include "format/WonkoFormat.h" + +WonkoIndex::WonkoIndex(QObject *parent) + : QAbstractListModel(parent) +{ +} +WonkoIndex::WonkoIndex(const QVector<WonkoVersionListPtr> &lists, QObject *parent) + : QAbstractListModel(parent), m_lists(lists) +{ + for (int i = 0; i < m_lists.size(); ++i) + { + m_uids.insert(m_lists.at(i)->uid(), m_lists.at(i)); + connectVersionList(i, m_lists.at(i)); + } +} + +QVariant WonkoIndex::data(const QModelIndex &index, int role) const +{ + if (index.parent().isValid() || index.row() < 0 || index.row() >= m_lists.size()) + { + return QVariant(); + } + + WonkoVersionListPtr list = m_lists.at(index.row()); + switch (role) + { + case Qt::DisplayRole: + switch (index.column()) + { + case 0: return list->humanReadable(); + default: break; + } + case UidRole: return list->uid(); + case NameRole: return list->name(); + case ListPtrRole: return QVariant::fromValue(list); + } + return QVariant(); +} +int WonkoIndex::rowCount(const QModelIndex &parent) const +{ + return m_lists.size(); +} +int WonkoIndex::columnCount(const QModelIndex &parent) const +{ + return 1; +} +QVariant WonkoIndex::headerData(int section, Qt::Orientation orientation, int role) const +{ + if (orientation == Qt::Horizontal && role == Qt::DisplayRole && section == 0) + { + return tr("Name"); + } + else + { + return QVariant(); + } +} + +std::unique_ptr<Task> WonkoIndex::remoteUpdateTask() +{ + return std::unique_ptr<WonkoIndexRemoteLoadTask>(new WonkoIndexRemoteLoadTask(this, this)); +} +std::unique_ptr<Task> WonkoIndex::localUpdateTask() +{ + return std::unique_ptr<WonkoIndexLocalLoadTask>(new WonkoIndexLocalLoadTask(this, this)); +} + +QJsonObject WonkoIndex::serialized() const +{ + return WonkoFormat::serializeIndex(this); +} + +bool WonkoIndex::hasUid(const QString &uid) const +{ + return m_uids.contains(uid); +} +WonkoVersionListPtr WonkoIndex::getList(const QString &uid) const +{ + return m_uids.value(uid, nullptr); +} +WonkoVersionListPtr WonkoIndex::getListGuaranteed(const QString &uid) const +{ + return m_uids.value(uid, std::make_shared<WonkoVersionList>(uid)); +} + +void WonkoIndex::merge(const Ptr &other) +{ + const QVector<WonkoVersionListPtr> lists = std::dynamic_pointer_cast<WonkoIndex>(other)->m_lists; + // initial load, no need to merge + if (m_lists.isEmpty()) + { + beginResetModel(); + m_lists = lists; + for (int i = 0; i < lists.size(); ++i) + { + m_uids.insert(lists.at(i)->uid(), lists.at(i)); + connectVersionList(i, lists.at(i)); + } + endResetModel(); + } + else + { + for (const WonkoVersionListPtr &list : lists) + { + if (m_uids.contains(list->uid())) + { + m_uids[list->uid()]->merge(list); + } + else + { + beginInsertRows(QModelIndex(), m_lists.size(), m_lists.size()); + connectVersionList(m_lists.size(), list); + m_lists.append(list); + m_uids.insert(list->uid(), list); + endInsertRows(); + } + } + } +} + +void WonkoIndex::connectVersionList(const int row, const WonkoVersionListPtr &list) +{ + connect(list.get(), &WonkoVersionList::nameChanged, this, [this, row]() + { + emit dataChanged(index(row), index(row), QVector<int>() << Qt::DisplayRole); + }); +} diff --git a/logic/wonko/WonkoIndex.h b/logic/wonko/WonkoIndex.h new file mode 100644 index 00000000..8b149c7d --- /dev/null +++ b/logic/wonko/WonkoIndex.h @@ -0,0 +1,68 @@ +/* Copyright 2015 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 <QAbstractListModel> +#include <memory> + +#include "BaseWonkoEntity.h" + +#include "multimc_logic_export.h" + +class Task; +using WonkoVersionListPtr = std::shared_ptr<class WonkoVersionList>; + +class MULTIMC_LOGIC_EXPORT WonkoIndex : public QAbstractListModel, public BaseWonkoEntity +{ + Q_OBJECT +public: + explicit WonkoIndex(QObject *parent = nullptr); + explicit WonkoIndex(const QVector<WonkoVersionListPtr> &lists, QObject *parent = nullptr); + + enum + { + UidRole = Qt::UserRole, + NameRole, + ListPtrRole + }; + + QVariant data(const QModelIndex &index, int role) const override; + int rowCount(const QModelIndex &parent) const override; + int columnCount(const QModelIndex &parent) const override; + QVariant headerData(int section, Qt::Orientation orientation, int role) const override; + + std::unique_ptr<Task> remoteUpdateTask() override; + std::unique_ptr<Task> localUpdateTask() override; + + QString localFilename() const override { return "index.json"; } + QJsonObject serialized() const override; + + // queries + bool hasUid(const QString &uid) const; + WonkoVersionListPtr getList(const QString &uid) const; + WonkoVersionListPtr getListGuaranteed(const QString &uid) const; + + QVector<WonkoVersionListPtr> lists() const { return m_lists; } + +public: // for usage by parsers only + void merge(const BaseWonkoEntity::Ptr &other); + +private: + QVector<WonkoVersionListPtr> m_lists; + QHash<QString, WonkoVersionListPtr> m_uids; + + void connectVersionList(const int row, const WonkoVersionListPtr &list); +}; diff --git a/logic/wonko/WonkoReference.cpp b/logic/wonko/WonkoReference.cpp new file mode 100644 index 00000000..519d59aa --- /dev/null +++ b/logic/wonko/WonkoReference.cpp @@ -0,0 +1,44 @@ +/* Copyright 2015 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 "WonkoReference.h" + +WonkoReference::WonkoReference(const QString &uid) + : m_uid(uid) +{ +} + +QString WonkoReference::uid() const +{ + return m_uid; +} + +QString WonkoReference::version() const +{ + return m_version; +} +void WonkoReference::setVersion(const QString &version) +{ + m_version = version; +} + +bool WonkoReference::operator==(const WonkoReference &other) const +{ + return m_uid == other.m_uid && m_version == other.m_version; +} +bool WonkoReference::operator!=(const WonkoReference &other) const +{ + return m_uid != other.m_uid || m_version != other.m_version; +} diff --git a/logic/wonko/WonkoReference.h b/logic/wonko/WonkoReference.h new file mode 100644 index 00000000..73a85d76 --- /dev/null +++ b/logic/wonko/WonkoReference.h @@ -0,0 +1,41 @@ +/* Copyright 2015 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 <QString> +#include <QMetaType> + +#include "multimc_logic_export.h" + +class MULTIMC_LOGIC_EXPORT WonkoReference +{ +public: + WonkoReference() {} + explicit WonkoReference(const QString &uid); + + QString uid() const; + + QString version() const; + void setVersion(const QString &version); + + bool operator==(const WonkoReference &other) const; + bool operator!=(const WonkoReference &other) const; + +private: + QString m_uid; + QString m_version; +}; +Q_DECLARE_METATYPE(WonkoReference) diff --git a/logic/wonko/WonkoUtil.cpp b/logic/wonko/WonkoUtil.cpp new file mode 100644 index 00000000..94726c6b --- /dev/null +++ b/logic/wonko/WonkoUtil.cpp @@ -0,0 +1,47 @@ +/* Copyright 2015 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 "WonkoUtil.h" + +#include <QUrl> +#include <QDir> + +#include "Env.h" + +namespace Wonko +{ +QUrl rootUrl() +{ + return ENV.wonkoRootUrl(); +} +QUrl indexUrl() +{ + return rootUrl().resolved(QStringLiteral("index.json")); +} +QUrl versionListUrl(const QString &uid) +{ + return rootUrl().resolved(uid + ".json"); +} +QUrl versionUrl(const QString &uid, const QString &version) +{ + return rootUrl().resolved(uid + "/" + version + ".json"); +} + +QDir localWonkoDir() +{ + return QDir("wonko"); +} + +} diff --git a/logic/wonko/WonkoUtil.h b/logic/wonko/WonkoUtil.h new file mode 100644 index 00000000..b618ab71 --- /dev/null +++ b/logic/wonko/WonkoUtil.h @@ -0,0 +1,31 @@ +/* Copyright 2015 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 "multimc_logic_export.h" + +class QUrl; +class QString; +class QDir; + +namespace Wonko +{ +MULTIMC_LOGIC_EXPORT QUrl rootUrl(); +MULTIMC_LOGIC_EXPORT QUrl indexUrl(); +MULTIMC_LOGIC_EXPORT QUrl versionListUrl(const QString &uid); +MULTIMC_LOGIC_EXPORT QUrl versionUrl(const QString &uid, const QString &version); +MULTIMC_LOGIC_EXPORT QDir localWonkoDir(); +} diff --git a/logic/wonko/WonkoVersion.cpp b/logic/wonko/WonkoVersion.cpp new file mode 100644 index 00000000..7b7da86c --- /dev/null +++ b/logic/wonko/WonkoVersion.cpp @@ -0,0 +1,102 @@ +/* Copyright 2015 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 "WonkoVersion.h" + +#include <QDateTime> + +#include "tasks/BaseWonkoEntityLocalLoadTask.h" +#include "tasks/BaseWonkoEntityRemoteLoadTask.h" +#include "format/WonkoFormat.h" + +WonkoVersion::WonkoVersion(const QString &uid, const QString &version) + : BaseVersion(), m_uid(uid), m_version(version) +{ +} + +QString WonkoVersion::descriptor() +{ + return m_version; +} +QString WonkoVersion::name() +{ + return m_version; +} +QString WonkoVersion::typeString() const +{ + return m_type; +} + +QDateTime WonkoVersion::time() const +{ + return QDateTime::fromMSecsSinceEpoch(m_time * 1000, Qt::UTC); +} + +std::unique_ptr<Task> WonkoVersion::remoteUpdateTask() +{ + return std::unique_ptr<WonkoVersionRemoteLoadTask>(new WonkoVersionRemoteLoadTask(this, this)); +} +std::unique_ptr<Task> WonkoVersion::localUpdateTask() +{ + return std::unique_ptr<WonkoVersionLocalLoadTask>(new WonkoVersionLocalLoadTask(this, this)); +} + +void WonkoVersion::merge(const std::shared_ptr<BaseWonkoEntity> &other) +{ + WonkoVersionPtr version = std::dynamic_pointer_cast<WonkoVersion>(other); + if (m_type != version->m_type) + { + setType(version->m_type); + } + if (m_time != version->m_time) + { + setTime(version->m_time); + } + if (m_requires != version->m_requires) + { + setRequires(version->m_requires); + } + + setData(version->m_data); +} + +QString WonkoVersion::localFilename() const +{ + return m_uid + '/' + m_version + ".json"; +} +QJsonObject WonkoVersion::serialized() const +{ + return WonkoFormat::serializeVersion(this); +} + +void WonkoVersion::setType(const QString &type) +{ + m_type = type; + emit typeChanged(); +} +void WonkoVersion::setTime(const qint64 time) +{ + m_time = time; + emit timeChanged(); +} +void WonkoVersion::setRequires(const QVector<WonkoReference> &requires) +{ + m_requires = requires; + emit requiresChanged(); +} +void WonkoVersion::setData(const VersionFilePtr &data) +{ + m_data = data; +} diff --git a/logic/wonko/WonkoVersion.h b/logic/wonko/WonkoVersion.h new file mode 100644 index 00000000..a1de4d9b --- /dev/null +++ b/logic/wonko/WonkoVersion.h @@ -0,0 +1,83 @@ +/* Copyright 2015 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 "BaseVersion.h" +#include "BaseWonkoEntity.h" + +#include <QVector> +#include <QStringList> +#include <QJsonObject> +#include <memory> + +#include "minecraft/VersionFile.h" +#include "WonkoReference.h" + +#include "multimc_logic_export.h" + +using WonkoVersionPtr = std::shared_ptr<class WonkoVersion>; + +class MULTIMC_LOGIC_EXPORT WonkoVersion : public QObject, public BaseVersion, public BaseWonkoEntity +{ + Q_OBJECT + Q_PROPERTY(QString uid READ uid CONSTANT) + Q_PROPERTY(QString version READ version CONSTANT) + Q_PROPERTY(QString type READ type NOTIFY typeChanged) + Q_PROPERTY(QDateTime time READ time NOTIFY timeChanged) + Q_PROPERTY(QVector<WonkoReference> requires READ requires NOTIFY requiresChanged) +public: + explicit WonkoVersion(const QString &uid, const QString &version); + + QString descriptor() override; + QString name() override; + QString typeString() const override; + + QString uid() const { return m_uid; } + QString version() const { return m_version; } + QString type() const { return m_type; } + QDateTime time() const; + qint64 rawTime() const { return m_time; } + QVector<WonkoReference> requires() const { return m_requires; } + VersionFilePtr data() const { return m_data; } + + std::unique_ptr<Task> remoteUpdateTask() override; + std::unique_ptr<Task> localUpdateTask() override; + void merge(const std::shared_ptr<BaseWonkoEntity> &other) override; + + QString localFilename() const override; + QJsonObject serialized() const override; + +public: // for usage by format parsers only + void setType(const QString &type); + void setTime(const qint64 time); + void setRequires(const QVector<WonkoReference> &requires); + void setData(const VersionFilePtr &data); + +signals: + void typeChanged(); + void timeChanged(); + void requiresChanged(); + +private: + QString m_uid; + QString m_version; + QString m_type; + qint64 m_time; + QVector<WonkoReference> m_requires; + VersionFilePtr m_data; +}; + +Q_DECLARE_METATYPE(WonkoVersionPtr) diff --git a/logic/wonko/WonkoVersionList.cpp b/logic/wonko/WonkoVersionList.cpp new file mode 100644 index 00000000..e9d79327 --- /dev/null +++ b/logic/wonko/WonkoVersionList.cpp @@ -0,0 +1,283 @@ +/* Copyright 2015 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 "WonkoVersionList.h" + +#include <QDateTime> + +#include "WonkoVersion.h" +#include "tasks/BaseWonkoEntityRemoteLoadTask.h" +#include "tasks/BaseWonkoEntityLocalLoadTask.h" +#include "format/WonkoFormat.h" +#include "WonkoReference.h" + +class WVLLoadTask : public Task +{ + Q_OBJECT +public: + explicit WVLLoadTask(WonkoVersionList *list, QObject *parent = nullptr) + : Task(parent), m_list(list) + { + } + + bool canAbort() const override + { + return !m_currentTask || m_currentTask->canAbort(); + } + bool abort() override + { + return m_currentTask->abort(); + } + +private: + void executeTask() override + { + if (!m_list->isLocalLoaded()) + { + m_currentTask = m_list->localUpdateTask(); + connect(m_currentTask.get(), &Task::succeeded, this, &WVLLoadTask::next); + } + else + { + m_currentTask = m_list->remoteUpdateTask(); + connect(m_currentTask.get(), &Task::succeeded, this, &WVLLoadTask::emitSucceeded); + } + connect(m_currentTask.get(), &Task::status, this, &WVLLoadTask::setStatus); + connect(m_currentTask.get(), &Task::progress, this, &WVLLoadTask::setProgress); + connect(m_currentTask.get(), &Task::failed, this, &WVLLoadTask::emitFailed); + m_currentTask->start(); + } + + void next() + { + m_currentTask = m_list->remoteUpdateTask(); + connect(m_currentTask.get(), &Task::status, this, &WVLLoadTask::setStatus); + connect(m_currentTask.get(), &Task::progress, this, &WVLLoadTask::setProgress); + connect(m_currentTask.get(), &Task::succeeded, this, &WVLLoadTask::emitSucceeded); + m_currentTask->start(); + } + + WonkoVersionList *m_list; + std::unique_ptr<Task> m_currentTask; +}; + +WonkoVersionList::WonkoVersionList(const QString &uid, QObject *parent) + : BaseVersionList(parent), m_uid(uid) +{ + setObjectName("Wonko version list: " + uid); +} + +Task *WonkoVersionList::getLoadTask() +{ + return new WVLLoadTask(this); +} + +bool WonkoVersionList::isLoaded() +{ + return isLocalLoaded() && isRemoteLoaded(); +} + +const BaseVersionPtr WonkoVersionList::at(int i) const +{ + return m_versions.at(i); +} +int WonkoVersionList::count() const +{ + return m_versions.size(); +} + +void WonkoVersionList::sortVersions() +{ + beginResetModel(); + std::sort(m_versions.begin(), m_versions.end(), [](const WonkoVersionPtr &a, const WonkoVersionPtr &b) + { + return *a.get() < *b.get(); + }); + endResetModel(); +} + +QVariant WonkoVersionList::data(const QModelIndex &index, int role) const +{ + if (!index.isValid() || index.row() < 0 || index.row() >= m_versions.size() || index.parent().isValid()) + { + return QVariant(); + } + + WonkoVersionPtr version = m_versions.at(index.row()); + + switch (role) + { + case VersionPointerRole: return QVariant::fromValue(std::dynamic_pointer_cast<BaseVersion>(version)); + case VersionRole: + case VersionIdRole: + return version->version(); + case ParentGameVersionRole: + { + const auto end = version->requires().end(); + const auto it = std::find_if(version->requires().begin(), end, + [](const WonkoReference &ref) { return ref.uid() == "net.minecraft"; }); + if (it != end) + { + return (*it).version(); + } + return QVariant(); + } + case TypeRole: return version->type(); + + case UidRole: return version->uid(); + case TimeRole: return version->time(); + case RequiresRole: return QVariant::fromValue(version->requires()); + case SortRole: return version->rawTime(); + case WonkoVersionPtrRole: return QVariant::fromValue(version); + case RecommendedRole: return version == getRecommended(); + case LatestRole: return version == getLatestStable(); + default: return QVariant(); + } +} + +BaseVersionList::RoleList WonkoVersionList::providesRoles() const +{ + return {VersionPointerRole, VersionRole, VersionIdRole, ParentGameVersionRole, + TypeRole, UidRole, TimeRole, RequiresRole, SortRole, + RecommendedRole, LatestRole, WonkoVersionPtrRole}; +} + +QHash<int, QByteArray> WonkoVersionList::roleNames() const +{ + QHash<int, QByteArray> roles = BaseVersionList::roleNames(); + roles.insert(UidRole, "uid"); + roles.insert(TimeRole, "time"); + roles.insert(SortRole, "sort"); + roles.insert(RequiresRole, "requires"); + return roles; +} + +std::unique_ptr<Task> WonkoVersionList::remoteUpdateTask() +{ + return std::unique_ptr<WonkoVersionListRemoteLoadTask>(new WonkoVersionListRemoteLoadTask(this, this)); +} +std::unique_ptr<Task> WonkoVersionList::localUpdateTask() +{ + return std::unique_ptr<WonkoVersionListLocalLoadTask>(new WonkoVersionListLocalLoadTask(this, this)); +} + +QString WonkoVersionList::localFilename() const +{ + return m_uid + ".json"; +} +QJsonObject WonkoVersionList::serialized() const +{ + return WonkoFormat::serializeVersionList(this); +} + +QString WonkoVersionList::humanReadable() const +{ + return m_name.isEmpty() ? m_uid : m_name; +} + +bool WonkoVersionList::hasVersion(const QString &version) const +{ + return m_lookup.contains(version); +} +WonkoVersionPtr WonkoVersionList::getVersion(const QString &version) const +{ + return m_lookup.value(version); +} + +void WonkoVersionList::setName(const QString &name) +{ + m_name = name; + emit nameChanged(name); +} +void WonkoVersionList::setVersions(const QVector<WonkoVersionPtr> &versions) +{ + beginResetModel(); + m_versions = versions; + std::sort(m_versions.begin(), m_versions.end(), [](const WonkoVersionPtr &a, const WonkoVersionPtr &b) + { + return a->rawTime() > b->rawTime(); + }); + for (int i = 0; i < m_versions.size(); ++i) + { + m_lookup.insert(m_versions.at(i)->version(), m_versions.at(i)); + setupAddedVersion(i, m_versions.at(i)); + } + + m_latest = m_versions.isEmpty() ? nullptr : m_versions.first(); + auto recommendedIt = std::find_if(m_versions.constBegin(), m_versions.constEnd(), [](const WonkoVersionPtr &ptr) { return ptr->type() == "release"; }); + m_recommended = recommendedIt == m_versions.constEnd() ? nullptr : *recommendedIt; + endResetModel(); +} + +void WonkoVersionList::merge(const BaseWonkoEntity::Ptr &other) +{ + const WonkoVersionListPtr list = std::dynamic_pointer_cast<WonkoVersionList>(other); + if (m_name != list->m_name) + { + setName(list->m_name); + } + + if (m_versions.isEmpty()) + { + setVersions(list->m_versions); + } + else + { + for (const WonkoVersionPtr &version : list->m_versions) + { + if (m_lookup.contains(version->version())) + { + m_lookup.value(version->version())->merge(version); + } + else + { + beginInsertRows(QModelIndex(), m_versions.size(), m_versions.size()); + setupAddedVersion(m_versions.size(), version); + m_versions.append(version); + m_lookup.insert(version->uid(), version); + endInsertRows(); + + if (!m_latest || version->rawTime() > m_latest->rawTime()) + { + m_latest = version; |
