From e0ab8207ed3614bf078cc2d79f154afeb9d45737 Mon Sep 17 00:00:00 2001 From: flow Date: Sat, 2 Apr 2022 18:29:35 -0300 Subject: [PATCH 1/9] feat: Add dialog to filter mod options in mod download --- launcher/CMakeLists.txt | 3 + launcher/ui/dialogs/FilterModsDialog.cpp | 75 ++++++++++ launcher/ui/dialogs/FilterModsDialog.h | 54 +++++++ launcher/ui/dialogs/FilterModsDialog.ui | 181 +++++++++++++++++++++++ 4 files changed, 313 insertions(+) create mode 100644 launcher/ui/dialogs/FilterModsDialog.cpp create mode 100644 launcher/ui/dialogs/FilterModsDialog.h create mode 100644 launcher/ui/dialogs/FilterModsDialog.ui diff --git a/launcher/CMakeLists.txt b/launcher/CMakeLists.txt index 42348792..8579071a 100644 --- a/launcher/CMakeLists.txt +++ b/launcher/CMakeLists.txt @@ -824,6 +824,8 @@ SET(LAUNCHER_SOURCES ui/dialogs/SkinUploadDialog.h ui/dialogs/ModDownloadDialog.cpp ui/dialogs/ModDownloadDialog.h + ui/dialogs/FilterModsDialog.cpp + ui/dialogs/FilterModsDialog.h # GUI - widgets @@ -923,6 +925,7 @@ qt5_wrap_ui(LAUNCHER_UI ui/dialogs/LoginDialog.ui ui/dialogs/EditAccountDialog.ui ui/dialogs/ReviewMessageBox.ui + ui/dialogs/FilterModsDialog.ui ) qt5_add_resources(LAUNCHER_RESOURCES diff --git a/launcher/ui/dialogs/FilterModsDialog.cpp b/launcher/ui/dialogs/FilterModsDialog.cpp new file mode 100644 index 00000000..a36f4ba4 --- /dev/null +++ b/launcher/ui/dialogs/FilterModsDialog.cpp @@ -0,0 +1,75 @@ +#include "FilterModsDialog.h" +#include "ui_FilterModsDialog.h" + +FilterModsDialog::FilterModsDialog(Version def, QWidget* parent) + : QDialog(parent), m_filter(new Filter()), ui(new Ui::FilterModsDialog) +{ + ui->setupUi(this); + + m_mcVersion_buttons.addButton(ui->strictVersionButton, VersionButtonID::Strict); + m_mcVersion_buttons.addButton(ui->majorVersionButton, VersionButtonID::Major); + m_mcVersion_buttons.addButton(ui->allVersionsButton, VersionButtonID::All); + m_mcVersion_buttons.addButton(ui->betweenVersionsButton, VersionButtonID::Between); + + connect(&m_mcVersion_buttons, SIGNAL(idClicked(int)), this, SLOT(onVersionFilterChanged(int))); + + m_filter->versions.push_front(def); +} + +int FilterModsDialog::execWithInstance(MinecraftInstance* instance) +{ + m_instance = instance; + + // Fix first openening behaviour + onVersionFilterChanged(0); + + auto mcVersionSplit = mcVersionStr().split("."); + + ui->strictVersionButton->setText( + tr("Strict match (= %1)").arg(mcVersionStr())); + ui->majorVersionButton->setText( + tr("Major varsion match (= %1.%2.x)").arg(mcVersionSplit[0], mcVersionSplit[1])); + ui->allVersionsButton->setText( + tr("Any version match")); + ui->betweenVersionsButton->setText( + tr("Between two versions")); + + int ret = QDialog::exec(); + m_instance = nullptr; + return ret; +} + +void FilterModsDialog::onVersionFilterChanged(int id) +{ + ui->lowerVersionComboBox->setEnabled(id == VersionButtonID::Between); + ui->upperVersionComboBox->setEnabled(id == VersionButtonID::Between); + + auto versionSplit = mcVersionStr().split("."); + int index = 0; + + m_filter->versions.clear(); + + switch(id){ + case(VersionButtonID::Strict): + m_filter->versions.push_front(mcVersion()); + break; + case(VersionButtonID::Major): + for(auto i = Version(QString("%1.%2").arg(versionSplit[0], versionSplit[1])); i <= mcVersion(); index++){ + m_filter->versions.push_front(i); + i = Version(QString("%1.%2.%3").arg(versionSplit[0], versionSplit[1], QString("%1").arg(index))); + } + break; + case(VersionButtonID::All): + break; + case(VersionButtonID::Between): + // TODO + break; + default: + break; + } +} + +FilterModsDialog::~FilterModsDialog() +{ + delete ui; +} diff --git a/launcher/ui/dialogs/FilterModsDialog.h b/launcher/ui/dialogs/FilterModsDialog.h new file mode 100644 index 00000000..b119e8e5 --- /dev/null +++ b/launcher/ui/dialogs/FilterModsDialog.h @@ -0,0 +1,54 @@ +#pragma once + +#include +#include + +#include "Version.h" +#include "minecraft/MinecraftInstance.h" +#include "minecraft/PackProfile.h" + +class MinecraftInstance; + +namespace Ui { +class FilterModsDialog; +} + +class FilterModsDialog : public QDialog +{ + Q_OBJECT +public: + struct Filter { + std::list versions; + }; + + std::shared_ptr m_filter; + +public: + explicit FilterModsDialog(Version def, QWidget* parent = nullptr); + ~FilterModsDialog(); + + int execWithInstance(MinecraftInstance* instance); + + auto getFilter() -> std::shared_ptr { return m_filter; } + +private: + enum VersionButtonID { + Strict = 0, + Major = 1, + All = 2, + Between = 3 + }; + + inline auto mcVersionStr() const -> QString { return m_instance ? m_instance->getPackProfile()->getComponentVersion("net.minecraft") : ""; } + inline auto mcVersion() const -> Version { return { mcVersionStr() }; } + +private slots: + void onVersionFilterChanged(int id); + +private: + Ui::FilterModsDialog* ui; + + MinecraftInstance* m_instance = nullptr; + + QButtonGroup m_mcVersion_buttons; +}; diff --git a/launcher/ui/dialogs/FilterModsDialog.ui b/launcher/ui/dialogs/FilterModsDialog.ui new file mode 100644 index 00000000..da368aac --- /dev/null +++ b/launcher/ui/dialogs/FilterModsDialog.ui @@ -0,0 +1,181 @@ + + + FilterModsDialog + + + Qt::ApplicationModal + + + + 0 + 0 + 345 + 323 + + + + Copy Instance + + + + :/icons/toolbar/copy:/icons/toolbar/copy + + + true + + + true + + + + + + + 0 + 0 + + + + Minecraft versions + + + false + + + false + + + + + + QLayout::SetDefaultConstraint + + + + + + + StrictVersion + + + true + + + + + + + MajorVersion + + + + + + + AllVersions + + + + + + + + + + + + + BetweenVersions + + + + + + + From + + + + + + + + + + To + + + + + + + + + + + + + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + Qt::Horizontal + + + QDialogButtonBox::Cancel|QDialogButtonBox::Ok + + + + + + + + + buttonBox + accepted() + FilterModsDialog + accept() + + + 248 + 254 + + + 157 + 274 + + + + + buttonBox + rejected() + FilterModsDialog + reject() + + + 316 + 260 + + + 286 + 274 + + + + + From c2b97c3e3f5ecb5a995b342c4e0afec6a1a3b2f6 Mon Sep 17 00:00:00 2001 From: flow Date: Sat, 2 Apr 2022 18:33:50 -0300 Subject: [PATCH 2/9] feat: Integrate newly created filter dialog in ModPage --- launcher/ui/dialogs/ModDownloadDialog.cpp | 2 +- launcher/ui/pages/modplatform/ModPage.cpp | 28 +++++++++++++++++++---- launcher/ui/pages/modplatform/ModPage.h | 7 ++++++ launcher/ui/pages/modplatform/ModPage.ui | 11 +++++++-- 4 files changed, 41 insertions(+), 7 deletions(-) diff --git a/launcher/ui/dialogs/ModDownloadDialog.cpp b/launcher/ui/dialogs/ModDownloadDialog.cpp index a53f93e8..9aac4145 100644 --- a/launcher/ui/dialogs/ModDownloadDialog.cpp +++ b/launcher/ui/dialogs/ModDownloadDialog.cpp @@ -80,7 +80,7 @@ void ModDownloadDialog::confirm() tr("Confirm mods to download") ); - for(auto task : keys){ + for(auto& task : keys){ confirm_dialog->appendMod(task, modTask.find(task).value()->getFilename()); } diff --git a/launcher/ui/pages/modplatform/ModPage.cpp b/launcher/ui/pages/modplatform/ModPage.cpp index eabd8379..16e44c0d 100644 --- a/launcher/ui/pages/modplatform/ModPage.cpp +++ b/launcher/ui/pages/modplatform/ModPage.cpp @@ -2,21 +2,29 @@ #include "ui_ModPage.h" #include +#include #include "minecraft/MinecraftInstance.h" #include "minecraft/PackProfile.h" #include "ui/dialogs/ModDownloadDialog.h" ModPage::ModPage(ModDownloadDialog* dialog, BaseInstance* instance, ModAPI* api) - : QWidget(dialog), m_instance(instance), ui(new Ui::ModPage), dialog(dialog), api(api) + : QWidget(dialog) + , m_instance(instance) + , ui(new Ui::ModPage) + , dialog(dialog) + , filter_dialog(static_cast(instance)->getPackProfile()->getComponentVersion("net.minecraft"), this) + , api(api) { ui->setupUi(this); connect(ui->searchButton, &QPushButton::clicked, this, &ModPage::triggerSearch); + connect(ui->modFilterButton, &QPushButton::clicked, this, &ModPage::filterMods); ui->searchEdit->installEventFilter(this); ui->versionSelectionBox->view()->setVerticalScrollBarPolicy(Qt::ScrollBarAsNeeded); ui->versionSelectionBox->view()->parentWidget()->setMaximumHeight(300); + m_filter = filter_dialog.getFilter(); } ModPage::~ModPage() @@ -49,6 +57,13 @@ auto ModPage::eventFilter(QObject* watched, QEvent* event) -> bool /******** Callbacks to events in the UI (set up in the derived classes) ********/ +void ModPage::filterMods() +{ + filter_dialog.execWithInstance(static_cast(m_instance)); + + m_filter = filter_dialog.getFilter(); +} + void ModPage::triggerSearch() { listModel->searchWithTerm(ui->searchEdit->text(), ui->sortByBox->currentIndex()); @@ -141,11 +156,16 @@ void ModPage::updateModVersions() for (int i = 0; i < current.versions.size(); i++) { auto version = current.versions[i]; + bool valid = false; //NOTE: Flame doesn't care about loaderString, so passing it changes nothing. - if (!validateVersion(version, mcVersion, loaderString)) { - continue; + for(auto& mcVer : m_filter->versions){ + if (validateVersion(version, mcVer.toString(), loaderString)) { + valid = true; + break; + } } - ui->versionSelectionBox->addItem(version.version, QVariant(i)); + if(valid) + ui->versionSelectionBox->addItem(version.version, QVariant(i)); } if (ui->versionSelectionBox->count() == 0) { ui->versionSelectionBox->addItem(tr("No valid version found!"), QVariant(-1)); } diff --git a/launcher/ui/pages/modplatform/ModPage.h b/launcher/ui/pages/modplatform/ModPage.h index 0cd13f37..3c71e6fe 100644 --- a/launcher/ui/pages/modplatform/ModPage.h +++ b/launcher/ui/pages/modplatform/ModPage.h @@ -5,6 +5,7 @@ #include "Application.h" #include "modplatform/ModAPI.h" #include "modplatform/ModIndex.h" +#include "ui/dialogs/FilterModsDialog.h" #include "ui/pages/BasePage.h" #include "ui/pages/modplatform/ModModel.h" @@ -39,6 +40,7 @@ class ModPage : public QWidget, public BasePage { virtual auto validateVersion(ModPlatform::IndexedVersion& ver, QString mineVer, QString loaderVer = "") const -> bool = 0; auto apiProvider() const -> const ModAPI* { return api.get(); }; + auto getFilter() const -> const std::shared_ptr { return m_filter; } auto getCurrent() -> ModPlatform::IndexedPack& { return current; } void updateModVersions(); @@ -52,6 +54,7 @@ class ModPage : public QWidget, public BasePage { void updateSelectionButton(); protected slots: + void filterMods(); void triggerSearch(); void onSelectionChanged(QModelIndex first, QModelIndex second); void onVersionSelectionChanged(QString data); @@ -60,6 +63,10 @@ class ModPage : public QWidget, public BasePage { protected: Ui::ModPage* ui = nullptr; ModDownloadDialog* dialog = nullptr; + + FilterModsDialog filter_dialog; + std::shared_ptr m_filter; + ModPlatform::ListModel* listModel = nullptr; ModPlatform::IndexedPack current; diff --git a/launcher/ui/pages/modplatform/ModPage.ui b/launcher/ui/pages/modplatform/ModPage.ui index 508f1bac..4444583e 100644 --- a/launcher/ui/pages/modplatform/ModPage.ui +++ b/launcher/ui/pages/modplatform/ModPage.ui @@ -51,12 +51,12 @@ - Search and filter... + Search for mods... - + @@ -80,6 +80,13 @@ + + + + Filter options + + + From c730fd6e5f125cde324d110282ed33ea4b9df136 Mon Sep 17 00:00:00 2001 From: flow Date: Sat, 2 Apr 2022 18:34:26 -0300 Subject: [PATCH 3/9] feat: Use version filter when searching mods --- launcher/modplatform/ModAPI.h | 18 ++++++++++++++++-- launcher/modplatform/flame/FlameAPI.h | 2 +- launcher/modplatform/modrinth/ModrinthAPI.h | 13 +------------ launcher/ui/pages/modplatform/ModModel.cpp | 8 +++----- launcher/ui/pages/modplatform/ModModel.h | 3 ++- 5 files changed, 23 insertions(+), 21 deletions(-) diff --git a/launcher/modplatform/ModAPI.h b/launcher/modplatform/ModAPI.h index 1a562172..6a906aa4 100644 --- a/launcher/modplatform/ModAPI.h +++ b/launcher/modplatform/ModAPI.h @@ -3,6 +3,8 @@ #include #include +#include "Version.h" + namespace ModPlatform { class ListModel; } @@ -22,7 +24,7 @@ class ModAPI { QString search; QString sorting; ModLoaderType mod_loader; - QString version; + std::list versions; }; virtual void searchMods(CallerType* caller, SearchArgs&& args) const = 0; @@ -30,7 +32,7 @@ class ModAPI { struct VersionSearchArgs { QString addonId; - QList mcVersions; + std::list mcVersions; ModLoaderType loader; }; @@ -53,4 +55,16 @@ class ModAPI { } return ""; } + + protected: + inline auto getGameVersionsString(std::list mcVersions) const -> QString + { + QString s; + for(auto& ver : mcVersions){ + s += ver.toString(); + if(ver != mcVersions.back()) + s += ","; + } + return s; + } }; diff --git a/launcher/modplatform/flame/FlameAPI.h b/launcher/modplatform/flame/FlameAPI.h index 8654a693..690ee15c 100644 --- a/launcher/modplatform/flame/FlameAPI.h +++ b/launcher/modplatform/flame/FlameAPI.h @@ -22,7 +22,7 @@ class FlameAPI : public NetworkModAPI { .arg(args.search) .arg(args.sorting) .arg(args.mod_loader) - .arg(args.version); + .arg(getGameVersionsString(args.versions)); }; inline auto getVersionsURL(VersionSearchArgs& args) const -> QString override diff --git a/launcher/modplatform/modrinth/ModrinthAPI.h b/launcher/modplatform/modrinth/ModrinthAPI.h index eefa4a85..0d652568 100644 --- a/launcher/modplatform/modrinth/ModrinthAPI.h +++ b/launcher/modplatform/modrinth/ModrinthAPI.h @@ -27,7 +27,7 @@ class ModrinthAPI : public NetworkModAPI { .arg(args.search) .arg(args.sorting) .arg(getModLoaderString(args.mod_loader)) - .arg(args.version); + .arg(getGameVersionsString(args.versions)); }; inline auto getVersionsURL(VersionSearchArgs& args) const -> QString override @@ -40,17 +40,6 @@ class ModrinthAPI : public NetworkModAPI { .arg(getModLoaderString(args.loader)); }; - inline auto getGameVersionsString(QList mcVersions) const -> QString - { - QString s; - for(int i = 0; i < mcVersions.count(); i++){ - s += mcVersions.at(i); - if(i < mcVersions.count() - 1) - s += ","; - } - return s; - } - static auto getModLoaderString(ModLoaderType type) -> const QString { if (type == Unspecified) diff --git a/launcher/ui/pages/modplatform/ModModel.cpp b/launcher/ui/pages/modplatform/ModModel.cpp index f75d2847..1998fe99 100644 --- a/launcher/ui/pages/modplatform/ModModel.cpp +++ b/launcher/ui/pages/modplatform/ModModel.cpp @@ -72,7 +72,7 @@ void ListModel::performPaginatedSearch() auto profile = (dynamic_cast((dynamic_cast(parent()))->m_instance))->getPackProfile(); m_parent->apiProvider()->searchMods(this, - { nextSearchOffset, currentSearchTerm, getSorts()[currentSort], profile->getModLoader(), getMineVersions().at(0) }); + { nextSearchOffset, currentSearchTerm, getSorts()[currentSort], profile->getModLoader(), getMineVersions() }); } void ListModel::searchWithTerm(const QString& term, const int sort) @@ -223,9 +223,7 @@ void ListModel::versionRequestSucceeded(QJsonDocument doc, QString addonId) /******** Helpers ********/ -auto ModPlatform::ListModel::getMineVersions() const -> QList +auto ModPlatform::ListModel::getMineVersions() const -> std::list { - return { (dynamic_cast((dynamic_cast(parent()))->m_instance)) - ->getPackProfile() - ->getComponentVersion("net.minecraft") }; + return m_parent->getFilter()->versions; } diff --git a/launcher/ui/pages/modplatform/ModModel.h b/launcher/ui/pages/modplatform/ModModel.h index dbadbeee..1b7601c2 100644 --- a/launcher/ui/pages/modplatform/ModModel.h +++ b/launcher/ui/pages/modplatform/ModModel.h @@ -7,6 +7,7 @@ #include "net/NetJob.h" class ModPage; +class Version; namespace ModPlatform { @@ -62,7 +63,7 @@ class ListModel : public QAbstractListModel { void requestLogo(QString file, QString url); - inline auto getMineVersions() const -> QList; + inline auto getMineVersions() const -> std::list; protected: ModPage* m_parent; From 5cb0e750936f09513b98a8b0fd57746ca18dc8bc Mon Sep 17 00:00:00 2001 From: flow Date: Sat, 2 Apr 2022 19:21:02 -0300 Subject: [PATCH 4/9] fix(ui): Refresh mod list when changing filtering options --- launcher/modplatform/ModAPI.h | 5 ++--- launcher/modplatform/modrinth/ModrinthAPI.h | 14 ++++++++++++-- launcher/ui/pages/modplatform/ModModel.cpp | 14 ++++++++++---- launcher/ui/pages/modplatform/ModModel.h | 1 + launcher/ui/pages/modplatform/ModPage.cpp | 7 +++++++ 5 files changed, 32 insertions(+), 9 deletions(-) diff --git a/launcher/modplatform/ModAPI.h b/launcher/modplatform/ModAPI.h index 6a906aa4..8e6cd45c 100644 --- a/launcher/modplatform/ModAPI.h +++ b/launcher/modplatform/ModAPI.h @@ -61,10 +61,9 @@ class ModAPI { { QString s; for(auto& ver : mcVersions){ - s += ver.toString(); - if(ver != mcVersions.back()) - s += ","; + s += QString("%1,").arg(ver.toString()); } + s.remove(s.length() - 1, 1); //remove last comma return s; } }; diff --git a/launcher/modplatform/modrinth/ModrinthAPI.h b/launcher/modplatform/modrinth/ModrinthAPI.h index 0d652568..87534ee9 100644 --- a/launcher/modplatform/modrinth/ModrinthAPI.h +++ b/launcher/modplatform/modrinth/ModrinthAPI.h @@ -22,12 +22,12 @@ class ModrinthAPI : public NetworkModAPI { "limit=25&" "query=%2&" "index=%3&" - "facets=[[\"categories:%4\"],[\"versions:%5\"],[\"project_type:mod\"]]") + "facets=[[\"categories:%4\"],[%5],[\"project_type:mod\"]]") .arg(args.offset) .arg(args.search) .arg(args.sorting) .arg(getModLoaderString(args.mod_loader)) - .arg(getGameVersionsString(args.versions)); + .arg(getGameVersionsArray(args.versions)); }; inline auto getVersionsURL(VersionSearchArgs& args) const -> QString override @@ -40,6 +40,16 @@ class ModrinthAPI : public NetworkModAPI { .arg(getModLoaderString(args.loader)); }; + auto getGameVersionsArray(std::list mcVersions) const -> QString + { + QString s; + for(auto& ver : mcVersions){ + s += QString("\"versions:%1\",").arg(ver.toString()); + } + s.remove(s.length() - 1, 1); //remove last comma + return s; + } + static auto getModLoaderString(ModLoaderType type) -> const QString { if (type == Unspecified) diff --git a/launcher/ui/pages/modplatform/ModModel.cpp b/launcher/ui/pages/modplatform/ModModel.cpp index 1998fe99..0ff784db 100644 --- a/launcher/ui/pages/modplatform/ModModel.cpp +++ b/launcher/ui/pages/modplatform/ModModel.cpp @@ -75,11 +75,8 @@ void ListModel::performPaginatedSearch() { nextSearchOffset, currentSearchTerm, getSorts()[currentSort], profile->getModLoader(), getMineVersions() }); } -void ListModel::searchWithTerm(const QString& term, const int sort) +void ListModel::refresh() { - if (currentSearchTerm == term && currentSearchTerm.isNull() == term.isNull() && currentSort == sort) { return; } - currentSearchTerm = term; - currentSort = sort; if (jobPtr) { jobPtr->abort(); searchState = ResetRequested; @@ -94,6 +91,15 @@ void ListModel::searchWithTerm(const QString& term, const int sort) performPaginatedSearch(); } +void ListModel::searchWithTerm(const QString& term, const int sort) +{ + if (currentSearchTerm == term && currentSearchTerm.isNull() == term.isNull() && currentSort == sort) { return; } + currentSearchTerm = term; + currentSort = sort; + + refresh(); +} + void ListModel::getLogo(const QString& logo, const QString& logoUrl, LogoCallback callback) { if (m_logoMap.contains(logo)) { diff --git a/launcher/ui/pages/modplatform/ModModel.h b/launcher/ui/pages/modplatform/ModModel.h index 1b7601c2..d4dc872d 100644 --- a/launcher/ui/pages/modplatform/ModModel.h +++ b/launcher/ui/pages/modplatform/ModModel.h @@ -34,6 +34,7 @@ class ListModel : public QAbstractListModel { /* Ask the API for more information */ void fetchMore(const QModelIndex& parent) override; + void refresh(); void searchWithTerm(const QString& term, const int sort); void requestModVersions(const ModPlatform::IndexedPack& current); diff --git a/launcher/ui/pages/modplatform/ModPage.cpp b/launcher/ui/pages/modplatform/ModPage.cpp index 16e44c0d..ece97ef2 100644 --- a/launcher/ui/pages/modplatform/ModPage.cpp +++ b/launcher/ui/pages/modplatform/ModPage.cpp @@ -62,6 +62,13 @@ void ModPage::filterMods() filter_dialog.execWithInstance(static_cast(m_instance)); m_filter = filter_dialog.getFilter(); + + listModel->refresh(); + + if(ui->versionSelectionBox->count() > 0){ + ui->versionSelectionBox->clear(); + updateModVersions(); + } } void ModPage::triggerSearch() From 76dfb7825ade6554095ac3a09b3accdbd4db5138 Mon Sep 17 00:00:00 2001 From: flow Date: Sat, 2 Apr 2022 20:08:37 -0300 Subject: [PATCH 5/9] fix: 'All' filter working and get around CF API capabilities --- launcher/modplatform/flame/FlameAPI.h | 6 +- launcher/modplatform/modrinth/ModrinthAPI.h | 4 +- launcher/ui/dialogs/FilterModsDialog.cpp | 31 ++++++++-- launcher/ui/dialogs/FilterModsDialog.h | 17 ++--- launcher/ui/dialogs/FilterModsDialog.ui | 62 +++---------------- launcher/ui/pages/modplatform/ModPage.cpp | 5 +- launcher/ui/pages/modplatform/ModPage.h | 2 +- .../pages/modplatform/flame/FlameModPage.cpp | 19 ++++++ .../ui/pages/modplatform/flame/FlameModPage.h | 2 + 9 files changed, 74 insertions(+), 74 deletions(-) diff --git a/launcher/modplatform/flame/FlameAPI.h b/launcher/modplatform/flame/FlameAPI.h index 690ee15c..9bcc357e 100644 --- a/launcher/modplatform/flame/FlameAPI.h +++ b/launcher/modplatform/flame/FlameAPI.h @@ -6,6 +6,8 @@ class FlameAPI : public NetworkModAPI { private: inline auto getModSearchURL(SearchArgs& args) const -> QString override { + auto gameVersionStr = args.versions.size() != 0 ? QString("gameVersion=%1").arg(args.versions.front().toString()) : QString(); + return QString( "https://addons-ecs.forgesvc.net/api/v2/addon/search?" "gameId=432&" @@ -17,12 +19,12 @@ class FlameAPI : public NetworkModAPI { "searchFilter=%2&" "sort=%3&" "modLoaderType=%4&" - "gameVersion=%5") + "%5") .arg(args.offset) .arg(args.search) .arg(args.sorting) .arg(args.mod_loader) - .arg(getGameVersionsString(args.versions)); + .arg(gameVersionStr); }; inline auto getVersionsURL(VersionSearchArgs& args) const -> QString override diff --git a/launcher/modplatform/modrinth/ModrinthAPI.h b/launcher/modplatform/modrinth/ModrinthAPI.h index 87534ee9..6604d772 100644 --- a/launcher/modplatform/modrinth/ModrinthAPI.h +++ b/launcher/modplatform/modrinth/ModrinthAPI.h @@ -22,7 +22,7 @@ class ModrinthAPI : public NetworkModAPI { "limit=25&" "query=%2&" "index=%3&" - "facets=[[\"categories:%4\"],[%5],[\"project_type:mod\"]]") + "facets=[[\"categories:%4\"],%5[\"project_type:mod\"]]") .arg(args.offset) .arg(args.search) .arg(args.sorting) @@ -47,7 +47,7 @@ class ModrinthAPI : public NetworkModAPI { s += QString("\"versions:%1\",").arg(ver.toString()); } s.remove(s.length() - 1, 1); //remove last comma - return s; + return s.isEmpty() ? QString() : QString("[%1],").arg(s); } static auto getModLoaderString(ModLoaderType type) -> const QString diff --git a/launcher/ui/dialogs/FilterModsDialog.cpp b/launcher/ui/dialogs/FilterModsDialog.cpp index a36f4ba4..bf4999e0 100644 --- a/launcher/ui/dialogs/FilterModsDialog.cpp +++ b/launcher/ui/dialogs/FilterModsDialog.cpp @@ -9,7 +9,7 @@ FilterModsDialog::FilterModsDialog(Version def, QWidget* parent) m_mcVersion_buttons.addButton(ui->strictVersionButton, VersionButtonID::Strict); m_mcVersion_buttons.addButton(ui->majorVersionButton, VersionButtonID::Major); m_mcVersion_buttons.addButton(ui->allVersionsButton, VersionButtonID::All); - m_mcVersion_buttons.addButton(ui->betweenVersionsButton, VersionButtonID::Between); + //m_mcVersion_buttons.addButton(ui->betweenVersionsButton, VersionButtonID::Between); connect(&m_mcVersion_buttons, SIGNAL(idClicked(int)), this, SLOT(onVersionFilterChanged(int))); @@ -31,18 +31,38 @@ int FilterModsDialog::execWithInstance(MinecraftInstance* instance) tr("Major varsion match (= %1.%2.x)").arg(mcVersionSplit[0], mcVersionSplit[1])); ui->allVersionsButton->setText( tr("Any version match")); - ui->betweenVersionsButton->setText( - tr("Between two versions")); + //ui->betweenVersionsButton->setText( + // tr("Between two versions")); int ret = QDialog::exec(); m_instance = nullptr; return ret; } +void FilterModsDialog::disableVersionButton(VersionButtonID id) +{ + switch(id){ + case(VersionButtonID::Strict): + ui->strictVersionButton->setEnabled(false); + break; + case(VersionButtonID::Major): + ui->majorVersionButton->setEnabled(false); + break; + case(VersionButtonID::All): + ui->allVersionsButton->setEnabled(false); + break; + case(VersionButtonID::Between): + // ui->betweenVersionsButton->setEnabled(false); + break; + default: + break; + } +} + void FilterModsDialog::onVersionFilterChanged(int id) { - ui->lowerVersionComboBox->setEnabled(id == VersionButtonID::Between); - ui->upperVersionComboBox->setEnabled(id == VersionButtonID::Between); + //ui->lowerVersionComboBox->setEnabled(id == VersionButtonID::Between); + //ui->upperVersionComboBox->setEnabled(id == VersionButtonID::Between); auto versionSplit = mcVersionStr().split("."); int index = 0; @@ -60,6 +80,7 @@ void FilterModsDialog::onVersionFilterChanged(int id) } break; case(VersionButtonID::All): + // Empty list to avoid enumerating all versions :P break; case(VersionButtonID::Between): // TODO diff --git a/launcher/ui/dialogs/FilterModsDialog.h b/launcher/ui/dialogs/FilterModsDialog.h index b119e8e5..3684b03c 100644 --- a/launcher/ui/dialogs/FilterModsDialog.h +++ b/launcher/ui/dialogs/FilterModsDialog.h @@ -17,6 +17,13 @@ class FilterModsDialog : public QDialog { Q_OBJECT public: + enum VersionButtonID { + Strict = 0, + Major = 1, + All = 2, + Between = 3 + }; + struct Filter { std::list versions; }; @@ -29,16 +36,12 @@ public: int execWithInstance(MinecraftInstance* instance); + /// By default all buttons are enabled + void disableVersionButton(VersionButtonID); + auto getFilter() -> std::shared_ptr { return m_filter; } private: - enum VersionButtonID { - Strict = 0, - Major = 1, - All = 2, - Between = 3 - }; - inline auto mcVersionStr() const -> QString { return m_instance ? m_instance->getPackProfile()->getComponentVersion("net.minecraft") : ""; } inline auto mcVersion() const -> Version { return { mcVersionStr() }; } diff --git a/launcher/ui/dialogs/FilterModsDialog.ui b/launcher/ui/dialogs/FilterModsDialog.ui index da368aac..67a63bfd 100644 --- a/launcher/ui/dialogs/FilterModsDialog.ui +++ b/launcher/ui/dialogs/FilterModsDialog.ui @@ -10,15 +10,17 @@ 0 0 345 - 323 + 169 - - Copy Instance + + + 0 + 0 + - - - :/icons/toolbar/copy:/icons/toolbar/copy + + Filter options true @@ -78,59 +80,11 @@ - - - - - - - - BetweenVersions - - - - - - - From - - - - - - - - - - To - - - - - - - - - - - - - - Qt::Vertical - - - - 20 - 40 - - - - diff --git a/launcher/ui/pages/modplatform/ModPage.cpp b/launcher/ui/pages/modplatform/ModPage.cpp index ece97ef2..ba56c3b8 100644 --- a/launcher/ui/pages/modplatform/ModPage.cpp +++ b/launcher/ui/pages/modplatform/ModPage.cpp @@ -64,7 +64,6 @@ void ModPage::filterMods() m_filter = filter_dialog.getFilter(); listModel->refresh(); - if(ui->versionSelectionBox->count() > 0){ ui->versionSelectionBox->clear(); updateModVersions(); @@ -164,14 +163,14 @@ void ModPage::updateModVersions() for (int i = 0; i < current.versions.size(); i++) { auto version = current.versions[i]; bool valid = false; - //NOTE: Flame doesn't care about loaderString, so passing it changes nothing. for(auto& mcVer : m_filter->versions){ + //NOTE: Flame doesn't care about loaderString, so passing it changes nothing. if (validateVersion(version, mcVer.toString(), loaderString)) { valid = true; break; } } - if(valid) + if(valid || m_filter->versions.size() == 0) ui->versionSelectionBox->addItem(version.version, QVariant(i)); } if (ui->versionSelectionBox->count() == 0) { ui->versionSelectionBox->addItem(tr("No valid version found!"), QVariant(-1)); } diff --git a/launcher/ui/pages/modplatform/ModPage.h b/launcher/ui/pages/modplatform/ModPage.h index 3c71e6fe..0befc7c3 100644 --- a/launcher/ui/pages/modplatform/ModPage.h +++ b/launcher/ui/pages/modplatform/ModPage.h @@ -54,7 +54,7 @@ class ModPage : public QWidget, public BasePage { void updateSelectionButton(); protected slots: - void filterMods(); + virtual void filterMods(); void triggerSearch(); void onSelectionChanged(QModelIndex first, QModelIndex second); void onVersionSelectionChanged(QString data); diff --git a/launcher/ui/pages/modplatform/flame/FlameModPage.cpp b/launcher/ui/pages/modplatform/flame/FlameModPage.cpp index 864ae8e6..5398bda3 100644 --- a/launcher/ui/pages/modplatform/flame/FlameModPage.cpp +++ b/launcher/ui/pages/modplatform/flame/FlameModPage.cpp @@ -67,6 +67,25 @@ auto FlameModPage::validateVersion(ModPlatform::IndexedVersion& ver, QString min return ver.mcVersion.contains(mineVer); } +// We override this so that it refreshes correctly, otherwise it wouldn't show +// any mod on the mod list, because the CF API does not support it :( +void FlameModPage::filterMods() +{ + filter_dialog.execWithInstance(static_cast(m_instance)); + + int prev_size = m_filter->versions.size(); + m_filter = filter_dialog.getFilter(); + int new_size = m_filter->versions.size(); + + if(new_size <= 1 && new_size != prev_size) + listModel->refresh(); + + if(ui->versionSelectionBox->count() > 0){ + ui->versionSelectionBox->clear(); + updateModVersions(); + } +} + // I don't know why, but doing this on the parent class makes it so that // other mod providers start loading before being selected, at least with // my Qt, so we need to implement this in every derived class... diff --git a/launcher/ui/pages/modplatform/flame/FlameModPage.h b/launcher/ui/pages/modplatform/flame/FlameModPage.h index dc58fd7f..7078e889 100644 --- a/launcher/ui/pages/modplatform/flame/FlameModPage.h +++ b/launcher/ui/pages/modplatform/flame/FlameModPage.h @@ -56,5 +56,7 @@ class FlameModPage : public ModPage { auto validateVersion(ModPlatform::IndexedVersion& ver, QString mineVer, QString loaderVer = "") const -> bool override; + void filterMods() override; + auto shouldDisplay() const -> bool override; }; From 63bce0464895236a043aa8a98e2905ab1bf34cc1 Mon Sep 17 00:00:00 2001 From: flow Date: Sun, 3 Apr 2022 10:21:48 -0300 Subject: [PATCH 6/9] fix: Polish usage in some cases Also fiz some typos --- launcher/ui/dialogs/FilterModsDialog.cpp | 42 +++++++++++++++---- launcher/ui/dialogs/FilterModsDialog.h | 8 ++++ launcher/ui/pages/modplatform/ModPage.cpp | 19 +++++---- launcher/ui/pages/modplatform/ModPage.h | 2 +- .../pages/modplatform/flame/FlameModPage.cpp | 20 ++++----- 5 files changed, 64 insertions(+), 27 deletions(-) diff --git a/launcher/ui/dialogs/FilterModsDialog.cpp b/launcher/ui/dialogs/FilterModsDialog.cpp index bf4999e0..9440d897 100644 --- a/launcher/ui/dialogs/FilterModsDialog.cpp +++ b/launcher/ui/dialogs/FilterModsDialog.cpp @@ -2,7 +2,7 @@ #include "ui_FilterModsDialog.h" FilterModsDialog::FilterModsDialog(Version def, QWidget* parent) - : QDialog(parent), m_filter(new Filter()), ui(new Ui::FilterModsDialog) + : QDialog(parent), m_filter(new Filter()), m_internal_filter(new Filter()), ui(new Ui::FilterModsDialog) { ui->setupUi(this); @@ -13,28 +13,44 @@ FilterModsDialog::FilterModsDialog(Version def, QWidget* parent) connect(&m_mcVersion_buttons, SIGNAL(idClicked(int)), this, SLOT(onVersionFilterChanged(int))); - m_filter->versions.push_front(def); + m_internal_filter->versions.push_front(def); + commitChanges(); } int FilterModsDialog::execWithInstance(MinecraftInstance* instance) { m_instance = instance; + auto* pressed_button = m_mcVersion_buttons.checkedButton(); + // Fix first openening behaviour - onVersionFilterChanged(0); + onVersionFilterChanged(m_previous_mcVersion_id); auto mcVersionSplit = mcVersionStr().split("."); ui->strictVersionButton->setText( tr("Strict match (= %1)").arg(mcVersionStr())); ui->majorVersionButton->setText( - tr("Major varsion match (= %1.%2.x)").arg(mcVersionSplit[0], mcVersionSplit[1])); + tr("Major version match (= %1.%2.x)").arg(mcVersionSplit[0], mcVersionSplit[1])); ui->allVersionsButton->setText( - tr("Any version match")); + tr("Any version")); //ui->betweenVersionsButton->setText( // tr("Between two versions")); int ret = QDialog::exec(); + + if(ret == QDialog::DialogCode::Accepted){ + // If there's no change, let's sey it's a cancel to the caller + if(*m_internal_filter.get() == *m_filter.get()) + return QDialog::DialogCode::Rejected; + + m_previous_mcVersion_id = (VersionButtonID) m_mcVersion_buttons.checkedId(); + commitChanges(); + } else { + pressed_button->click(); + revertChanges(); + } + m_instance = nullptr; return ret; } @@ -59,6 +75,16 @@ void FilterModsDialog::disableVersionButton(VersionButtonID id) } } +// Do deep copy +void FilterModsDialog::commitChanges() +{ + m_filter->versions = m_internal_filter->versions; +} +void FilterModsDialog::revertChanges() +{ + m_internal_filter->versions = m_filter->versions; +} + void FilterModsDialog::onVersionFilterChanged(int id) { //ui->lowerVersionComboBox->setEnabled(id == VersionButtonID::Between); @@ -67,15 +93,15 @@ void FilterModsDialog::onVersionFilterChanged(int id) auto versionSplit = mcVersionStr().split("."); int index = 0; - m_filter->versions.clear(); + m_internal_filter->versions.clear(); switch(id){ case(VersionButtonID::Strict): - m_filter->versions.push_front(mcVersion()); + m_internal_filter->versions.push_front(mcVersion()); break; case(VersionButtonID::Major): for(auto i = Version(QString("%1.%2").arg(versionSplit[0], versionSplit[1])); i <= mcVersion(); index++){ - m_filter->versions.push_front(i); + m_internal_filter->versions.push_front(i); i = Version(QString("%1.%2.%3").arg(versionSplit[0], versionSplit[1], QString("%1").arg(index))); } break; diff --git a/launcher/ui/dialogs/FilterModsDialog.h b/launcher/ui/dialogs/FilterModsDialog.h index 3684b03c..fac28ca4 100644 --- a/launcher/ui/dialogs/FilterModsDialog.h +++ b/launcher/ui/dialogs/FilterModsDialog.h @@ -26,9 +26,13 @@ public: struct Filter { std::list versions; + + bool operator==(const Filter& other) const { return versions == other.versions; } + bool operator!=(const Filter& other) const { return !(*this == other); } }; std::shared_ptr m_filter; + std::shared_ptr m_internal_filter; public: explicit FilterModsDialog(Version def, QWidget* parent = nullptr); @@ -45,6 +49,9 @@ private: inline auto mcVersionStr() const -> QString { return m_instance ? m_instance->getPackProfile()->getComponentVersion("net.minecraft") : ""; } inline auto mcVersion() const -> Version { return { mcVersionStr() }; } + void commitChanges(); + void revertChanges(); + private slots: void onVersionFilterChanged(int id); @@ -54,4 +61,5 @@ private: MinecraftInstance* m_instance = nullptr; QButtonGroup m_mcVersion_buttons; + VersionButtonID m_previous_mcVersion_id = VersionButtonID::Strict; }; diff --git a/launcher/ui/pages/modplatform/ModPage.cpp b/launcher/ui/pages/modplatform/ModPage.cpp index ba56c3b8..37f68291 100644 --- a/launcher/ui/pages/modplatform/ModPage.cpp +++ b/launcher/ui/pages/modplatform/ModPage.cpp @@ -59,14 +59,15 @@ auto ModPage::eventFilter(QObject* watched, QEvent* event) -> bool void ModPage::filterMods() { - filter_dialog.execWithInstance(static_cast(m_instance)); - + auto ret = filter_dialog.execWithInstance(static_cast(m_instance)); m_filter = filter_dialog.getFilter(); - listModel->refresh(); - if(ui->versionSelectionBox->count() > 0){ + if(ret == QDialog::DialogCode::Accepted){ + listModel->refresh(); + + int prev_count = ui->versionSelectionBox->count(); ui->versionSelectionBox->clear(); - updateModVersions(); + updateModVersions(prev_count); } } @@ -152,7 +153,7 @@ void ModPage::retranslate() ui->retranslateUi(this); } -void ModPage::updateModVersions() +void ModPage::updateModVersions(int prev_count) { auto packProfile = (dynamic_cast(m_instance))->getPackProfile(); @@ -173,9 +174,11 @@ void ModPage::updateModVersions() if(valid || m_filter->versions.size() == 0) ui->versionSelectionBox->addItem(version.version, QVariant(i)); } - if (ui->versionSelectionBox->count() == 0) { ui->versionSelectionBox->addItem(tr("No valid version found!"), QVariant(-1)); } + if (ui->versionSelectionBox->count() == 0 && prev_count != 0) { + ui->versionSelectionBox->addItem(tr("No valid version found!"), QVariant(-1)); + ui->modSelectionButton->setText(tr("Cannot select invalid version :(")); + } - ui->modSelectionButton->setText(tr("Cannot select invalid version :(")); updateSelectionButton(); } diff --git a/launcher/ui/pages/modplatform/ModPage.h b/launcher/ui/pages/modplatform/ModPage.h index 0befc7c3..06581ab2 100644 --- a/launcher/ui/pages/modplatform/ModPage.h +++ b/launcher/ui/pages/modplatform/ModPage.h @@ -43,7 +43,7 @@ class ModPage : public QWidget, public BasePage { auto getFilter() const -> const std::shared_ptr { return m_filter; } auto getCurrent() -> ModPlatform::IndexedPack& { return current; } - void updateModVersions(); + void updateModVersions(int prev_count = -1); void openedImpl() override; auto eventFilter(QObject* watched, QEvent* event) -> bool override; diff --git a/launcher/ui/pages/modplatform/flame/FlameModPage.cpp b/launcher/ui/pages/modplatform/flame/FlameModPage.cpp index 5398bda3..6e666c4c 100644 --- a/launcher/ui/pages/modplatform/flame/FlameModPage.cpp +++ b/launcher/ui/pages/modplatform/flame/FlameModPage.cpp @@ -67,22 +67,22 @@ auto FlameModPage::validateVersion(ModPlatform::IndexedVersion& ver, QString min return ver.mcVersion.contains(mineVer); } -// We override this so that it refreshes correctly, otherwise it wouldn't show -// any mod on the mod list, because the CF API does not support it :( +// We override this so that it refreshes correctly, otherwise it would show +// invalid mods on the mod list, because the API would return mods for the +// wrong mod loader :( void FlameModPage::filterMods() { - filter_dialog.execWithInstance(static_cast(m_instance)); - - int prev_size = m_filter->versions.size(); + auto ret = filter_dialog.execWithInstance(static_cast(m_instance)); m_filter = filter_dialog.getFilter(); - int new_size = m_filter->versions.size(); - if(new_size <= 1 && new_size != prev_size) - listModel->refresh(); + if(ret == QDialog::DialogCode::Accepted){ + // CF API can't handle well this + if(!m_filter->versions.empty()) + listModel->refresh(); - if(ui->versionSelectionBox->count() > 0){ + int prev_count = ui->versionSelectionBox->count(); ui->versionSelectionBox->clear(); - updateModVersions(); + updateModVersions(prev_count); } } From 277de4120052b2630850a18969a56ee92e8c2c63 Mon Sep 17 00:00:00 2001 From: flow Date: Thu, 14 Apr 2022 10:27:03 -0300 Subject: [PATCH 7/9] rework: make the filter as a tabbed widget in the dialog itself Still needs a clear indication that the filter only applies after you click the search button... --- launcher/ui/dialogs/FilterModsDialog.ui | 135 ------------------ launcher/ui/pages/modplatform/ModModel.cpp | 9 +- launcher/ui/pages/modplatform/ModModel.h | 2 +- launcher/ui/pages/modplatform/ModPage.cpp | 30 ++-- launcher/ui/pages/modplatform/ModPage.h | 8 +- launcher/ui/pages/modplatform/ModPage.ui | 27 ++-- .../pages/modplatform/flame/FlameModPage.cpp | 19 --- .../ui/pages/modplatform/flame/FlameModPage.h | 2 - .../ModFilterWidget.cpp} | 73 ++++------ .../ModFilterWidget.h} | 26 ++-- launcher/ui/widgets/ModFilterWidget.ui | 54 +++++++ 11 files changed, 138 insertions(+), 247 deletions(-) delete mode 100644 launcher/ui/dialogs/FilterModsDialog.ui rename launcher/ui/{dialogs/FilterModsDialog.cpp => widgets/ModFilterWidget.cpp} (57%) rename launcher/ui/{dialogs/FilterModsDialog.h => widgets/ModFilterWidget.h} (64%) create mode 100644 launcher/ui/widgets/ModFilterWidget.ui diff --git a/launcher/ui/dialogs/FilterModsDialog.ui b/launcher/ui/dialogs/FilterModsDialog.ui deleted file mode 100644 index 67a63bfd..00000000 --- a/launcher/ui/dialogs/FilterModsDialog.ui +++ /dev/null @@ -1,135 +0,0 @@ - - - FilterModsDialog - - - Qt::ApplicationModal - - - - 0 - 0 - 345 - 169 - - - - - 0 - 0 - - - - Filter options - - - true - - - true - - - - - - - 0 - 0 - - - - Minecraft versions - - - false - - - false - - - - - - QLayout::SetDefaultConstraint - - - - - - - StrictVersion - - - true - - - - - - - MajorVersion - - - - - - - AllVersions - - - - - - - - - - - - - - Qt::Horizontal - - - QDialogButtonBox::Cancel|QDialogButtonBox::Ok - - - - - - - - - buttonBox - accepted() - FilterModsDialog - accept() - - - 248 - 254 - - - 157 - 274 - - - - - buttonBox - rejected() - FilterModsDialog - reject() - - - 316 - 260 - - - 286 - 274 - - - - - diff --git a/launcher/ui/pages/modplatform/ModModel.cpp b/launcher/ui/pages/modplatform/ModModel.cpp index 0ff784db..da0331b5 100644 --- a/launcher/ui/pages/modplatform/ModModel.cpp +++ b/launcher/ui/pages/modplatform/ModModel.cpp @@ -91,9 +91,14 @@ void ListModel::refresh() performPaginatedSearch(); } -void ListModel::searchWithTerm(const QString& term, const int sort) +void ListModel::searchWithTerm(const QString& term, const int sort, const bool filter_changed) { - if (currentSearchTerm == term && currentSearchTerm.isNull() == term.isNull() && currentSort == sort) { return; } + if (currentSearchTerm == term + && currentSearchTerm.isNull() == term.isNull() + && currentSort == sort + && !filter_changed) + { return; } + currentSearchTerm = term; currentSort = sort; diff --git a/launcher/ui/pages/modplatform/ModModel.h b/launcher/ui/pages/modplatform/ModModel.h index d4dc872d..d460cff2 100644 --- a/launcher/ui/pages/modplatform/ModModel.h +++ b/launcher/ui/pages/modplatform/ModModel.h @@ -35,7 +35,7 @@ class ListModel : public QAbstractListModel { /* Ask the API for more information */ void fetchMore(const QModelIndex& parent) override; void refresh(); - void searchWithTerm(const QString& term, const int sort); + void searchWithTerm(const QString& term, const int sort, const bool filter_changed); void requestModVersions(const ModPlatform::IndexedPack& current); virtual void loadIndexedPack(ModPlatform::IndexedPack& m, QJsonObject& obj) = 0; diff --git a/launcher/ui/pages/modplatform/ModPage.cpp b/launcher/ui/pages/modplatform/ModPage.cpp index 37f68291..57c2e45d 100644 --- a/launcher/ui/pages/modplatform/ModPage.cpp +++ b/launcher/ui/pages/modplatform/ModPage.cpp @@ -13,7 +13,7 @@ ModPage::ModPage(ModDownloadDialog* dialog, BaseInstance* instance, ModAPI* api) , m_instance(instance) , ui(new Ui::ModPage) , dialog(dialog) - , filter_dialog(static_cast(instance)->getPackProfile()->getComponentVersion("net.minecraft"), this) + , filter_widget(static_cast(instance)->getPackProfile()->getComponentVersion("net.minecraft"), this) , api(api) { ui->setupUi(this); @@ -24,7 +24,10 @@ ModPage::ModPage(ModDownloadDialog* dialog, BaseInstance* instance, ModAPI* api) ui->versionSelectionBox->view()->setVerticalScrollBarPolicy(Qt::ScrollBarAsNeeded); ui->versionSelectionBox->view()->parentWidget()->setMaximumHeight(300); - m_filter = filter_dialog.getFilter(); + ui->gridLayout_3->addWidget(&filter_widget, 0, 0, 1, ui->gridLayout_3->columnCount()); + + filter_widget.setInstance(static_cast(m_instance)); + m_filter = filter_widget.getFilter(); } ModPage::~ModPage() @@ -59,21 +62,22 @@ auto ModPage::eventFilter(QObject* watched, QEvent* event) -> bool void ModPage::filterMods() { - auto ret = filter_dialog.execWithInstance(static_cast(m_instance)); - m_filter = filter_dialog.getFilter(); - - if(ret == QDialog::DialogCode::Accepted){ - listModel->refresh(); - - int prev_count = ui->versionSelectionBox->count(); - ui->versionSelectionBox->clear(); - updateModVersions(prev_count); - } + filter_widget.setHidden(!filter_widget.isHidden()); } void ModPage::triggerSearch() { - listModel->searchWithTerm(ui->searchEdit->text(), ui->sortByBox->currentIndex()); + auto changed = filter_widget.changed(); + m_filter = filter_widget.getFilter(); + + if(changed){ + ui->packView->clearSelection(); + ui->packDescription->clear(); + ui->versionSelectionBox->clear(); + updateSelectionButton(); + } + + listModel->searchWithTerm(ui->searchEdit->text(), ui->sortByBox->currentIndex(), changed); } void ModPage::onSelectionChanged(QModelIndex first, QModelIndex second) diff --git a/launcher/ui/pages/modplatform/ModPage.h b/launcher/ui/pages/modplatform/ModPage.h index 06581ab2..85aaede9 100644 --- a/launcher/ui/pages/modplatform/ModPage.h +++ b/launcher/ui/pages/modplatform/ModPage.h @@ -5,9 +5,9 @@ #include "Application.h" #include "modplatform/ModAPI.h" #include "modplatform/ModIndex.h" -#include "ui/dialogs/FilterModsDialog.h" #include "ui/pages/BasePage.h" #include "ui/pages/modplatform/ModModel.h" +#include "ui/widgets/ModFilterWidget.h" class ModDownloadDialog; @@ -40,7 +40,7 @@ class ModPage : public QWidget, public BasePage { virtual auto validateVersion(ModPlatform::IndexedVersion& ver, QString mineVer, QString loaderVer = "") const -> bool = 0; auto apiProvider() const -> const ModAPI* { return api.get(); }; - auto getFilter() const -> const std::shared_ptr { return m_filter; } + auto getFilter() const -> const std::shared_ptr { return m_filter; } auto getCurrent() -> ModPlatform::IndexedPack& { return current; } void updateModVersions(int prev_count = -1); @@ -64,8 +64,8 @@ class ModPage : public QWidget, public BasePage { Ui::ModPage* ui = nullptr; ModDownloadDialog* dialog = nullptr; - FilterModsDialog filter_dialog; - std::shared_ptr m_filter; + ModFilterWidget filter_widget; + std::shared_ptr m_filter; ModPlatform::ListModel* listModel = nullptr; ModPlatform::IndexedPack current; diff --git a/launcher/ui/pages/modplatform/ModPage.ui b/launcher/ui/pages/modplatform/ModPage.ui index 4444583e..afcd9bb7 100644 --- a/launcher/ui/pages/modplatform/ModPage.ui +++ b/launcher/ui/pages/modplatform/ModPage.ui @@ -11,7 +11,7 @@ - + @@ -41,7 +41,7 @@ - + Search @@ -55,7 +55,7 @@ - + @@ -80,15 +80,22 @@ - - - - Filter options - - - + + + + Filter options + + + + + + + Qt::Vertical + + + diff --git a/launcher/ui/pages/modplatform/flame/FlameModPage.cpp b/launcher/ui/pages/modplatform/flame/FlameModPage.cpp index 6e666c4c..864ae8e6 100644 --- a/launcher/ui/pages/modplatform/flame/FlameModPage.cpp +++ b/launcher/ui/pages/modplatform/flame/FlameModPage.cpp @@ -67,25 +67,6 @@ auto FlameModPage::validateVersion(ModPlatform::IndexedVersion& ver, QString min return ver.mcVersion.contains(mineVer); } -// We override this so that it refreshes correctly, otherwise it would show -// invalid mods on the mod list, because the API would return mods for the -// wrong mod loader :( -void FlameModPage::filterMods() -{ - auto ret = filter_dialog.execWithInstance(static_cast(m_instance)); - m_filter = filter_dialog.getFilter(); - - if(ret == QDialog::DialogCode::Accepted){ - // CF API can't handle well this - if(!m_filter->versions.empty()) - listModel->refresh(); - - int prev_count = ui->versionSelectionBox->count(); - ui->versionSelectionBox->clear(); - updateModVersions(prev_count); - } -} - // I don't know why, but doing this on the parent class makes it so that // other mod providers start loading before being selected, at least with // my Qt, so we need to implement this in every derived class... diff --git a/launcher/ui/pages/modplatform/flame/FlameModPage.h b/launcher/ui/pages/modplatform/flame/FlameModPage.h index 7078e889..dc58fd7f 100644 --- a/launcher/ui/pages/modplatform/flame/FlameModPage.h +++ b/launcher/ui/pages/modplatform/flame/FlameModPage.h @@ -56,7 +56,5 @@ class FlameModPage : public ModPage { auto validateVersion(ModPlatform::IndexedVersion& ver, QString mineVer, QString loaderVer = "") const -> bool override; - void filterMods() override; - auto shouldDisplay() const -> bool override; }; diff --git a/launcher/ui/dialogs/FilterModsDialog.cpp b/launcher/ui/widgets/ModFilterWidget.cpp similarity index 57% rename from launcher/ui/dialogs/FilterModsDialog.cpp rename to launcher/ui/widgets/ModFilterWidget.cpp index 9440d897..339ecb4b 100644 --- a/launcher/ui/dialogs/FilterModsDialog.cpp +++ b/launcher/ui/widgets/ModFilterWidget.cpp @@ -1,31 +1,28 @@ -#include "FilterModsDialog.h" -#include "ui_FilterModsDialog.h" +#include "ModFilterWidget.h" +#include "ui_ModFilterWidget.h" -FilterModsDialog::FilterModsDialog(Version def, QWidget* parent) - : QDialog(parent), m_filter(new Filter()), m_internal_filter(new Filter()), ui(new Ui::FilterModsDialog) +ModFilterWidget::ModFilterWidget(Version def, QWidget* parent) + : QTabWidget(parent), m_filter(new Filter()), ui(new Ui::ModFilterWidget) { ui->setupUi(this); m_mcVersion_buttons.addButton(ui->strictVersionButton, VersionButtonID::Strict); + ui->strictVersionButton->click(); m_mcVersion_buttons.addButton(ui->majorVersionButton, VersionButtonID::Major); m_mcVersion_buttons.addButton(ui->allVersionsButton, VersionButtonID::All); //m_mcVersion_buttons.addButton(ui->betweenVersionsButton, VersionButtonID::Between); connect(&m_mcVersion_buttons, SIGNAL(idClicked(int)), this, SLOT(onVersionFilterChanged(int))); - m_internal_filter->versions.push_front(def); - commitChanges(); + m_filter->versions.push_front(def); + + setHidden(true); } -int FilterModsDialog::execWithInstance(MinecraftInstance* instance) +void ModFilterWidget::setInstance(MinecraftInstance* instance) { m_instance = instance; - auto* pressed_button = m_mcVersion_buttons.checkedButton(); - - // Fix first openening behaviour - onVersionFilterChanged(m_previous_mcVersion_id); - auto mcVersionSplit = mcVersionStr().split("."); ui->strictVersionButton->setText( @@ -36,26 +33,15 @@ int FilterModsDialog::execWithInstance(MinecraftInstance* instance) tr("Any version")); //ui->betweenVersionsButton->setText( // tr("Between two versions")); - - int ret = QDialog::exec(); - - if(ret == QDialog::DialogCode::Accepted){ - // If there's no change, let's sey it's a cancel to the caller - if(*m_internal_filter.get() == *m_filter.get()) - return QDialog::DialogCode::Rejected; - - m_previous_mcVersion_id = (VersionButtonID) m_mcVersion_buttons.checkedId(); - commitChanges(); - } else { - pressed_button->click(); - revertChanges(); - } - - m_instance = nullptr; - return ret; } -void FilterModsDialog::disableVersionButton(VersionButtonID id) +auto ModFilterWidget::getFilter() -> std::shared_ptr +{ + m_last_version_id = m_version_id; + return m_filter; +} + +void ModFilterWidget::disableVersionButton(VersionButtonID id) { switch(id){ case(VersionButtonID::Strict): @@ -75,17 +61,7 @@ void FilterModsDialog::disableVersionButton(VersionButtonID id) } } -// Do deep copy -void FilterModsDialog::commitChanges() -{ - m_filter->versions = m_internal_filter->versions; -} -void FilterModsDialog::revertChanges() -{ - m_internal_filter->versions = m_filter->versions; -} - -void FilterModsDialog::onVersionFilterChanged(int id) +void ModFilterWidget::onVersionFilterChanged(int id) { //ui->lowerVersionComboBox->setEnabled(id == VersionButtonID::Between); //ui->upperVersionComboBox->setEnabled(id == VersionButtonID::Between); @@ -93,15 +69,18 @@ void FilterModsDialog::onVersionFilterChanged(int id) auto versionSplit = mcVersionStr().split("."); int index = 0; - m_internal_filter->versions.clear(); + auto cast_id = (VersionButtonID) id; + m_version_id = cast_id; - switch(id){ + m_filter->versions.clear(); + + switch(cast_id){ case(VersionButtonID::Strict): - m_internal_filter->versions.push_front(mcVersion()); + m_filter->versions.push_front(mcVersion()); break; case(VersionButtonID::Major): for(auto i = Version(QString("%1.%2").arg(versionSplit[0], versionSplit[1])); i <= mcVersion(); index++){ - m_internal_filter->versions.push_front(i); + m_filter->versions.push_front(i); i = Version(QString("%1.%2.%3").arg(versionSplit[0], versionSplit[1], QString("%1").arg(index))); } break; @@ -111,12 +90,10 @@ void FilterModsDialog::onVersionFilterChanged(int id) case(VersionButtonID::Between): // TODO break; - default: - break; } } -FilterModsDialog::~FilterModsDialog() +ModFilterWidget::~ModFilterWidget() { delete ui; } diff --git a/launcher/ui/dialogs/FilterModsDialog.h b/launcher/ui/widgets/ModFilterWidget.h similarity index 64% rename from launcher/ui/dialogs/FilterModsDialog.h rename to launcher/ui/widgets/ModFilterWidget.h index fac28ca4..5348882f 100644 --- a/launcher/ui/dialogs/FilterModsDialog.h +++ b/launcher/ui/widgets/ModFilterWidget.h @@ -1,6 +1,6 @@ #pragma once -#include +#include #include #include "Version.h" @@ -10,10 +10,10 @@ class MinecraftInstance; namespace Ui { -class FilterModsDialog; +class ModFilterWidget; } -class FilterModsDialog : public QDialog +class ModFilterWidget : public QTabWidget { Q_OBJECT public: @@ -32,34 +32,34 @@ public: }; std::shared_ptr m_filter; - std::shared_ptr m_internal_filter; public: - explicit FilterModsDialog(Version def, QWidget* parent = nullptr); - ~FilterModsDialog(); + explicit ModFilterWidget(Version def, QWidget* parent = nullptr); + ~ModFilterWidget(); - int execWithInstance(MinecraftInstance* instance); + void setInstance(MinecraftInstance* instance); /// By default all buttons are enabled void disableVersionButton(VersionButtonID); - auto getFilter() -> std::shared_ptr { return m_filter; } + auto getFilter() -> std::shared_ptr; + auto changed() const -> bool { return m_last_version_id != m_version_id; } private: inline auto mcVersionStr() const -> QString { return m_instance ? m_instance->getPackProfile()->getComponentVersion("net.minecraft") : ""; } inline auto mcVersion() const -> Version { return { mcVersionStr() }; } - void commitChanges(); - void revertChanges(); - private slots: void onVersionFilterChanged(int id); private: - Ui::FilterModsDialog* ui; + Ui::ModFilterWidget* ui; MinecraftInstance* m_instance = nullptr; QButtonGroup m_mcVersion_buttons; - VersionButtonID m_previous_mcVersion_id = VersionButtonID::Strict; + + /* Used to tell if the filter was changed since the last getFilter() call */ + VersionButtonID m_last_version_id = VersionButtonID::Strict; + VersionButtonID m_version_id = VersionButtonID::Strict; }; diff --git a/launcher/ui/widgets/ModFilterWidget.ui b/launcher/ui/widgets/ModFilterWidget.ui new file mode 100644 index 00000000..ad1090e2 --- /dev/null +++ b/launcher/ui/widgets/ModFilterWidget.ui @@ -0,0 +1,54 @@ + + + ModFilterWidget + + + + 0 + 0 + 400 + 300 + + + + + 0 + 0 + + + + + Minecraft versions + + + + + + + + allVersions + + + + + + + strictVersion + + + + + + + majorVersion + + + + + + + + + + + From 5f15f51610f861521afdb295df0de6d9407ba951 Mon Sep 17 00:00:00 2001 From: flow Date: Thu, 14 Apr 2022 10:52:23 -0300 Subject: [PATCH 8/9] ui: underline search button text when changing filters This hopefully makes it easier to the user to know that their changes will only apply after hitting the search button. I tried setting the background color, but it seems more unreliable on cross-platform than underlining. Also, it could be worse for daltonic people, so I don't know what to do :( --- launcher/CMakeLists.txt | 7 +++---- launcher/ui/pages/modplatform/ModPage.cpp | 7 +++++++ launcher/ui/widgets/ModFilterWidget.cpp | 12 +++++++++++- launcher/ui/widgets/ModFilterWidget.h | 4 ++++ 4 files changed, 25 insertions(+), 5 deletions(-) diff --git a/launcher/CMakeLists.txt b/launcher/CMakeLists.txt index 8579071a..0ab398e8 100644 --- a/launcher/CMakeLists.txt +++ b/launcher/CMakeLists.txt @@ -824,9 +824,6 @@ SET(LAUNCHER_SOURCES ui/dialogs/SkinUploadDialog.h ui/dialogs/ModDownloadDialog.cpp ui/dialogs/ModDownloadDialog.h - ui/dialogs/FilterModsDialog.cpp - ui/dialogs/FilterModsDialog.h - # GUI - widgets ui/widgets/Common.cpp @@ -851,6 +848,8 @@ SET(LAUNCHER_SOURCES ui/widgets/LogView.h ui/widgets/MCModInfoFrame.cpp ui/widgets/MCModInfoFrame.h + ui/widgets/ModFilterWidget.cpp + ui/widgets/ModFilterWidget.h ui/widgets/ModListView.cpp ui/widgets/ModListView.h ui/widgets/PageContainer.cpp @@ -909,6 +908,7 @@ qt5_wrap_ui(LAUNCHER_UI ui/widgets/InstanceCardWidget.ui ui/widgets/CustomCommands.ui ui/widgets/MCModInfoFrame.ui + ui/widgets/ModFilterWidget.ui ui/dialogs/CopyInstanceDialog.ui ui/dialogs/ProfileSetupDialog.ui ui/dialogs/ProgressDialog.ui @@ -925,7 +925,6 @@ qt5_wrap_ui(LAUNCHER_UI ui/dialogs/LoginDialog.ui ui/dialogs/EditAccountDialog.ui ui/dialogs/ReviewMessageBox.ui - ui/dialogs/FilterModsDialog.ui ) qt5_add_resources(LAUNCHER_RESOURCES diff --git a/launcher/ui/pages/modplatform/ModPage.cpp b/launcher/ui/pages/modplatform/ModPage.cpp index 57c2e45d..29f6b601 100644 --- a/launcher/ui/pages/modplatform/ModPage.cpp +++ b/launcher/ui/pages/modplatform/ModPage.cpp @@ -28,6 +28,13 @@ ModPage::ModPage(ModDownloadDialog* dialog, BaseInstance* instance, ModAPI* api) filter_widget.setInstance(static_cast(m_instance)); m_filter = filter_widget.getFilter(); + + connect(&filter_widget, &ModFilterWidget::filterChanged, this, [&]{ + ui->searchButton->setStyleSheet("text-decoration: underline"); + }); + connect(&filter_widget, &ModFilterWidget::filterUnchanged, this, [&]{ + ui->searchButton->setStyleSheet("text-decoration: none"); + }); } ModPage::~ModPage() diff --git a/launcher/ui/widgets/ModFilterWidget.cpp b/launcher/ui/widgets/ModFilterWidget.cpp index 339ecb4b..ffc8d05d 100644 --- a/launcher/ui/widgets/ModFilterWidget.cpp +++ b/launcher/ui/widgets/ModFilterWidget.cpp @@ -38,6 +38,7 @@ void ModFilterWidget::setInstance(MinecraftInstance* instance) auto ModFilterWidget::getFilter() -> std::shared_ptr { m_last_version_id = m_version_id; + emit filterUnchanged(); return m_filter; } @@ -70,7 +71,11 @@ void ModFilterWidget::onVersionFilterChanged(int id) int index = 0; auto cast_id = (VersionButtonID) id; - m_version_id = cast_id; + if (cast_id != m_version_id) { + m_version_id = cast_id; + } else { + return; + } m_filter->versions.clear(); @@ -91,6 +96,11 @@ void ModFilterWidget::onVersionFilterChanged(int id) // TODO break; } + + if(changed()) + emit filterChanged(); + else + emit filterUnchanged(); } ModFilterWidget::~ModFilterWidget() diff --git a/launcher/ui/widgets/ModFilterWidget.h b/launcher/ui/widgets/ModFilterWidget.h index 5348882f..334fc672 100644 --- a/launcher/ui/widgets/ModFilterWidget.h +++ b/launcher/ui/widgets/ModFilterWidget.h @@ -52,6 +52,10 @@ private: private slots: void onVersionFilterChanged(int id); +public: signals: + void filterChanged(); + void filterUnchanged(); + private: Ui::ModFilterWidget* ui; From 8e9eca6a970bf098c1045658368dc66b39e438ed Mon Sep 17 00:00:00 2001 From: flow Date: Fri, 15 Apr 2022 08:27:40 -0300 Subject: [PATCH 9/9] ui: resize mod download dialog using its parents geometry --- launcher/ui/dialogs/ModDownloadDialog.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/launcher/ui/dialogs/ModDownloadDialog.cpp b/launcher/ui/dialogs/ModDownloadDialog.cpp index 9aac4145..d02ea476 100644 --- a/launcher/ui/dialogs/ModDownloadDialog.cpp +++ b/launcher/ui/dialogs/ModDownloadDialog.cpp @@ -22,7 +22,9 @@ ModDownloadDialog::ModDownloadDialog(const std::shared_ptr &mods : QDialog(parent), mods(mods), m_instance(instance) { setObjectName(QStringLiteral("ModDownloadDialog")); - resize(400, 347); + + resize(std::max(0.5*parent->width(), 400.0), std::max(0.75*parent->height(), 400.0)); + m_verticalLayout = new QVBoxLayout(this); m_verticalLayout->setObjectName(QStringLiteral("verticalLayout"));