refactor(RD): move success callbacks from ModModel to ResourceModel
While implementing the resource pack downloader in another branch, I noticed that most of the code in the success callback was identical in both cases, safe for a few minute differences in strings. So, this tries to make it easier to share this piece of code. However, it still leaves the possibility of extending the methods in ResourceModel to accomodate for cases where this similarity may not hold. Signed-off-by: flow <flowlnlnln@gmail.com>
This commit is contained in:
parent
c3f0139f76
commit
3cff23dae2
@ -1,7 +1,5 @@
|
||||
#include "ModModel.h"
|
||||
|
||||
#include "Json.h"
|
||||
|
||||
#include "minecraft/MinecraftInstance.h"
|
||||
#include "minecraft/PackProfile.h"
|
||||
|
||||
@ -31,14 +29,6 @@ ResourceAPI::SearchArgs ModModel::createSearchArguments()
|
||||
|
||||
return { ModPlatform::ResourceType::MOD, m_next_search_offset, m_search_term, sort, profile->getModLoaders(), versions };
|
||||
}
|
||||
ResourceAPI::SearchCallbacks ModModel::createSearchCallbacks()
|
||||
{
|
||||
return { [this](auto& doc) {
|
||||
if (!s_running_models.constFind(this).value())
|
||||
return;
|
||||
searchRequestFinished(doc);
|
||||
} };
|
||||
}
|
||||
|
||||
ResourceAPI::VersionSearchArgs ModModel::createVersionsArguments(QModelIndex& entry)
|
||||
{
|
||||
@ -54,28 +44,12 @@ ResourceAPI::VersionSearchArgs ModModel::createVersionsArguments(QModelIndex& en
|
||||
|
||||
return { pack, versions, profile->getModLoaders() };
|
||||
}
|
||||
ResourceAPI::VersionSearchCallbacks ModModel::createVersionsCallbacks(QModelIndex& entry)
|
||||
{
|
||||
return { [this, entry](auto& doc, auto pack) {
|
||||
if (!s_running_models.constFind(this).value())
|
||||
return;
|
||||
versionRequestSucceeded(doc, pack, entry);
|
||||
} };
|
||||
}
|
||||
|
||||
ResourceAPI::ProjectInfoArgs ModModel::createInfoArguments(QModelIndex& entry)
|
||||
{
|
||||
auto& pack = m_packs[entry.row()];
|
||||
return { pack };
|
||||
}
|
||||
ResourceAPI::ProjectInfoCallbacks ModModel::createInfoCallbacks(QModelIndex& entry)
|
||||
{
|
||||
return { [this, entry](auto& doc, auto pack) {
|
||||
if (!s_running_models.constFind(this).value())
|
||||
return;
|
||||
infoRequestFinished(doc, pack, entry);
|
||||
} };
|
||||
}
|
||||
|
||||
void ModModel::searchWithTerm(const QString& term, unsigned int sort, bool filter_changed)
|
||||
{
|
||||
@ -89,97 +63,4 @@ void ModModel::searchWithTerm(const QString& term, unsigned int sort, bool filte
|
||||
refresh();
|
||||
}
|
||||
|
||||
/******** Request callbacks ********/
|
||||
|
||||
void ModModel::searchRequestFinished(QJsonDocument& doc)
|
||||
{
|
||||
QList<ModPlatform::IndexedPack> newList;
|
||||
auto packs = documentToArray(doc);
|
||||
|
||||
for (auto packRaw : packs) {
|
||||
auto packObj = packRaw.toObject();
|
||||
|
||||
ModPlatform::IndexedPack pack;
|
||||
try {
|
||||
loadIndexedPack(pack, packObj);
|
||||
newList.append(pack);
|
||||
} catch (const JSONValidationError& e) {
|
||||
qWarning() << "Error while loading mod from " << debugName() << ": " << e.cause();
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if (packs.size() < 25) {
|
||||
m_search_state = SearchState::Finished;
|
||||
} else {
|
||||
m_next_search_offset += 25;
|
||||
m_search_state = SearchState::CanFetchMore;
|
||||
}
|
||||
|
||||
// When you have a Qt build with assertions turned on, proceeding here will abort the application
|
||||
if (newList.size() == 0)
|
||||
return;
|
||||
|
||||
beginInsertRows(QModelIndex(), m_packs.size(), m_packs.size() + newList.size() - 1);
|
||||
m_packs.append(newList);
|
||||
endInsertRows();
|
||||
}
|
||||
|
||||
void ModModel::infoRequestFinished(QJsonDocument& doc, ModPlatform::IndexedPack& pack, const QModelIndex& index)
|
||||
{
|
||||
qDebug() << "Loading mod info";
|
||||
|
||||
auto current_pack = data(index, Qt::UserRole).value<ModPlatform::IndexedPack>();
|
||||
|
||||
// Check if the index is still valid for this mod or not
|
||||
if (pack.addonId != current_pack.addonId)
|
||||
return;
|
||||
|
||||
try {
|
||||
auto obj = Json::requireObject(doc);
|
||||
loadExtraPackInfo(current_pack, obj);
|
||||
} catch (const JSONValidationError& e) {
|
||||
qDebug() << doc;
|
||||
qWarning() << "Error while reading " << debugName() << " mod info: " << e.cause();
|
||||
}
|
||||
|
||||
// Cache info :^)
|
||||
QVariant new_pack;
|
||||
new_pack.setValue(current_pack);
|
||||
if (!setData(index, new_pack, Qt::UserRole)) {
|
||||
qWarning() << "Failed to cache mod info!";
|
||||
return;
|
||||
}
|
||||
|
||||
emit projectInfoUpdated();
|
||||
}
|
||||
|
||||
void ModModel::versionRequestSucceeded(QJsonDocument doc, ModPlatform::IndexedPack& pack, const QModelIndex& index)
|
||||
{
|
||||
auto arr = doc.isObject() ? Json::ensureArray(doc.object(), "data") : doc.array();
|
||||
|
||||
auto current_pack = data(index, Qt::UserRole).value<ModPlatform::IndexedPack>();
|
||||
|
||||
// Check if the index is still valid for this mod or not
|
||||
if (pack.addonId != current_pack.addonId)
|
||||
return;
|
||||
|
||||
try {
|
||||
loadIndexedPackVersions(current_pack, arr);
|
||||
} catch (const JSONValidationError& e) {
|
||||
qDebug() << doc;
|
||||
qWarning() << "Error while reading " << debugName() << " mod version: " << e.cause();
|
||||
}
|
||||
|
||||
// Cache info :^)
|
||||
QVariant new_pack;
|
||||
new_pack.setValue(current_pack);
|
||||
if (!setData(index, new_pack, Qt::UserRole)) {
|
||||
qWarning() << "Failed to cache mod versions!";
|
||||
return;
|
||||
}
|
||||
|
||||
emit versionListUpdated();
|
||||
}
|
||||
|
||||
} // namespace ResourceDownload
|
||||
|
@ -23,29 +23,19 @@ class ModModel : public ResourceModel {
|
||||
/* Ask the API for more information */
|
||||
void searchWithTerm(const QString& term, unsigned int sort, bool filter_changed);
|
||||
|
||||
virtual void loadIndexedPack(ModPlatform::IndexedPack& m, QJsonObject& obj) = 0;
|
||||
virtual void loadExtraPackInfo(ModPlatform::IndexedPack& m, QJsonObject& obj) = 0;
|
||||
virtual void loadIndexedPackVersions(ModPlatform::IndexedPack& m, QJsonArray& arr) = 0;
|
||||
void loadIndexedPack(ModPlatform::IndexedPack& m, QJsonObject& obj) override = 0;
|
||||
void loadExtraPackInfo(ModPlatform::IndexedPack& m, QJsonObject& obj) override = 0;
|
||||
void loadIndexedPackVersions(ModPlatform::IndexedPack& m, QJsonArray& arr) override = 0;
|
||||
|
||||
void setFilter(std::shared_ptr<ModFilterWidget::Filter> filter) { m_filter = filter; }
|
||||
|
||||
public slots:
|
||||
void searchRequestFinished(QJsonDocument& doc);
|
||||
void infoRequestFinished(QJsonDocument& doc, ModPlatform::IndexedPack& pack, const QModelIndex& index);
|
||||
void versionRequestSucceeded(QJsonDocument doc, ModPlatform::IndexedPack& pack, const QModelIndex& index);
|
||||
|
||||
public slots:
|
||||
ResourceAPI::SearchArgs createSearchArguments() override;
|
||||
ResourceAPI::SearchCallbacks createSearchCallbacks() override;
|
||||
|
||||
ResourceAPI::VersionSearchArgs createVersionsArguments(QModelIndex&) override;
|
||||
ResourceAPI::VersionSearchCallbacks createVersionsCallbacks(QModelIndex&) override;
|
||||
|
||||
ResourceAPI::ProjectInfoArgs createInfoArguments(QModelIndex&) override;
|
||||
ResourceAPI::ProjectInfoCallbacks createInfoCallbacks(QModelIndex&) override;
|
||||
|
||||
protected:
|
||||
virtual auto documentToArray(QJsonDocument& obj) const -> QJsonArray = 0;
|
||||
auto documentToArray(QJsonDocument& obj) const -> QJsonArray override = 0;
|
||||
|
||||
protected:
|
||||
std::shared_ptr<ModFilterWidget::Filter> m_filter = nullptr;
|
||||
|
@ -8,13 +8,11 @@
|
||||
|
||||
#include "Application.h"
|
||||
#include "BuildConfig.h"
|
||||
#include "Json.h"
|
||||
|
||||
#include "net/Download.h"
|
||||
#include "net/NetJob.h"
|
||||
|
||||
#include "minecraft/MinecraftInstance.h"
|
||||
#include "minecraft/PackProfile.h"
|
||||
|
||||
#include "modplatform/ModIndex.h"
|
||||
|
||||
#include "ui/widgets/ProjectItem.h"
|
||||
@ -129,9 +127,14 @@ void ResourceModel::search()
|
||||
auto args{ createSearchArguments() };
|
||||
|
||||
auto callbacks{ createSearchCallbacks() };
|
||||
Q_ASSERT(callbacks.on_succeed);
|
||||
|
||||
// Use defaults if no callbacks are set
|
||||
if (!callbacks.on_succeed)
|
||||
callbacks.on_succeed = [this](auto& doc) {
|
||||
if (!s_running_models.constFind(this).value())
|
||||
return;
|
||||
searchRequestSucceeded(doc);
|
||||
};
|
||||
if (!callbacks.on_fail)
|
||||
callbacks.on_fail = [this](QString reason, int network_error_code) {
|
||||
if (!s_running_models.constFind(this).value())
|
||||
@ -160,6 +163,14 @@ void ResourceModel::loadEntry(QModelIndex& entry)
|
||||
auto args{ createVersionsArguments(entry) };
|
||||
auto callbacks{ createVersionsCallbacks(entry) };
|
||||
|
||||
// Use default if no callbacks are set
|
||||
if (!callbacks.on_succeed)
|
||||
callbacks.on_succeed = [this, entry](auto& doc, auto pack) {
|
||||
if (!s_running_models.constFind(this).value())
|
||||
return;
|
||||
versionRequestSucceeded(doc, pack, entry);
|
||||
};
|
||||
|
||||
if (auto job = m_api->getProjectVersions(std::move(args), std::move(callbacks)); job)
|
||||
runInfoJob(job);
|
||||
}
|
||||
@ -168,6 +179,14 @@ void ResourceModel::loadEntry(QModelIndex& entry)
|
||||
auto args{ createInfoArguments(entry) };
|
||||
auto callbacks{ createInfoCallbacks(entry) };
|
||||
|
||||
// Use default if no callbacks are set
|
||||
if (!callbacks.on_succeed)
|
||||
callbacks.on_succeed = [this, entry](auto& doc, auto pack) {
|
||||
if (!s_running_models.constFind(this).value())
|
||||
return;
|
||||
infoRequestSucceeded(doc, pack, entry);
|
||||
};
|
||||
|
||||
if (auto job = m_api->getProjectInfo(std::move(args), std::move(callbacks)); job)
|
||||
runInfoJob(job);
|
||||
}
|
||||
@ -279,6 +298,64 @@ std::optional<QIcon> ResourceModel::getIcon(QModelIndex& index, const QUrl& url)
|
||||
return {};
|
||||
}
|
||||
|
||||
// No 'forgor to implement' shall pass here :blobfox_knife:
|
||||
#define NEED_FOR_CALLBACK_ASSERT(name) \
|
||||
Q_ASSERT_X(0 != 0, #name, "You NEED to re-implement this if you intend on using the default callbacks.")
|
||||
|
||||
QJsonArray ResourceModel::documentToArray(QJsonDocument& doc) const
|
||||
{
|
||||
NEED_FOR_CALLBACK_ASSERT("documentToArray");
|
||||
return {};
|
||||
}
|
||||
void ResourceModel::loadIndexedPack(ModPlatform::IndexedPack&, QJsonObject&)
|
||||
{
|
||||
NEED_FOR_CALLBACK_ASSERT("loadIndexedPack");
|
||||
}
|
||||
void ResourceModel::loadExtraPackInfo(ModPlatform::IndexedPack&, QJsonObject&)
|
||||
{
|
||||
NEED_FOR_CALLBACK_ASSERT("loadExtraPackInfo");
|
||||
}
|
||||
void ResourceModel::loadIndexedPackVersions(ModPlatform::IndexedPack&, QJsonArray&)
|
||||
{
|
||||
NEED_FOR_CALLBACK_ASSERT("loadIndexedPackVersions");
|
||||
}
|
||||
|
||||
/* Default callbacks */
|
||||
|
||||
void ResourceModel::searchRequestSucceeded(QJsonDocument& doc)
|
||||
{
|
||||
QList<ModPlatform::IndexedPack> newList;
|
||||
auto packs = documentToArray(doc);
|
||||
|
||||
for (auto packRaw : packs) {
|
||||
auto packObj = packRaw.toObject();
|
||||
|
||||
ModPlatform::IndexedPack pack;
|
||||
try {
|
||||
loadIndexedPack(pack, packObj);
|
||||
newList.append(pack);
|
||||
} catch (const JSONValidationError& e) {
|
||||
qWarning() << "Error while loading resource from " << debugName() << ": " << e.cause();
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if (packs.size() < 25) {
|
||||
m_search_state = SearchState::Finished;
|
||||
} else {
|
||||
m_next_search_offset += 25;
|
||||
m_search_state = SearchState::CanFetchMore;
|
||||
}
|
||||
|
||||
// When you have a Qt build with assertions turned on, proceeding here will abort the application
|
||||
if (newList.size() == 0)
|
||||
return;
|
||||
|
||||
beginInsertRows(QModelIndex(), m_packs.size(), m_packs.size() + newList.size() - 1);
|
||||
m_packs.append(newList);
|
||||
endInsertRows();
|
||||
}
|
||||
|
||||
void ResourceModel::searchRequestFailed(QString reason, int network_error_code)
|
||||
{
|
||||
switch (network_error_code) {
|
||||
@ -289,8 +366,7 @@ void ResourceModel::searchRequestFailed(QString reason, int network_error_code)
|
||||
case 409:
|
||||
// 409 Gone, notify user to update
|
||||
QMessageBox::critical(nullptr, tr("Error"),
|
||||
QString("%1")
|
||||
.arg(tr("API version too old!\nPlease update %1!").arg(BuildConfig.LAUNCHER_DISPLAYNAME)));
|
||||
QString("%1").arg(tr("API version too old!\nPlease update %1!").arg(BuildConfig.LAUNCHER_DISPLAYNAME)));
|
||||
break;
|
||||
}
|
||||
|
||||
@ -309,4 +385,58 @@ void ResourceModel::searchRequestAborted()
|
||||
search();
|
||||
}
|
||||
|
||||
void ResourceModel::versionRequestSucceeded(QJsonDocument& doc, ModPlatform::IndexedPack& pack, const QModelIndex& index)
|
||||
{
|
||||
auto current_pack = data(index, Qt::UserRole).value<ModPlatform::IndexedPack>();
|
||||
|
||||
// Check if the index is still valid for this resource or not
|
||||
if (pack.addonId != current_pack.addonId)
|
||||
return;
|
||||
|
||||
try {
|
||||
auto arr = doc.isObject() ? Json::ensureArray(doc.object(), "data") : doc.array();
|
||||
loadIndexedPackVersions(current_pack, arr);
|
||||
} catch (const JSONValidationError& e) {
|
||||
qDebug() << doc;
|
||||
qWarning() << "Error while reading " << debugName() << " resource version: " << e.cause();
|
||||
}
|
||||
|
||||
// Cache info :^)
|
||||
QVariant new_pack;
|
||||
new_pack.setValue(current_pack);
|
||||
if (!setData(index, new_pack, Qt::UserRole)) {
|
||||
qWarning() << "Failed to cache resource versions!";
|
||||
return;
|
||||
}
|
||||
|
||||
emit versionListUpdated();
|
||||
}
|
||||
|
||||
void ResourceModel::infoRequestSucceeded(QJsonDocument& doc, ModPlatform::IndexedPack& pack, const QModelIndex& index)
|
||||
{
|
||||
auto current_pack = data(index, Qt::UserRole).value<ModPlatform::IndexedPack>();
|
||||
|
||||
// Check if the index is still valid for this resource or not
|
||||
if (pack.addonId != current_pack.addonId)
|
||||
return;
|
||||
|
||||
try {
|
||||
auto obj = Json::requireObject(doc);
|
||||
loadExtraPackInfo(current_pack, obj);
|
||||
} catch (const JSONValidationError& e) {
|
||||
qDebug() << doc;
|
||||
qWarning() << "Error while reading " << debugName() << " resource info: " << e.cause();
|
||||
}
|
||||
|
||||
// Cache info :^)
|
||||
QVariant new_pack;
|
||||
new_pack.setValue(current_pack);
|
||||
if (!setData(index, new_pack, Qt::UserRole)) {
|
||||
qWarning() << "Failed to cache resource info!";
|
||||
return;
|
||||
}
|
||||
|
||||
emit projectInfoUpdated();
|
||||
}
|
||||
|
||||
} // namespace ResourceDownload
|
||||
|
@ -57,13 +57,13 @@ class ResourceModel : public QAbstractListModel {
|
||||
void setSearchTerm(QString term) { m_search_term = term; }
|
||||
|
||||
virtual ResourceAPI::SearchArgs createSearchArguments() = 0;
|
||||
virtual ResourceAPI::SearchCallbacks createSearchCallbacks() = 0;
|
||||
virtual ResourceAPI::SearchCallbacks createSearchCallbacks() { return {}; }
|
||||
|
||||
virtual ResourceAPI::VersionSearchArgs createVersionsArguments(QModelIndex&) = 0;
|
||||
virtual ResourceAPI::VersionSearchCallbacks createVersionsCallbacks(QModelIndex&) = 0;
|
||||
virtual ResourceAPI::VersionSearchCallbacks createVersionsCallbacks(QModelIndex&) { return {}; }
|
||||
|
||||
virtual ResourceAPI::ProjectInfoArgs createInfoArguments(QModelIndex&) = 0;
|
||||
virtual ResourceAPI::ProjectInfoCallbacks createInfoCallbacks(QModelIndex&) = 0;
|
||||
virtual ResourceAPI::ProjectInfoCallbacks createInfoCallbacks(QModelIndex&) { return {}; }
|
||||
|
||||
/** Requests the API for more entries. */
|
||||
virtual void search();
|
||||
@ -86,6 +86,22 @@ class ResourceModel : public QAbstractListModel {
|
||||
|
||||
[[nodiscard]] auto getCurrentSortingMethodByIndex() const -> std::optional<ResourceAPI::SortingMethod>;
|
||||
|
||||
/** Converts a JSON document to a common array format.
|
||||
*
|
||||
* This is needed so that different providers, with different JSON structures, can be parsed
|
||||
* uniformally. You NEED to re-implement this if you intend on using the default callbacks.
|
||||
*/
|
||||
[[nodiscard]] virtual auto documentToArray(QJsonDocument&) const -> QJsonArray;
|
||||
|
||||
/** Functions to load data into a pack.
|
||||
*
|
||||
* Those are needed for the same reason as ddocumentToArray, and NEED to be re-implemented in the same way.
|
||||
*/
|
||||
|
||||
virtual void loadIndexedPack(ModPlatform::IndexedPack&, QJsonObject&);
|
||||
virtual void loadExtraPackInfo(ModPlatform::IndexedPack&, QJsonObject&);
|
||||
virtual void loadIndexedPackVersions(ModPlatform::IndexedPack&, QJsonArray&);
|
||||
|
||||
protected:
|
||||
const BaseInstance& m_base_instance;
|
||||
|
||||
@ -114,9 +130,14 @@ class ResourceModel : public QAbstractListModel {
|
||||
|
||||
private:
|
||||
/* Default search request callbacks */
|
||||
void searchRequestSucceeded(QJsonDocument&);
|
||||
void searchRequestFailed(QString reason, int network_error_code);
|
||||
void searchRequestAborted();
|
||||
|
||||
void versionRequestSucceeded(QJsonDocument&, ModPlatform::IndexedPack&, const QModelIndex&);
|
||||
|
||||
void infoRequestSucceeded(QJsonDocument&, ModPlatform::IndexedPack&, const QModelIndex&);
|
||||
|
||||
signals:
|
||||
void versionListUpdated();
|
||||
void projectInfoUpdated();
|
||||
|
Loading…
Reference in New Issue
Block a user