diff options
Diffstat (limited to 'api/logic/meta')
-rw-r--r-- | api/logic/meta/BaseEntity.cpp | 168 | ||||
-rw-r--r-- | api/logic/meta/BaseEntity.h | 68 | ||||
-rw-r--r-- | api/logic/meta/Index.cpp | 148 | ||||
-rw-r--r-- | api/logic/meta/Index.h | 71 | ||||
-rw-r--r-- | api/logic/meta/Index_test.cpp | 44 | ||||
-rw-r--r-- | api/logic/meta/JsonFormat.cpp | 218 | ||||
-rw-r--r-- | api/logic/meta/JsonFormat.h | 83 | ||||
-rw-r--r-- | api/logic/meta/Version.cpp | 140 | ||||
-rw-r--r-- | api/logic/meta/Version.h | 118 | ||||
-rw-r--r-- | api/logic/meta/VersionList.cpp | 245 | ||||
-rw-r--r-- | api/logic/meta/VersionList.h | 101 |
11 files changed, 0 insertions, 1404 deletions
diff --git a/api/logic/meta/BaseEntity.cpp b/api/logic/meta/BaseEntity.cpp deleted file mode 100644 index 5ff7a59a..00000000 --- a/api/logic/meta/BaseEntity.cpp +++ /dev/null @@ -1,168 +0,0 @@ -/* Copyright 2015-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 "BaseEntity.h" - -#include "Json.h" - -#include "net/Download.h" -#include "net/HttpMetaCache.h" -#include "net/NetJob.h" - -#include "Env.h" -#include "Json.h" - -#include "BuildConfig.h" - -class ParsingValidator : public Net::Validator -{ -public: /* con/des */ - ParsingValidator(Meta::BaseEntity *entity) : m_entity(entity) - { - }; - virtual ~ParsingValidator() - { - }; - -public: /* methods */ - bool init(QNetworkRequest &) override - { - return true; - } - bool write(QByteArray & data) override - { - this->data.append(data); - return true; - } - bool abort() override - { - return true; - } - bool validate(QNetworkReply &) override - { - auto fname = m_entity->localFilename(); - try - { - auto doc = Json::requireDocument(data, fname); - auto obj = Json::requireObject(doc, fname); - m_entity->parse(obj); - return true; - } - catch (const Exception &e) - { - qWarning() << "Unable to parse response:" << e.cause(); - return false; - } - } - -private: /* data */ - QByteArray data; - Meta::BaseEntity *m_entity; -}; - -Meta::BaseEntity::~BaseEntity() -{ -} - -QUrl Meta::BaseEntity::url() const -{ - return QUrl(BuildConfig.META_URL).resolved(localFilename()); -} - -bool Meta::BaseEntity::loadLocalFile() -{ - const QString fname = QDir("meta").absoluteFilePath(localFilename()); - if (!QFile::exists(fname)) - { - return false; - } - // TODO: check if the file has the expected checksum - try - { - auto doc = Json::requireDocument(fname, fname); - auto obj = Json::requireObject(doc, fname); - parse(obj); - return true; - } - catch (const Exception &e) - { - qDebug() << QString("Unable to parse file %1: %2").arg(fname, e.cause()); - // just make sure it's gone and we never consider it again. - QFile::remove(fname); - return false; - } -} - -void Meta::BaseEntity::load(Net::Mode loadType) -{ - // load local file if nothing is loaded yet - if(!isLoaded()) - { - if(loadLocalFile()) - { - m_loadStatus = LoadStatus::Local; - } - } - // if we need remote update, run the update task - if(loadType == Net::Mode::Offline || !shouldStartRemoteUpdate()) - { - return; - } - NetJob *job = new NetJob(QObject::tr("Download of meta file %1").arg(localFilename())); - auto url = this->url(); - auto entry = ENV.metacache()->resolveEntry("meta", localFilename()); - entry->setStale(true); - auto dl = Net::Download::makeCached(url, entry); - /* - * The validator parses the file and loads it into the object. - * If that fails, the file is not written to storage. - */ - dl->addValidator(new ParsingValidator(this)); - job->addNetAction(dl); - m_updateStatus = UpdateStatus::InProgress; - m_updateTask.reset(job); - QObject::connect(job, &NetJob::succeeded, [&]() - { - m_loadStatus = LoadStatus::Remote; - m_updateStatus = UpdateStatus::Succeeded; - m_updateTask.reset(); - }); - QObject::connect(job, &NetJob::failed, [&]() - { - m_updateStatus = UpdateStatus::Failed; - m_updateTask.reset(); - }); - m_updateTask->start(); -} - -bool Meta::BaseEntity::isLoaded() const -{ - return m_loadStatus > LoadStatus::NotLoaded; -} - -bool Meta::BaseEntity::shouldStartRemoteUpdate() const -{ - // TODO: version-locks and offline mode? - return m_updateStatus != UpdateStatus::InProgress; -} - -shared_qobject_ptr<Task> Meta::BaseEntity::getCurrentTask() -{ - if(m_updateStatus == UpdateStatus::InProgress) - { - return m_updateTask; - } - return nullptr; -} diff --git a/api/logic/meta/BaseEntity.h b/api/logic/meta/BaseEntity.h deleted file mode 100644 index 04a37420..00000000 --- a/api/logic/meta/BaseEntity.h +++ /dev/null @@ -1,68 +0,0 @@ -/* Copyright 2015-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 <QJsonObject> -#include <QObject> -#include "QObjectPtr.h" - -#include "multimc_logic_export.h" -#include "net/Mode.h" - -class Task; -namespace Meta -{ -class MULTIMC_LOGIC_EXPORT BaseEntity -{ -public: /* types */ - using Ptr = std::shared_ptr<BaseEntity>; - enum class LoadStatus - { - NotLoaded, - Local, - Remote - }; - enum class UpdateStatus - { - NotDone, - InProgress, - Failed, - Succeeded - }; - -public: - virtual ~BaseEntity(); - - virtual void parse(const QJsonObject &obj) = 0; - - virtual QString localFilename() const = 0; - virtual QUrl url() const; - - bool isLoaded() const; - bool shouldStartRemoteUpdate() const; - - void load(Net::Mode loadType); - shared_qobject_ptr<Task> getCurrentTask(); - -protected: /* methods */ - bool loadLocalFile(); - -private: - LoadStatus m_loadStatus = LoadStatus::NotLoaded; - UpdateStatus m_updateStatus = UpdateStatus::NotDone; - shared_qobject_ptr<Task> m_updateTask; -}; -} diff --git a/api/logic/meta/Index.cpp b/api/logic/meta/Index.cpp deleted file mode 100644 index 6802470d..00000000 --- a/api/logic/meta/Index.cpp +++ /dev/null @@ -1,148 +0,0 @@ -/* Copyright 2015-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 "Index.h" - -#include "VersionList.h" -#include "JsonFormat.h" - -namespace Meta -{ -Index::Index(QObject *parent) - : QAbstractListModel(parent) -{ -} -Index::Index(const QVector<VersionListPtr> &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 Index::data(const QModelIndex &index, int role) const -{ - if (index.parent().isValid() || index.row() < 0 || index.row() >= m_lists.size()) - { - return QVariant(); - } - - VersionListPtr 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 Index::rowCount(const QModelIndex &parent) const -{ - return m_lists.size(); -} -int Index::columnCount(const QModelIndex &parent) const -{ - return 1; -} -QVariant Index::headerData(int section, Qt::Orientation orientation, int role) const -{ - if (orientation == Qt::Horizontal && role == Qt::DisplayRole && section == 0) - { - return tr("Name"); - } - else - { - return QVariant(); - } -} - -bool Index::hasUid(const QString &uid) const -{ - return m_uids.contains(uid); -} - -VersionListPtr Index::get(const QString &uid) -{ - VersionListPtr out = m_uids.value(uid, nullptr); - if(!out) - { - out = std::make_shared<VersionList>(uid); - m_uids[uid] = out; - } - return out; -} - -VersionPtr Index::get(const QString &uid, const QString &version) -{ - auto list = get(uid); - return list->getVersion(version); -} - -void Index::parse(const QJsonObject& obj) -{ - parseIndex(obj, this); -} - -void Index::merge(const std::shared_ptr<Index> &other) -{ - const QVector<VersionListPtr> lists = std::dynamic_pointer_cast<Index>(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 VersionListPtr &list : lists) - { - if (m_uids.contains(list->uid())) - { - m_uids[list->uid()]->mergeFromIndex(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 Index::connectVersionList(const int row, const VersionListPtr &list) -{ - connect(list.get(), &VersionList::nameChanged, this, [this, row]() - { - emit dataChanged(index(row), index(row), QVector<int>() << Qt::DisplayRole); - }); -} -} diff --git a/api/logic/meta/Index.h b/api/logic/meta/Index.h deleted file mode 100644 index e9412e70..00000000 --- a/api/logic/meta/Index.h +++ /dev/null @@ -1,71 +0,0 @@ -/* Copyright 2015-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 <QAbstractListModel> -#include <memory> - -#include "BaseEntity.h" - -#include "multimc_logic_export.h" - -class Task; - -namespace Meta -{ -using VersionListPtr = std::shared_ptr<class VersionList>; -using VersionPtr = std::shared_ptr<class Version>; - -class MULTIMC_LOGIC_EXPORT Index : public QAbstractListModel, public BaseEntity -{ - Q_OBJECT -public: - explicit Index(QObject *parent = nullptr); - explicit Index(const QVector<VersionListPtr> &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; - - QString localFilename() const override { return "index.json"; } - - // queries - VersionListPtr get(const QString &uid); - VersionPtr get(const QString &uid, const QString &version); - bool hasUid(const QString &uid) const; - - QVector<VersionListPtr> lists() const { return m_lists; } - -public: // for usage by parsers only - void merge(const std::shared_ptr<Index> &other); - void parse(const QJsonObject &obj) override; - -private: - QVector<VersionListPtr> m_lists; - QHash<QString, VersionListPtr> m_uids; - - void connectVersionList(const int row, const VersionListPtr &list); -}; -} - diff --git a/api/logic/meta/Index_test.cpp b/api/logic/meta/Index_test.cpp deleted file mode 100644 index b0892070..00000000 --- a/api/logic/meta/Index_test.cpp +++ /dev/null @@ -1,44 +0,0 @@ -#include <QTest> -#include "TestUtil.h" - -#include "meta/Index.h" -#include "meta/VersionList.h" -#include "Env.h" - -class IndexTest : public QObject -{ - Q_OBJECT -private -slots: - void test_isProvidedByEnv() - { - QVERIFY(ENV.metadataIndex()); - QCOMPARE(ENV.metadataIndex(), ENV.metadataIndex()); - } - - void test_hasUid_and_getList() - { - Meta::Index windex({std::make_shared<Meta::VersionList>("list1"), std::make_shared<Meta::VersionList>("list2"), std::make_shared<Meta::VersionList>("list3")}); - QVERIFY(windex.hasUid("list1")); - QVERIFY(!windex.hasUid("asdf")); - QVERIFY(windex.get("list2") != nullptr); - QCOMPARE(windex.get("list2")->uid(), QString("list2")); - QVERIFY(windex.get("adsf") != nullptr); - } - - void test_merge() - { - Meta::Index windex({std::make_shared<Meta::VersionList>("list1"), std::make_shared<Meta::VersionList>("list2"), std::make_shared<Meta::VersionList>("list3")}); - QCOMPARE(windex.lists().size(), 3); - windex.merge(std::shared_ptr<Meta::Index>(new Meta::Index({std::make_shared<Meta::VersionList>("list1"), std::make_shared<Meta::VersionList>("list2"), std::make_shared<Meta::VersionList>("list3")}))); - QCOMPARE(windex.lists().size(), 3); - windex.merge(std::shared_ptr<Meta::Index>(new Meta::Index({std::make_shared<Meta::VersionList>("list4"), std::make_shared<Meta::VersionList>("list2"), std::make_shared<Meta::VersionList>("list5")}))); - QCOMPARE(windex.lists().size(), 5); - windex.merge(std::shared_ptr<Meta::Index>(new Meta::Index({std::make_shared<Meta::VersionList>("list6")}))); - QCOMPARE(windex.lists().size(), 6); - } -}; - -QTEST_GUILESS_MAIN(IndexTest) - -#include "Index_test.moc" diff --git a/api/logic/meta/JsonFormat.cpp b/api/logic/meta/JsonFormat.cpp deleted file mode 100644 index 796da4bb..00000000 --- a/api/logic/meta/JsonFormat.cpp +++ /dev/null @@ -1,218 +0,0 @@ -/* Copyright 2015-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 "JsonFormat.h" - -// FIXME: remove this from here... somehow -#include "minecraft/OneSixVersionFormat.h" -#include "Json.h" - -#include "Index.h" -#include "Version.h" -#include "VersionList.h" - -using namespace Json; - -namespace Meta -{ - -MetadataVersion currentFormatVersion() -{ - return MetadataVersion::InitialRelease; -} - -// Index -static std::shared_ptr<Index> parseIndexInternal(const QJsonObject &obj) -{ - const QVector<QJsonObject> objects = requireIsArrayOf<QJsonObject>(obj, "packages"); - QVector<VersionListPtr> lists; - lists.reserve(objects.size()); - std::transform(objects.begin(), objects.end(), std::back_inserter(lists), [](const QJsonObject &obj) - { - VersionListPtr list = std::make_shared<VersionList>(requireString(obj, "uid")); - list->setName(ensureString(obj, "name", QString())); - return list; - }); - return std::make_shared<Index>(lists); -} - -// Version -static VersionPtr parseCommonVersion(const QString &uid, const QJsonObject &obj) -{ - VersionPtr version = std::make_shared<Version>(uid, requireString(obj, "version")); - version->setTime(QDateTime::fromString(requireString(obj, "releaseTime"), Qt::ISODate).toMSecsSinceEpoch() / 1000); - version->setType(ensureString(obj, "type", QString())); - version->setRecommended(ensureBoolean(obj, QString("recommended"), false)); - version->setVolatile(ensureBoolean(obj, QString("volatile"), false)); - RequireSet requires, conflicts; - parseRequires(obj, &requires, "requires"); - parseRequires(obj, &conflicts, "conflicts"); - version->setRequires(requires, conflicts); - return version; -} - -static std::shared_ptr<Version> parseVersionInternal(const QJsonObject &obj) -{ - VersionPtr version = parseCommonVersion(requireString(obj, "uid"), obj); - - version->setData(OneSixVersionFormat::versionFileFromJson(QJsonDocument(obj), - QString("%1/%2.json").arg(version->uid(), version->version()), - obj.contains("order"))); - return version; -} - -// Version list / package -static std::shared_ptr<VersionList> parseVersionListInternal(const QJsonObject &obj) -{ - const QString uid = requireString(obj, "uid"); - - const QVector<QJsonObject> versionsRaw = requireIsArrayOf<QJsonObject>(obj, "versions"); - QVector<VersionPtr> versions; - versions.reserve(versionsRaw.size()); - std::transform(versionsRaw.begin(), versionsRaw.end(), std::back_inserter(versions), [uid](const QJsonObject &vObj) - { - auto version = parseCommonVersion(uid, vObj); - version->setProvidesRecommendations(); - return version; - }); - - VersionListPtr list = std::make_shared<VersionList>(uid); - list->setName(ensureString(obj, "name", QString())); - list->setVersions(versions); - return list; -} - - -MetadataVersion parseFormatVersion(const QJsonObject &obj, bool required) -{ - if (!obj.contains("formatVersion")) - { - if(required) - { - return MetadataVersion::Invalid; - } - return MetadataVersion::InitialRelease; - } - if (!obj.value("formatVersion").isDouble()) - { - return MetadataVersion::Invalid; - } - switch(obj.value("formatVersion").toInt()) - { - case 0: - case 1: - return MetadataVersion::InitialRelease; - default: - return MetadataVersion::Invalid; - } -} - -void serializeFormatVersion(QJsonObject& obj, Meta::MetadataVersion version) -{ - if(version == MetadataVersion::Invalid) - { - return; - } - obj.insert("formatVersion", int(version)); -} - -void parseIndex(const QJsonObject &obj, Index *ptr) -{ - const MetadataVersion version = parseFormatVersion(obj); - switch (version) - { - case MetadataVersion::InitialRelease: - ptr->merge(parseIndexInternal(obj)); - break; - case MetadataVersion::Invalid: - throw ParseException(QObject::tr("Unknown format version!")); - } -} - -void parseVersionList(const QJsonObject &obj, VersionList *ptr) -{ - const MetadataVersion version = parseFormatVersion(obj); - switch (version) - { - case MetadataVersion::InitialRelease: - ptr->merge(parseVersionListInternal(obj)); - break; - case MetadataVersion::Invalid: - throw ParseException(QObject::tr("Unknown format version!")); - } -} - -void parseVersion(const QJsonObject &obj, Version *ptr) -{ - const MetadataVersion version = parseFormatVersion(obj); - switch (version) - { - case MetadataVersion::InitialRelease: - ptr->merge(parseVersionInternal(obj)); - break; - case MetadataVersion::Invalid: - throw ParseException(QObject::tr("Unknown format version!")); - } -} - -/* -[ -{"uid":"foo", "equals":"version"} -] -*/ -void parseRequires(const QJsonObject& obj, RequireSet* ptr, const char * keyName) -{ - if(obj.contains(keyName)) - { - QSet<QString> requires; - auto reqArray = requireArray(obj, keyName); - auto iter = reqArray.begin(); - while(iter != reqArray.end()) - { - auto reqObject = requireObject(*iter); - auto uid = requireString(reqObject, "uid"); - auto equals = ensureString(reqObject, "equals", QString()); - auto suggests = ensureString(reqObject, "suggests", QString()); - ptr->insert({uid, equals, suggests}); - iter++; - } - } -} -void serializeRequires(QJsonObject& obj, RequireSet* ptr, const char * keyName) -{ - if(!ptr || ptr->empty()) - { - return; - } - QJsonArray arrOut; - for(auto &iter: *ptr) - { - QJsonObject reqOut; - reqOut.insert("uid", iter.uid); - if(!iter.equalsVersion.isEmpty()) - { - reqOut.insert("equals", iter.equalsVersion); - } - if(!iter.suggests.isEmpty()) - { - reqOut.insert("suggests", iter.suggests); - } - arrOut.append(reqOut); - } - obj.insert(keyName, arrOut); -} - -} - diff --git a/api/logic/meta/JsonFormat.h b/api/logic/meta/JsonFormat.h deleted file mode 100644 index 93217b7e..00000000 --- a/api/logic/meta/JsonFormat.h +++ /dev/null @@ -1,83 +0,0 @@ -/* Copyright 2015-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 <QJsonObject> -#include <memory> - -#include "Exception.h" -#include "meta/BaseEntity.h" -#include <set> - -namespace Meta -{ -class Index; -class Version; -class VersionList; - -enum class MetadataVersion -{ - Invalid = -1, - InitialRelease = 1 -}; - -class ParseException : public Exception -{ -public: - using Exception::Exception; -}; -struct Require -{ - bool operator==(const Require & rhs) const - { - return uid == rhs.uid; - } - bool operator<(const Require & rhs) const - { - return uid < rhs.uid; - } - bool deepEquals(const Require & rhs) const - { - return uid == rhs.uid - && equalsVersion == rhs.equalsVersion - && suggests == rhs.suggests; - } - QString uid; - QString equalsVersion; - QString suggests; -}; - -inline Q_DECL_PURE_FUNCTION uint qHash(const Require &key, uint seed = 0) Q_DECL_NOTHROW -{ - return qHash(key.uid, seed); -} - -using RequireSet = std::set<Require>; - -void parseIndex(const QJsonObject &obj, Index *ptr); -void parseVersion(const QJsonObject &obj, Version *ptr); -void parseVersionList(const QJsonObject &obj, VersionList *ptr); - -MetadataVersion parseFormatVersion(const QJsonObject &obj, bool required = true); -void serializeFormatVersion(QJsonObject &obj, MetadataVersion version); - -// FIXME: this has a different shape than the others...FIX IT!? -void parseRequires(const QJsonObject &obj, RequireSet * ptr, const char * keyName = "requires"); -void serializeRequires(QJsonObject & objOut, RequireSet* ptr, const char * keyName = "requires"); -MetadataVersion currentFormatVersion(); -} - -Q_DECLARE_METATYPE(std::set<Meta::Require>) diff --git a/api/logic/meta/Version.cpp b/api/logic/meta/Version.cpp deleted file mode 100644 index a8dc3169..00000000 --- a/api/logic/meta/Version.cpp +++ /dev/null @@ -1,140 +0,0 @@ -/* Copyright 2015-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 "Version.h" - -#include <QDateTime> - -#include "JsonFormat.h" -#include "minecraft/PackProfile.h" - -Meta::Version::Version(const QString &uid, const QString &version) - : BaseVersion(), m_uid(uid), m_version(version) -{ -} - -Meta::Version::~Version() -{ -} - -QString Meta::Version::descriptor() -{ - return m_version; -} -QString Meta::Version::name() -{ - if(m_data) - return m_data->name; - return m_uid; -} -QString Meta::Version::typeString() const -{ - return m_type; -} - -QDateTime Meta::Version::time() const -{ - return QDateTime::fromMSecsSinceEpoch(m_time * 1000, Qt::UTC); -} - -void Meta::Version::parse(const QJsonObject& obj) -{ - parseVersion(obj, this); -} - -void Meta::Version::mergeFromList(const Meta::VersionPtr& other) -{ - if(other->m_providesRecommendations) - { - if(m_recommended != other->m_recommended) - { - setRecommended(other->m_recommended); - } - } - if (m_type != other->m_type) - { - setType(other->m_type); - } - if (m_time != other->m_time) - { - setTime(other->m_time); - } - if (m_requires != other->m_requires) - { - m_requires = other->m_requires; - } - if (m_conflicts != other->m_conflicts) - { - m_conflicts = other->m_conflicts; - } - if(m_volatile != other->m_volatile) - { - setVolatile(other->m_volatile); - } -} - -void Meta::Version::merge(const VersionPtr &other) -{ - mergeFromList(other); - if(other->m_data) - { - setData(other->m_data); - } -} - -QString Meta::Version::localFilename() const -{ - return m_uid + '/' + m_version + ".json"; -} - -void Meta::Version::setType(const QString &type) -{ - m_type = type; - emit typeChanged(); -} - -void Meta::Version::setTime(const qint64 time) -{ - m_time = time; - emit timeChanged(); -} - -void Meta::Version::setRequires(const Meta::RequireSet &requires, const Meta::RequireSet &conflicts) -{ - m_requires = requires; - m_conflicts = conflicts; - emit requiresChanged(); -} - -void Meta::Version::setVolatile(bool volatile_) -{ - m_volatile = volatile_; -} - - -void Meta::Version::setData(const VersionFilePtr &data) -{ - m_data = data; -} - -void Meta::Version::setProvidesRecommendations() -{ - m_providesRecommendations = true; -} - -void Meta::Version::setRecommended(bool recommended) -{ - m_recommended = recommended; -} diff --git a/api/logic/meta/Version.h b/api/logic/meta/Version.h deleted file mode 100644 index a38d7bcd..00000000 --- a/api/logic/meta/Version.h +++ /dev/null @@ -1,118 +0,0 @@ -/* Copyright 2015-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 "BaseVersion.h" - -#include <QJsonObject> -#include <QStringList> -#include <QVector> -#include <memory> - -#include "minecraft/VersionFile.h" - -#include "BaseEntity.h" - -#include "multimc_logic_export.h" - -#include "JsonFormat.h" - -namespace Meta -{ -using VersionPtr = std::shared_ptr<class Version>; - -class MULTIMC_LOGIC_EXPORT Version : public QObject, public BaseVersion, public BaseEntity -{ - Q_OBJECT - -public: /* con/des */ - explicit Version(const QString &uid, const QString &version); - virtual ~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; - } - const Meta::RequireSet &requires() const - { - return m_requires; - } - VersionFilePtr data() const - { - return m_data; - } - bool isRecommended() const - { - return m_recommended; - } - bool isLoaded() const - { - return m_data != nullptr; - } - - void merge(const VersionPtr &other); - void mergeFromList(const VersionPtr &other); - void parse(const QJsonObject &obj) override; - - QString localFilename() const override; - -public: // for usage by format parsers only - void setType(const QString &type); - void setTime(const qint64 time); - void setRequires(const Meta::RequireSet &requires, const Meta::RequireSet &conflicts); - void setVolatile(bool volatile_); - void setRecommended(bool recommended); - void setProvidesRecommendations(); - void setData(const VersionFilePtr &data); - -signals: - void typeChanged(); - void timeChanged(); - void requiresChanged(); - -private: - bool m_providesRecommendations = false; - bool m_recommended = false; - QString m_name; - QString m_uid; - QString m_version; - QString m_type; - qint64 m_time = 0; - Meta::RequireSet m_requires; - Meta::RequireSet m_conflicts; - bool m_volatile = false; - VersionFilePtr m_data; -}; -} - -Q_DECLARE_METATYPE(Meta::VersionPtr) diff --git a/api/logic/meta/VersionList.cpp b/api/logic/meta/VersionList.cpp deleted file mode 100644 index 607007eb..00000000 --- a/api/logic/meta/VersionList.cpp +++ /dev/null @@ -1,245 +0,0 @@ -/* Copyright 2015-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 "VersionList.h" - -#include <QDateTime> - -#include "Version.h" -#include "JsonFormat.h" -#include "Version.h" - -namespace Meta -{ -VersionList::VersionList(const QString &uid, QObject *parent) - : BaseVersionList(parent), m_uid(uid) -{ - setObjectName("Version list: " + uid); -} - -shared_qobject_ptr<Task> VersionList::getLoadTask() -{ - load(Net::Mode::Online); - return getCurrentTask(); -} - -bool VersionList::isLoaded() -{ - return BaseEntity::isLoaded(); -} - -const BaseVersionPtr VersionList::at(int i) const -{ - return m_versions.at(i); -} -int VersionList::count() const -{ - return m_versions.size(); -} - -void VersionList::sortVersions() -{ - beginResetModel(); - std::sort(m_versions.begin(), m_versions.end(), [](const VersionPtr &a, const VersionPtr &b) - { - return *a.get() < *b.get(); - }); - endResetModel(); -} - -QVariant VersionList::data(const QModelIndex &index, int role) const -{ - if (!index.isValid() || index.row() < 0 || index.row() >= m_versions.size() || index.parent().isValid()) - { - return QVariant(); - } - - VersionPtr 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 ParentVersionRole: - { - // FIXME: HACK: this should be generic and be replaced by something else. Anything that is a hard 'equals' dep is a 'parent uid'. - auto & reqs = version->requires(); - auto iter = std::find_if(reqs.begin(), reqs.end(), [](const Require & req) - { - return req.uid == "net.minecraft"; - }); - if (iter != reqs.end()) - { - return (*iter).equalsVersion; - } - 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 VersionPtrRole: return QVariant::fromValue(version); - case RecommendedRole: return version->isRecommended(); - // FIXME: this should be determined in whatever view/proxy is used... - // case LatestRole: return version == getLatestStable(); - default: return QVariant(); - } -} - -BaseVersionList::RoleList VersionList::providesRoles() const -{ - return {VersionPointerRole, VersionRole, VersionIdRole, ParentVersionRole, - TypeRole, UidRole, TimeRole, RequiresRole, SortRole, - RecommendedRole, LatestRole, VersionPtrRole}; -} - -QHash<int, QByteArray> VersionList::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; -} - -QString VersionList::localFilename() const -{ - return m_uid + "/index.json"; -} - -QString VersionList::humanReadable() const -{ - return m_name.isEmpty() ? m_uid : m_name; -} - -VersionPtr VersionList::getVersion(const QString &version) -{ - VersionPtr out = m_lookup.value(version, nullptr); - if(!out) - { - out = std::make_shared<Version>(m_uid, version); - m_lookup[version] = out; - } - return out; -} - -void VersionList::setName(const QString &name) -{ - m_name = name; - emit nameChanged(name); -} - -void VersionList::setVersions(const QVector<VersionPtr> &versions) -{ - beginResetModel(); - m_versions = versions; - std::sort(m_versions.begin(), m_versions.end(), [](const VersionPtr &a, const VersionPtr &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)); - } - - // FIXME: this is dumb, we have 'recommended' as part of the metadata already... - auto recommendedIt = std::find_if(m_versions.constBegin(), m_versions.constEnd(), [](const VersionPtr &ptr) { return ptr->type() == "release"; }); - m_recommended = recommendedIt == m_versions.constEnd() ? nullptr : *recommendedIt; - endResetModel(); -} - -void VersionList::parse(const QJsonObject& obj) -{ - parseVersionList(obj, this); -} - -// FIXME: this is dumb, we have 'recommended' as part of the metadata already... -static const Meta::VersionPtr &getBetterVersion(const Meta::VersionPtr &a, const Meta::VersionPtr &b) -{ - if(!a) - return b; - if(!b) - return a; - if(a->type() == b->type()) - { - // newer of same type wins - return (a->rawTime() > b->rawTime() ? a : b); - } - // 'release' type wins - return (a->type() == "release" ? a : b); -} - -void VersionList::mergeFromIndex(const VersionListPtr &other) -{ - if (m_name != other->m_name) - { - setName(other->m_name); - } -} - -void VersionList::merge(const VersionListPtr &other) -{ - if (m_name != other->m_name) - { - setName(other->m_name); - } - - // TODO: do not reset the whole model. maybe? - beginResetModel(); - m_versions.clear(); - if(other->m_versions.isEmpty()) - { - qWarning() << "Empty list loaded ..."; - } - for (const VersionPtr &version : other->m_versions) - { - // we already have the version. merge the contents - if (m_lookup.contains(version->version())) - { - m_lookup.value(version->version())->mergeFromList(version); - } - else - { - m_lookup.insert(version->uid(), version); - } - // connect it. - setupAddedVersion(m_versions.size(), version); - m_versions.append(version); - m_recommended = getBetterVersion(m_recommended, version); - } - endResetModel(); -} - -void VersionList::setupAddedVersion(const int row, const VersionPtr &version) -{ - // FIXME: do not disconnect from everythin, disconnect only the lambdas here - version->disconnect(); - connect(version.get(), &Version::requiresChanged, this, [this, row]() { emit dataChanged(index(row), index(row), QVector<int>() << RequiresRole); }); - connect(version.get(), &Version::timeChanged, this, [this, row]() { emit dataChanged(index(row), index(row), QVector<int>() << TimeRole << SortRole); }); - connect(version.get(), &Version::typeChanged, this, [this, row]() { emit dataChanged(index(row), index(row), QVector<int>() << TypeRole); }); -} - -BaseVersionPtr VersionList::getRecommended() const -{ - return m_recommended; -} - -} diff --git a/api/logic/meta/VersionList.h b/api/logic/meta/VersionList.h deleted file mode 100644 index bba32ca3..00000000 --- a/api/logic/meta/VersionList.h +++ /dev/null @@ -1,101 +0,0 @@ -/* Copyright 2015-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 "BaseEntity.h" -#include "BaseVersionList.h" -#include <QJsonObject> -#include <memory> - -namespace Meta -{ -using VersionPtr = std::shared_ptr<class Version>; -using VersionListPtr = std::shared_ptr<class VersionList>; - -class MULTIMC_LOGIC_EXPORT VersionList : public BaseVersionList, public BaseEntity -{ - Q_OBJECT - Q_PROPERTY(QString uid READ uid CONSTANT) - Q_PROPERTY(QString name READ name NOTIFY nameChanged) -public: - explicit VersionList(const QString &uid, QObject *parent = nullptr); - - enum Roles - { - UidRole = Qt::UserRole + 100, - TimeRole, - RequiresRole, - VersionPtrRole - }; - - shared_qobject_ptr<Task> getLoadTask() override; - bool isLoaded() override; - const BaseVersionPtr at(int i) const override; - int count() const override; - void sortVersions() override; - - BaseVersionPtr getRecommended() const override; - - QVariant data(const QModelIndex &index, int role) const override; - RoleList providesRoles() const override; - QHash<int, QByteArray> roleNames() const override; - - QString localFilename() const override; - - QString uid() const - { - return m_uid; - } - QString name() const - { - return m_name; - } - QString humanReadable() const; - - VersionPtr getVersion(const QString &version); - - QVector<VersionPtr> versions() const - { - return m_versions; - } - -public: // for usage only by parsers - void setName(const QString &name); - void setVersions(const QVector<VersionPtr> &versions); - void merge(const VersionListPtr &other); - void mergeFromIndex(const VersionListPtr &other); - void parse(const QJsonObject &obj) override; - -signals: - void nameChanged(const QString &name); - -protected slots: - void updateListData(QList<BaseVersionPtr>) override - { - } - -private: - QVector<VersionPtr> m_versions; - QHash<QString, VersionPtr> m_lookup; - QString m_uid; - QString m_name; - - VersionPtr m_recommended; - - void setupAddedVersion(const int row, const VersionPtr &version); -}; -} -Q_DECLARE_METATYPE(Meta::VersionListPtr) |