add curseforge modpack filter
Signed-off-by: Trial97 <alexandru.tripon97@gmail.com>
This commit is contained in:
parent
44b4262f3c
commit
dfe3cd849d
15 changed files with 242 additions and 75 deletions
|
@ -1,6 +1,7 @@
|
|||
#include "FlameModel.h"
|
||||
#include <Json.h>
|
||||
#include "Application.h"
|
||||
#include "modplatform/ModIndex.h"
|
||||
#include "modplatform/ResourceAPI.h"
|
||||
#include "modplatform/flame/FlameAPI.h"
|
||||
#include "ui/widgets/ProjectItem.h"
|
||||
|
@ -183,34 +184,28 @@ void ListModel::performPaginatedSearch()
|
|||
return;
|
||||
}
|
||||
}
|
||||
auto netJob = makeShared<NetJob>("Flame::Search", APPLICATION->network());
|
||||
auto searchUrl = QString(
|
||||
"https://api.curseforge.com/v1/mods/search?"
|
||||
"gameId=432&"
|
||||
"classId=4471&"
|
||||
"index=%1&"
|
||||
"pageSize=25&"
|
||||
"searchFilter=%2&"
|
||||
"sortField=%3&"
|
||||
"sortOrder=desc")
|
||||
.arg(nextSearchOffset)
|
||||
.arg(currentSearchTerm)
|
||||
.arg(currentSort + 1);
|
||||
ResourceAPI::SortingMethod sort{};
|
||||
sort.index = currentSort + 1;
|
||||
|
||||
netJob->addNetAction(Net::ApiDownload::makeByteArray(QUrl(searchUrl), response));
|
||||
auto netJob = makeShared<NetJob>("Flame::Search", APPLICATION->network());
|
||||
auto searchUrl = FlameAPI::getStaticSearchURL({ ModPlatform::ResourceType::MODPACK, nextSearchOffset, currentSearchTerm, sort,
|
||||
m_filter->loaders, m_filter->versions, "", m_filter->categoryIds });
|
||||
|
||||
netJob->addNetAction(Net::ApiDownload::makeByteArray(QUrl(searchUrl.value()), response));
|
||||
jobPtr = netJob;
|
||||
jobPtr->start();
|
||||
QObject::connect(netJob.get(), &NetJob::succeeded, this, &ListModel::searchRequestFinished);
|
||||
QObject::connect(netJob.get(), &NetJob::failed, this, &ListModel::searchRequestFailed);
|
||||
}
|
||||
|
||||
void ListModel::searchWithTerm(const QString& term, int sort)
|
||||
void ListModel::searchWithTerm(const QString& term, int sort, std::shared_ptr<ModFilterWidget::Filter> filter, bool filterChanged)
|
||||
{
|
||||
if (currentSearchTerm == term && currentSearchTerm.isNull() == term.isNull() && currentSort == sort) {
|
||||
if (currentSearchTerm == term && currentSearchTerm.isNull() == term.isNull() && currentSort == sort && !filterChanged) {
|
||||
return;
|
||||
}
|
||||
currentSearchTerm = term;
|
||||
currentSort = sort;
|
||||
m_filter = filter;
|
||||
if (hasActiveSearchJob()) {
|
||||
jobPtr->abort();
|
||||
searchState = ResetRequested;
|
||||
|
|
|
@ -14,6 +14,7 @@
|
|||
|
||||
#include <net/NetJob.h>
|
||||
#include <functional>
|
||||
#include "ui/widgets/ModFilterWidget.h"
|
||||
|
||||
#include <modplatform/flame/FlamePackIndex.h>
|
||||
|
||||
|
@ -38,7 +39,7 @@ class ListModel : public QAbstractListModel {
|
|||
void fetchMore(const QModelIndex& parent) override;
|
||||
|
||||
void getLogo(const QString& logo, const QString& logoUrl, LogoCallback callback);
|
||||
void searchWithTerm(const QString& term, int sort);
|
||||
void searchWithTerm(const QString& term, int sort, std::shared_ptr<ModFilterWidget::Filter> filter, bool filterChanged);
|
||||
|
||||
[[nodiscard]] bool hasActiveSearchJob() const { return jobPtr && jobPtr->isRunning(); }
|
||||
[[nodiscard]] Task::Ptr activeSearchJob() { return hasActiveSearchJob() ? jobPtr : nullptr; }
|
||||
|
@ -65,6 +66,7 @@ class ListModel : public QAbstractListModel {
|
|||
|
||||
QString currentSearchTerm;
|
||||
int currentSort = 0;
|
||||
std::shared_ptr<ModFilterWidget::Filter> m_filter;
|
||||
int nextSearchOffset = 0;
|
||||
enum SearchState { None, CanPossiblyFetchMore, ResetRequested, Finished } searchState = None;
|
||||
Task::Ptr jobPtr;
|
||||
|
|
|
@ -34,10 +34,13 @@
|
|||
*/
|
||||
|
||||
#include "FlamePage.h"
|
||||
#include "modplatform/flame/FlamePackIndex.h"
|
||||
#include "ui/dialogs/CustomMessageBox.h"
|
||||
#include "ui/widgets/ModFilterWidget.h"
|
||||
#include "ui_FlamePage.h"
|
||||
|
||||
#include <QKeyEvent>
|
||||
#include <memory>
|
||||
|
||||
#include "Application.h"
|
||||
#include "FlameModel.h"
|
||||
|
@ -88,6 +91,7 @@ FlamePage::FlamePage(NewInstanceDialog* dialog, QWidget* parent)
|
|||
|
||||
ui->packView->setItemDelegate(new ProjectItemDelegate(this));
|
||||
ui->packDescription->setMetaEntry("FlamePacks");
|
||||
createFilterWidget();
|
||||
}
|
||||
|
||||
FlamePage::~FlamePage()
|
||||
|
@ -131,10 +135,35 @@ void FlamePage::openedImpl()
|
|||
|
||||
void FlamePage::triggerSearch()
|
||||
{
|
||||
listModel->searchWithTerm(ui->searchEdit->text(), ui->sortByBox->currentIndex());
|
||||
ui->packView->selectionModel()->setCurrentIndex({}, QItemSelectionModel::SelectionFlag::ClearAndSelect);
|
||||
ui->packView->clearSelection();
|
||||
ui->packDescription->clear();
|
||||
ui->versionSelectionBox->clear();
|
||||
listModel->searchWithTerm(ui->searchEdit->text(), ui->sortByBox->currentIndex(), m_filterWidget->getFilter(),
|
||||
m_filterWidget->changed());
|
||||
m_fetch_progress.watch(listModel->activeSearchJob().get());
|
||||
}
|
||||
|
||||
bool checkMcVersions(std::list<Version> filter, QString value)
|
||||
{
|
||||
for (auto mcVersion : filter) {
|
||||
if (value == mcVersion.toString()) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return filter.empty();
|
||||
}
|
||||
|
||||
bool checkVersionFilters(const Flame::IndexedVersion& v, std::shared_ptr<ModFilterWidget::Filter> filter)
|
||||
{
|
||||
if (!filter)
|
||||
return true;
|
||||
return ((!filter->loaders || !v.loaders || filter->loaders & v.loaders) && // loaders
|
||||
(filter->releases.empty() || // releases
|
||||
std::find(filter->releases.cbegin(), filter->releases.cend(), v.version_type) != filter->releases.cend()) &&
|
||||
checkMcVersions(filter->versions, v.mcVersion)); // mcVersions}
|
||||
}
|
||||
|
||||
void FlamePage::onSelectionChanged(QModelIndex curr, [[maybe_unused]] QModelIndex prev)
|
||||
{
|
||||
ui->versionSelectionBox->clear();
|
||||
|
@ -148,7 +177,7 @@ void FlamePage::onSelectionChanged(QModelIndex curr, [[maybe_unused]] QModelInde
|
|||
|
||||
current = listModel->data(curr, Qt::UserRole).value<Flame::IndexedPack>();
|
||||
|
||||
if (current.versionsLoaded == false) {
|
||||
if (!current.versionsLoaded || m_filterWidget->changed()) {
|
||||
qDebug() << "Loading flame modpack versions";
|
||||
auto netJob = new NetJob(QString("Flame::PackVersions(%1)").arg(current.name), APPLICATION->network());
|
||||
auto response = std::make_shared<QByteArray>();
|
||||
|
@ -176,6 +205,16 @@ void FlamePage::onSelectionChanged(QModelIndex curr, [[maybe_unused]] QModelInde
|
|||
qWarning() << "Error while reading flame modpack version: " << e.cause();
|
||||
}
|
||||
|
||||
auto pred = [this](const Flame::IndexedVersion& v) { return !checkVersionFilters(v, m_filterWidget->getFilter()); };
|
||||
#if QT_VERSION >= QT_VERSION_CHECK(6, 1, 0)
|
||||
current.versions.removeIf(pred);
|
||||
#else
|
||||
for (auto it = current.versions.begin(); it != current.versions.end();)
|
||||
if (pred(*it))
|
||||
it = current.versions.erase(it);
|
||||
else
|
||||
++it;
|
||||
#endif
|
||||
for (auto version : current.versions) {
|
||||
auto release_type = version.version_type.isValid() ? QString(" [%1]").arg(version.version_type.toString()) : "";
|
||||
auto mcVersion = !version.mcVersion.isEmpty() && !version.version.contains(version.mcVersion)
|
||||
|
@ -308,3 +347,25 @@ void FlamePage::setSearchTerm(QString term)
|
|||
{
|
||||
ui->searchEdit->setText(term);
|
||||
}
|
||||
|
||||
void FlamePage::createFilterWidget()
|
||||
{
|
||||
auto widget = ModFilterWidget::create(nullptr, false, this);
|
||||
m_filterWidget.swap(widget);
|
||||
auto old = ui->splitter->replaceWidget(0, m_filterWidget.get());
|
||||
// because we replaced the widget we also need to delete it
|
||||
if (old) {
|
||||
delete old;
|
||||
}
|
||||
|
||||
connect(ui->filterButton, &QPushButton::clicked, this, [this] { m_filterWidget->setHidden(!m_filterWidget->isHidden()); });
|
||||
|
||||
connect(m_filterWidget.get(), &ModFilterWidget::filterChanged, this, &FlamePage::triggerSearch);
|
||||
auto response = std::make_shared<QByteArray>();
|
||||
m_categoriesTask = FlameAPI::getCategories(response, ModPlatform::ResourceType::MODPACK);
|
||||
QObject::connect(m_categoriesTask.get(), &Task::succeeded, [this, response]() {
|
||||
auto categories = FlameAPI::loadModCategories(response);
|
||||
m_filterWidget->setCategories(categories);
|
||||
});
|
||||
m_categoriesTask->start();
|
||||
}
|
||||
|
|
|
@ -41,6 +41,7 @@
|
|||
#include <modplatform/flame/FlamePackIndex.h>
|
||||
#include <QTimer>
|
||||
#include "ui/pages/modplatform/ModpackProviderBasePage.h"
|
||||
#include "ui/widgets/ModFilterWidget.h"
|
||||
#include "ui/widgets/ProgressWidget.h"
|
||||
|
||||
namespace Ui {
|
||||
|
@ -84,6 +85,7 @@ class FlamePage : public QWidget, public ModpackProviderBasePage {
|
|||
void triggerSearch();
|
||||
void onSelectionChanged(QModelIndex first, QModelIndex second);
|
||||
void onVersionSelectionChanged(int index);
|
||||
void createFilterWidget();
|
||||
|
||||
private:
|
||||
Ui::FlamePage* ui = nullptr;
|
||||
|
@ -97,4 +99,7 @@ class FlamePage : public QWidget, public ModpackProviderBasePage {
|
|||
|
||||
// Used to do instant searching with a delay to cache quick changes
|
||||
QTimer m_search_timer;
|
||||
|
||||
unique_qobject_ptr<ModFilterWidget> m_filterWidget;
|
||||
Task::Ptr m_categoriesTask;
|
||||
};
|
||||
|
|
|
@ -30,42 +30,59 @@
|
|||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLineEdit" name="searchEdit">
|
||||
<property name="placeholderText">
|
||||
<string>Search and filter...</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout">
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
<item>
|
||||
<widget class="QListView" name="packView">
|
||||
<property name="horizontalScrollBarPolicy">
|
||||
<enum>Qt::ScrollBarAlwaysOff</enum>
|
||||
</property>
|
||||
<property name="alternatingRowColors">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="iconSize">
|
||||
<size>
|
||||
<width>48</width>
|
||||
<height>48</height>
|
||||
</size>
|
||||
<widget class="QLineEdit" name="searchEdit">
|
||||
<property name="placeholderText">
|
||||
<string>Search and filter...</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="ProjectDescriptionPage" name="packDescription">
|
||||
<property name="openExternalLinks">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="openLinks">
|
||||
<bool>true</bool>
|
||||
<widget class="QPushButton" name="filterButton">
|
||||
<property name="text">
|
||||
<string>Filter</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QSplitter" name="splitter">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<widget class="QWidget" name="widget" native="true"/>
|
||||
<widget class="QListView" name="packView">
|
||||
<property name="horizontalScrollBarPolicy">
|
||||
<enum>Qt::ScrollBarAlwaysOff</enum>
|
||||
</property>
|
||||
<property name="alternatingRowColors">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="iconSize">
|
||||
<size>
|
||||
<width>48</width>
|
||||
<height>48</height>
|
||||
</size>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="ProjectDescriptionPage" name="packDescription">
|
||||
<property name="openExternalLinks">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="openLinks">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout">
|
||||
<item>
|
||||
|
|
|
@ -215,11 +215,11 @@ unique_qobject_ptr<ModFilterWidget> FlameModPage::createFilterWidget()
|
|||
void FlameModPage::prepareProviderCategories()
|
||||
{
|
||||
auto response = std::make_shared<QByteArray>();
|
||||
auto task = FlameAPI::getModCategories(response);
|
||||
QObject::connect(task.get(), &Task::succeeded, [this, response]() {
|
||||
m_categoriesTask = FlameAPI::getModCategories(response);
|
||||
QObject::connect(m_categoriesTask.get(), &Task::succeeded, [this, response]() {
|
||||
auto categories = FlameAPI::loadModCategories(response);
|
||||
m_filter_widget->setCategories(categories);
|
||||
});
|
||||
task->start();
|
||||
m_categoriesTask->start();
|
||||
};
|
||||
} // namespace ResourceDownload
|
||||
|
|
|
@ -100,6 +100,9 @@ class FlameModPage : public ModPage {
|
|||
|
||||
protected:
|
||||
virtual void prepareProviderCategories() override;
|
||||
|
||||
private:
|
||||
Task::Ptr m_categoriesTask;
|
||||
};
|
||||
|
||||
class FlameResourcePackPage : public ResourcePackResourcePage {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue