aboutsummaryrefslogtreecommitdiff
path: root/logic
diff options
context:
space:
mode:
authorJan Dalheimer <jan@dalheimer.de>2016-04-06 23:09:30 +0200
committerPetr Mrázek <peterix@gmail.com>2016-04-30 23:59:23 +0200
commit00e5968bd28ab1df33b3a39dbac8cda99aa2a0d2 (patch)
treec930ca4f0edae9bb2bbd1a9ce2fddb2ca5a7bf32 /logic
parent5ae3b2c11416eb897a08b0d9531843d0357332f8 (diff)
downloadPrismLauncher-00e5968bd28ab1df33b3a39dbac8cda99aa2a0d2.tar.gz
PrismLauncher-00e5968bd28ab1df33b3a39dbac8cda99aa2a0d2.tar.bz2
PrismLauncher-00e5968bd28ab1df33b3a39dbac8cda99aa2a0d2.zip
NOISSUE Add a skeleton of the wonko system
Diffstat (limited to 'logic')
-rw-r--r--logic/BaseVersionList.cpp17
-rw-r--r--logic/BaseVersionList.h8
-rw-r--r--logic/CMakeLists.txt21
-rw-r--r--logic/Env.cpp11
-rw-r--r--logic/Env.h9
-rw-r--r--logic/Json.h32
-rw-r--r--logic/java/JavaInstallList.cpp2
-rw-r--r--logic/java/JavaInstallList.h2
-rw-r--r--logic/minecraft/MinecraftVersionList.cpp2
-rw-r--r--logic/minecraft/MinecraftVersionList.h2
-rw-r--r--logic/minecraft/forge/ForgeVersionList.cpp2
-rw-r--r--logic/minecraft/forge/ForgeVersionList.h2
-rw-r--r--logic/wonko/BaseWonkoEntity.cpp39
-rw-r--r--logic/wonko/BaseWonkoEntity.h51
-rw-r--r--logic/wonko/WonkoIndex.cpp147
-rw-r--r--logic/wonko/WonkoIndex.h68
-rw-r--r--logic/wonko/WonkoReference.cpp44
-rw-r--r--logic/wonko/WonkoReference.h41
-rw-r--r--logic/wonko/WonkoUtil.cpp47
-rw-r--r--logic/wonko/WonkoUtil.h31
-rw-r--r--logic/wonko/WonkoVersion.cpp102
-rw-r--r--logic/wonko/WonkoVersion.h83
-rw-r--r--logic/wonko/WonkoVersionList.cpp283
-rw-r--r--logic/wonko/WonkoVersionList.h92
-rw-r--r--logic/wonko/format/WonkoFormat.cpp80
-rw-r--r--logic/wonko/format/WonkoFormat.h54
-rw-r--r--logic/wonko/format/WonkoFormatV1.cpp156
-rw-r--r--logic/wonko/format/WonkoFormatV1.h30
-rw-r--r--logic/wonko/tasks/BaseWonkoEntityLocalLoadTask.cpp117
-rw-r--r--logic/wonko/tasks/BaseWonkoEntityLocalLoadTask.h81
-rw-r--r--logic/wonko/tasks/BaseWonkoEntityRemoteLoadTask.cpp126
-rw-r--r--logic/wonko/tasks/BaseWonkoEntityRemoteLoadTask.h85
32 files changed, 1841 insertions, 26 deletions
diff --git a/logic/BaseVersionList.cpp b/logic/BaseVersionList.cpp
index 73f4a7ef..b34f318c 100644
--- a/logic/BaseVersionList.cpp
+++ b/logic/BaseVersionList.cpp
@@ -72,7 +72,7 @@ QVariant BaseVersionList::data(const QModelIndex &index, int role) const
}
}
-BaseVersionList::RoleList BaseVersionList::providesRoles()
+BaseVersionList::RoleList BaseVersionList::providesRoles() const
{
return {VersionPointerRole, VersionRole, VersionIdRole, TypeRole};
}
@@ -87,3 +87,18 @@ int BaseVersionList::columnCount(const QModelIndex &parent) const
{
return 1;
}
+
+QHash<int, QByteArray> BaseVersionList::roleNames() const
+{
+ QHash<int, QByteArray> roles = QAbstractListModel::roleNames();
+ roles.insert(VersionRole, "version");
+ roles.insert(VersionIdRole, "versionId");
+ roles.insert(ParentGameVersionRole, "parentGameVersion");
+ roles.insert(RecommendedRole, "recommended");
+ roles.insert(LatestRole, "latest");
+ roles.insert(TypeRole, "type");
+ roles.insert(BranchRole, "branch");
+ roles.insert(PathRole, "path");
+ roles.insert(ArchitectureRole, "architecture");
+ return roles;
+}
diff --git a/logic/BaseVersionList.h b/logic/BaseVersionList.h
index 42ea77c0..73d2ee1f 100644
--- a/logic/BaseVersionList.h
+++ b/logic/BaseVersionList.h
@@ -50,9 +50,10 @@ public:
TypeRole,
BranchRole,
PathRole,
- ArchitectureRole
+ ArchitectureRole,
+ SortRole
};
- typedef QList<ModelRoles> RoleList;
+ typedef QList<int> RoleList;
explicit BaseVersionList(QObject *parent = 0);
@@ -78,9 +79,10 @@ public:
virtual QVariant data(const QModelIndex &index, int role) const;
virtual int rowCount(const QModelIndex &parent) const;
virtual int columnCount(const QModelIndex &parent) const;
+ virtual QHash<int, QByteArray> roleNames() const override;
//! which roles are provided by this version list?
- virtual RoleList providesRoles();
+ virtual RoleList providesRoles() const;
/*!
* \brief Finds a version by its descriptor.
diff --git a/logic/CMakeLists.txt b/logic/CMakeLists.txt
index 19236e1b..cd8aa246 100644
--- a/logic/CMakeLists.txt
+++ b/logic/CMakeLists.txt
@@ -313,6 +313,27 @@ set(LOGIC_SOURCES
tools/MCEditTool.cpp
tools/MCEditTool.h
+ # Wonko
+ wonko/tasks/BaseWonkoEntityRemoteLoadTask.cpp
+ wonko/tasks/BaseWonkoEntityRemoteLoadTask.h
+ wonko/tasks/BaseWonkoEntityLocalLoadTask.cpp
+ wonko/tasks/BaseWonkoEntityLocalLoadTask.h
+ wonko/format/WonkoFormatV1.cpp
+ wonko/format/WonkoFormatV1.h
+ wonko/format/WonkoFormat.cpp
+ wonko/format/WonkoFormat.h
+ wonko/BaseWonkoEntity.cpp
+ wonko/BaseWonkoEntity.h
+ wonko/WonkoVersionList.cpp
+ wonko/WonkoVersionList.h
+ wonko/WonkoVersion.cpp
+ wonko/WonkoVersion.h
+ wonko/WonkoIndex.cpp
+ wonko/WonkoIndex.h
+ wonko/WonkoUtil.cpp
+ wonko/WonkoUtil.h
+ wonko/WonkoReference.cpp
+ wonko/WonkoReference.h
)
################################ COMPILE ################################
diff --git a/logic/Env.cpp b/logic/Env.cpp
index c9093e77..d66ec184 100644
--- a/logic/Env.cpp
+++ b/logic/Env.cpp
@@ -8,6 +8,7 @@
#include <QNetworkAccessManager>
#include <QDebug>
#include "tasks/Task.h"
+#include "wonko/WonkoIndex.h"
#include <QDebug>
/*
@@ -138,6 +139,15 @@ void Env::registerVersionList(QString name, std::shared_ptr< BaseVersionList > v
m_versionLists[name] = vlist;
}
+std::shared_ptr<WonkoIndex> Env::wonkoIndex()
+{
+ if (!m_wonkoIndex)
+ {
+ m_wonkoIndex = std::make_shared<WonkoIndex>();
+ }
+ return m_wonkoIndex;
+}
+
void Env::initHttpMetaCache()
{
@@ -154,6 +164,7 @@ void Env::initHttpMetaCache()
m_metacache->addBase("root", QDir::currentPath());
m_metacache->addBase("translations", QDir("translations").absolutePath());
m_metacache->addBase("icons", QDir("cache/icons").absolutePath());
+ m_metacache->addBase("wonko", QDir("cache/wonko").absolutePath());
m_metacache->Load();
}
diff --git a/logic/Env.h b/logic/Env.h
index 806fa106..2b29acaa 100644
--- a/logic/Env.h
+++ b/logic/Env.h
@@ -11,6 +11,7 @@ class QNetworkAccessManager;
class HttpMetaCache;
class BaseVersionList;
class BaseVersion;
+class WonkoIndex;
#if defined(ENV)
#undef ENV
@@ -49,9 +50,17 @@ public:
std::shared_ptr<BaseVersion> getVersion(QString component, QString version);
void registerVersionList(QString name, std::shared_ptr<BaseVersionList> vlist);
+
+ std::shared_ptr<WonkoIndex> wonkoIndex();
+
+ QString wonkoRootUrl() const { return m_wonkoRootUrl; }
+ void setWonkoRootUrl(const QString &url) { m_wonkoRootUrl = url; }
+
protected:
std::shared_ptr<QNetworkAccessManager> m_qnam;
std::shared_ptr<HttpMetaCache> m_metacache;
std::shared_ptr<IconList> m_icons;
QMap<QString, std::shared_ptr<BaseVersionList>> m_versionLists;
+ std::shared_ptr<WonkoIndex> m_wonkoIndex;
+ QString m_wonkoRootUrl;
};
diff --git a/logic/Json.h b/logic/Json.h
index cb266c6e..2cb60f0e 100644
--- a/logic/Json.h
+++ b/logic/Json.h
@@ -113,9 +113,9 @@ template<> MULTIMC_LOGIC_EXPORT QUrl requireIsType<QUrl>(const QJsonValue &value
// the following functions are higher level functions, that make use of the above functions for
// type conversion
template <typename T>
-T ensureIsType(const QJsonValue &value, const T default_, const QString &what = "Value")
+T ensureIsType(const QJsonValue &value, const T default_ = T(), const QString &what = "Value")
{
- if (value.isUndefined())
+ if (value.isUndefined() || value.isNull())
{
return default_;
}
@@ -142,7 +142,7 @@ T requireIsType(const QJsonObject &parent, const QString &key, const QString &wh
}
template <typename T>
-T ensureIsType(const QJsonObject &parent, const QString &key, const T default_, const QString &what = "__placeholder__")
+T ensureIsType(const QJsonObject &parent, const QString &key, const T default_ = T(), const QString &what = "__placeholder__")
{
const QString localWhat = QString(what).replace("__placeholder__", '\'' + key + '\'');
if (!parent.contains(key))
@@ -153,10 +153,10 @@ T ensureIsType(const QJsonObject &parent, const QString &key, const T default_,
}
template <typename T>
-QList<T> requireIsArrayOf(const QJsonDocument &doc)
+QVector<T> requireIsArrayOf(const QJsonDocument &doc)
{
const QJsonArray array = requireArray(doc);
- QList<T> out;
+ QVector<T> out;
for (const QJsonValue val : array)
{
out.append(requireIsType<T>(val, "Document"));
@@ -165,19 +165,19 @@ QList<T> requireIsArrayOf(const QJsonDocument &doc)
}
template <typename T>
-QList<T> ensureIsArrayOf(const QJsonValue &value, const QString &what = "Value")
+QVector<T> ensureIsArrayOf(const QJsonValue &value, const QString &what = "Value")
{
- const QJsonArray array = requireIsType<QJsonArray>(value, what);
- QList<T> out;
+ const QJsonArray array = ensureIsType<QJsonArray>(value, QJsonArray(), what);
+ QVector<T> out;
for (const QJsonValue val : array)
{
- out.append(ensureIsType<T>(val, what));
+ out.append(requireIsType<T>(val, what));
}
return out;
}
template <typename T>
-QList<T> ensureIsArrayOf(const QJsonValue &value, const QList<T> default_, const QString &what = "Value")
+QVector<T> ensureIsArrayOf(const QJsonValue &value, const QVector<T> default_, const QString &what = "Value")
{
if (value.isUndefined())
{
@@ -188,19 +188,19 @@ QList<T> ensureIsArrayOf(const QJsonValue &value, const QList<T> default_, const
/// @throw JsonException
template <typename T>
-QList<T> requireIsArrayOf(const QJsonObject &parent, const QString &key, const QString &what = "__placeholder__")
+QVector<T> requireIsArrayOf(const QJsonObject &parent, const QString &key, const QString &what = "__placeholder__")
{
const QString localWhat = QString(what).replace("__placeholder__", '\'' + key + '\'');
if (!parent.contains(key))
{
throw JsonException(localWhat + "s parent does not contain " + localWhat);
}
- return requireIsArrayOf<T>(parent.value(key), localWhat);
+ return ensureIsArrayOf<T>(parent.value(key), localWhat);
}
template <typename T>
-QList<T> ensureIsArrayOf(const QJsonObject &parent, const QString &key,
- const QList<T> &default_, const QString &what = "__placeholder__")
+QVector<T> ensureIsArrayOf(const QJsonObject &parent, const QString &key,
+ const QVector<T> &default_ = QVector<T>(), const QString &what = "__placeholder__")
{
const QString localWhat = QString(what).replace("__placeholder__", '\'' + key + '\'');
if (!parent.contains(key))
@@ -216,7 +216,7 @@ QList<T> ensureIsArrayOf(const QJsonObject &parent, const QString &key,
{ \
return requireIsType<TYPE>(value, what); \
} \
- inline TYPE ensure##NAME(const QJsonValue &value, const TYPE default_, const QString &what = "Value") \
+ inline TYPE ensure##NAME(const QJsonValue &value, const TYPE default_ = TYPE(), const QString &what = "Value") \
{ \
return ensureIsType<TYPE>(value, default_, what); \
} \
@@ -224,7 +224,7 @@ QList<T> ensureIsArrayOf(const QJsonObject &parent, const QString &key,
{ \
return requireIsType<TYPE>(parent, key, what); \
} \
- inline TYPE ensure##NAME(const QJsonObject &parent, const QString &key, const TYPE default_, const QString &what = "__placeholder") \
+ inline TYPE ensure##NAME(const QJsonObject &parent, const QString &key, const TYPE default_ = TYPE(), const QString &what = "__placeholder") \
{ \
return ensureIsType<TYPE>(parent, key, default_, what); \
}
diff --git a/logic/java/JavaInstallList.cpp b/logic/java/JavaInstallList.cpp
index fbd8ee9b..c0729227 100644
--- a/logic/java/JavaInstallList.cpp
+++ b/logic/java/JavaInstallList.cpp
@@ -77,7 +77,7 @@ QVariant JavaInstallList::data(const QModelIndex &index, int role) const
}
}
-BaseVersionList::RoleList JavaInstallList::providesRoles()
+BaseVersionList::RoleList JavaInstallList::providesRoles() const
{
return {VersionPointerRole, VersionIdRole, VersionRole, RecommendedRole, PathRole, ArchitectureRole};
}
diff --git a/logic/java/JavaInstallList.h b/logic/java/JavaInstallList.h
index f2ec20f7..cf0e5784 100644
--- a/logic/java/JavaInstallList.h
+++ b/logic/java/JavaInstallList.h
@@ -41,7 +41,7 @@ public:
virtual void sortVersions() override;
virtual QVariant data(const QModelIndex &index, int role) const override;
- virtual RoleList providesRoles() override;
+ virtual RoleList providesRoles() const override;
public slots:
virtual void updateListData(QList<BaseVersionPtr> versions) override;
diff --git a/logic/minecraft/MinecraftVersionList.cpp b/logic/minecraft/MinecraftVersionList.cpp
index eab55c9a..a5cc3a39 100644
--- a/logic/minecraft/MinecraftVersionList.cpp
+++ b/logic/minecraft/MinecraftVersionList.cpp
@@ -307,7 +307,7 @@ QVariant MinecraftVersionList::data(const QModelIndex& index, int role) const
}
}
-BaseVersionList::RoleList MinecraftVersionList::providesRoles()
+BaseVersionList::RoleList MinecraftVersionList::providesRoles() const
{
return {VersionPointerRole, VersionRole, VersionIdRole, RecommendedRole, LatestRole, TypeRole};
}
diff --git a/logic/minecraft/MinecraftVersionList.h b/logic/minecraft/MinecraftVersionList.h
index 8643f0f0..0fca02a7 100644
--- a/logic/minecraft/MinecraftVersionList.h
+++ b/logic/minecraft/MinecraftVersionList.h
@@ -52,7 +52,7 @@ public:
virtual int count() const override;
virtual void sortVersions() override;
virtual QVariant data(const QModelIndex & index, int role) const override;
- virtual RoleList providesRoles() override;
+ virtual RoleList providesRoles() const override;
virtual BaseVersionPtr getLatestStable() const override;
virtual BaseVersionPtr getRecommended() const override;
diff --git a/logic/minecraft/forge/ForgeVersionList.cpp b/logic/minecraft/forge/ForgeVersionList.cpp
index 907672f2..de185e5f 100644
--- a/logic/minecraft/forge/ForgeVersionList.cpp
+++ b/logic/minecraft/forge/ForgeVersionList.cpp
@@ -89,7 +89,7 @@ QVariant ForgeVersionList::data(const QModelIndex &index, int role) const
}
}
-QList<BaseVersionList::ModelRoles> ForgeVersionList::providesRoles()
+BaseVersionList::RoleList ForgeVersionList::providesRoles() const
{
return {VersionPointerRole, VersionRole, VersionIdRole, ParentGameVersionRole, RecommendedRole, BranchRole};
}
diff --git a/logic/minecraft/forge/ForgeVersionList.h b/logic/minecraft/forge/ForgeVersionList.h
index 308503e3..62c08b2a 100644
--- a/logic/minecraft/forge/ForgeVersionList.h
+++ b/logic/minecraft/forge/ForgeVersionList.h
@@ -47,7 +47,7 @@ public:
ForgeVersionPtr findVersionByVersionNr(QString version);
virtual QVariant data(const QModelIndex &index, int role) const override;
- virtual QList<ModelRoles> providesRoles() override;
+ virtual RoleList providesRoles() const override;
virtual int columnCount(const QModelIndex &parent) const override;
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: