diff options
Diffstat (limited to 'launcher/ui/pages/modplatform/ResourceModel.h')
-rw-r--r-- | launcher/ui/pages/modplatform/ResourceModel.h | 101 |
1 files changed, 101 insertions, 0 deletions
diff --git a/launcher/ui/pages/modplatform/ResourceModel.h b/launcher/ui/pages/modplatform/ResourceModel.h new file mode 100644 index 00000000..af0e9f55 --- /dev/null +++ b/launcher/ui/pages/modplatform/ResourceModel.h @@ -0,0 +1,101 @@ +#pragma once + +#include <optional> + +#include <QAbstractListModel> + +#include "QObjectPtr.h" +#include "modplatform/ResourceAPI.h" +#include "tasks/ConcurrentTask.h" + +class NetJob; +class ResourcePage; +class ResourceAPI; + +namespace ModPlatform { +struct IndexedPack; +} + + +class ResourceModel : public QAbstractListModel { + Q_OBJECT + + public: + ResourceModel(ResourcePage* parent, ResourceAPI* api); + ~ResourceModel() override; + + [[nodiscard]] auto data(const QModelIndex&, int role) const -> QVariant override; + bool setData(const QModelIndex& index, const QVariant& value, int role) override; + + [[nodiscard]] auto debugName() const -> QString; + + [[nodiscard]] inline int rowCount(const QModelIndex& parent) const override { return parent.isValid() ? 0 : m_packs.size(); } + [[nodiscard]] inline int columnCount(const QModelIndex& parent) const override { return parent.isValid() ? 0 : 1; }; + [[nodiscard]] inline auto flags(const QModelIndex& index) const -> Qt::ItemFlags override { return QAbstractListModel::flags(index); }; + + inline void addActiveJob(Task::Ptr ptr) { m_current_job.addTask(ptr); if (!m_current_job.isRunning()) m_current_job.start(); } + inline Task const& activeJob() { return m_current_job; } + + public slots: + void fetchMore(const QModelIndex& parent) override; + [[nodiscard]] inline bool canFetchMore(const QModelIndex& parent) const override + { + return parent.isValid() ? false : m_search_state == SearchState::CanFetchMore; + } + + void setSearchTerm(QString term) { m_search_term = term; } + + virtual ResourceAPI::SearchArgs createSearchArguments() = 0; + virtual ResourceAPI::SearchCallbacks createSearchCallbacks() = 0; + + virtual ResourceAPI::VersionSearchArgs createVersionsArguments(QModelIndex&) = 0; + virtual ResourceAPI::VersionSearchCallbacks createVersionsCallbacks(QModelIndex&) = 0; + + virtual ResourceAPI::ProjectInfoArgs createInfoArguments(QModelIndex&) = 0; + virtual ResourceAPI::ProjectInfoCallbacks createInfoCallbacks(QModelIndex&) = 0; + + /** Requests the API for more entries. */ + virtual void search(); + + /** Applies any processing / extra requests needed to fully load the specified entry's information. */ + virtual void loadEntry(QModelIndex&); + + /** Schedule a refresh, clearing the current state. */ + void refresh(); + + /** Gets the icon at the URL for the given index. If it's not fetched yet, fetch it and update when fisinhed. */ + std::optional<QIcon> getIcon(QModelIndex&, const QUrl&); + + protected: + /** Resets the model's data. */ + void clearData(); + + [[nodiscard]] bool isPackSelected(const ModPlatform::IndexedPack&) const; + + protected: + /* Basic search parameters */ + enum class SearchState { None, CanFetchMore, ResetRequested, Finished } m_search_state = SearchState::None; + int m_next_search_offset = 0; + QString m_search_term; + + std::unique_ptr<ResourceAPI> m_api; + + ConcurrentTask m_current_job; + + shared_qobject_ptr<NetJob> m_current_icon_job; + QSet<QUrl> m_currently_running_icon_actions; + QSet<QUrl> m_failed_icon_actions; + + ResourcePage* m_associated_page = nullptr; + + QList<ModPlatform::IndexedPack> m_packs; + + // HACK: We need this to prevent callbacks from calling the model after it has already been deleted. + // This leaks a tiny bit of memory per time the user has opened a resource dialog. How to make this better? + static QHash<ResourceModel*, bool> s_running_models; + + private: + /* Default search request callbacks */ + void searchRequestFailed(QString reason, int network_error_code); + void searchRequestAborted(); +}; |