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...
This commit is contained in:
flow 2022-04-14 10:27:03 -03:00
parent 63bce04648
commit 277de41200
11 changed files with 138 additions and 247 deletions

View File

@ -1,135 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>FilterModsDialog</class>
<widget class="QDialog" name="FilterModsDialog">
<property name="windowModality">
<enum>Qt::ApplicationModal</enum>
</property>
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>345</width>
<height>169</height>
</rect>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="windowTitle">
<string>Filter options</string>
</property>
<property name="sizeGripEnabled">
<bool>true</bool>
</property>
<property name="modal">
<bool>true</bool>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QGroupBox" name="groupBox">
<property name="sizePolicy">
<sizepolicy hsizetype="MinimumExpanding" vsizetype="MinimumExpanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="title">
<string>Minecraft versions</string>
</property>
<property name="flat">
<bool>false</bool>
</property>
<property name="checkable">
<bool>false</bool>
</property>
<layout class="QVBoxLayout" name="verticalLayout_4">
<item>
<layout class="QFormLayout" name="formLayout_2">
<property name="sizeConstraint">
<enum>QLayout::SetDefaultConstraint</enum>
</property>
<item row="0" column="0">
<layout class="QVBoxLayout" name="verticalLayout_2">
<item>
<widget class="QRadioButton" name="strictVersionButton">
<property name="text">
<string>StrictVersion</string>
</property>
<property name="checked">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<widget class="QRadioButton" name="majorVersionButton">
<property name="text">
<string>MajorVersion</string>
</property>
</widget>
</item>
<item>
<widget class="QRadioButton" name="allVersionsButton">
<property name="text">
<string>AllVersions</string>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QDialogButtonBox" name="buttonBox">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="standardButtons">
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
</property>
</widget>
</item>
</layout>
</widget>
<resources/>
<connections>
<connection>
<sender>buttonBox</sender>
<signal>accepted()</signal>
<receiver>FilterModsDialog</receiver>
<slot>accept()</slot>
<hints>
<hint type="sourcelabel">
<x>248</x>
<y>254</y>
</hint>
<hint type="destinationlabel">
<x>157</x>
<y>274</y>
</hint>
</hints>
</connection>
<connection>
<sender>buttonBox</sender>
<signal>rejected()</signal>
<receiver>FilterModsDialog</receiver>
<slot>reject()</slot>
<hints>
<hint type="sourcelabel">
<x>316</x>
<y>260</y>
</hint>
<hint type="destinationlabel">
<x>286</x>
<y>274</y>
</hint>
</hints>
</connection>
</connections>
</ui>

View File

@ -91,9 +91,14 @@ void ListModel::refresh()
performPaginatedSearch(); 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; currentSearchTerm = term;
currentSort = sort; currentSort = sort;

View File

@ -35,7 +35,7 @@ class ListModel : public QAbstractListModel {
/* Ask the API for more information */ /* Ask the API for more information */
void fetchMore(const QModelIndex& parent) override; void fetchMore(const QModelIndex& parent) override;
void refresh(); 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); void requestModVersions(const ModPlatform::IndexedPack& current);
virtual void loadIndexedPack(ModPlatform::IndexedPack& m, QJsonObject& obj) = 0; virtual void loadIndexedPack(ModPlatform::IndexedPack& m, QJsonObject& obj) = 0;

View File

@ -13,7 +13,7 @@ ModPage::ModPage(ModDownloadDialog* dialog, BaseInstance* instance, ModAPI* api)
, m_instance(instance) , m_instance(instance)
, ui(new Ui::ModPage) , ui(new Ui::ModPage)
, dialog(dialog) , dialog(dialog)
, filter_dialog(static_cast<MinecraftInstance*>(instance)->getPackProfile()->getComponentVersion("net.minecraft"), this) , filter_widget(static_cast<MinecraftInstance*>(instance)->getPackProfile()->getComponentVersion("net.minecraft"), this)
, api(api) , api(api)
{ {
ui->setupUi(this); ui->setupUi(this);
@ -24,7 +24,10 @@ ModPage::ModPage(ModDownloadDialog* dialog, BaseInstance* instance, ModAPI* api)
ui->versionSelectionBox->view()->setVerticalScrollBarPolicy(Qt::ScrollBarAsNeeded); ui->versionSelectionBox->view()->setVerticalScrollBarPolicy(Qt::ScrollBarAsNeeded);
ui->versionSelectionBox->view()->parentWidget()->setMaximumHeight(300); 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<MinecraftInstance*>(m_instance));
m_filter = filter_widget.getFilter();
} }
ModPage::~ModPage() ModPage::~ModPage()
@ -59,21 +62,22 @@ auto ModPage::eventFilter(QObject* watched, QEvent* event) -> bool
void ModPage::filterMods() void ModPage::filterMods()
{ {
auto ret = filter_dialog.execWithInstance(static_cast<MinecraftInstance*>(m_instance)); filter_widget.setHidden(!filter_widget.isHidden());
m_filter = filter_dialog.getFilter();
if(ret == QDialog::DialogCode::Accepted){
listModel->refresh();
int prev_count = ui->versionSelectionBox->count();
ui->versionSelectionBox->clear();
updateModVersions(prev_count);
}
} }
void ModPage::triggerSearch() 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) void ModPage::onSelectionChanged(QModelIndex first, QModelIndex second)

View File

@ -5,9 +5,9 @@
#include "Application.h" #include "Application.h"
#include "modplatform/ModAPI.h" #include "modplatform/ModAPI.h"
#include "modplatform/ModIndex.h" #include "modplatform/ModIndex.h"
#include "ui/dialogs/FilterModsDialog.h"
#include "ui/pages/BasePage.h" #include "ui/pages/BasePage.h"
#include "ui/pages/modplatform/ModModel.h" #include "ui/pages/modplatform/ModModel.h"
#include "ui/widgets/ModFilterWidget.h"
class ModDownloadDialog; 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; virtual auto validateVersion(ModPlatform::IndexedVersion& ver, QString mineVer, QString loaderVer = "") const -> bool = 0;
auto apiProvider() const -> const ModAPI* { return api.get(); }; auto apiProvider() const -> const ModAPI* { return api.get(); };
auto getFilter() const -> const std::shared_ptr<FilterModsDialog::Filter> { return m_filter; } auto getFilter() const -> const std::shared_ptr<ModFilterWidget::Filter> { return m_filter; }
auto getCurrent() -> ModPlatform::IndexedPack& { return current; } auto getCurrent() -> ModPlatform::IndexedPack& { return current; }
void updateModVersions(int prev_count = -1); void updateModVersions(int prev_count = -1);
@ -64,8 +64,8 @@ class ModPage : public QWidget, public BasePage {
Ui::ModPage* ui = nullptr; Ui::ModPage* ui = nullptr;
ModDownloadDialog* dialog = nullptr; ModDownloadDialog* dialog = nullptr;
FilterModsDialog filter_dialog; ModFilterWidget filter_widget;
std::shared_ptr<FilterModsDialog::Filter> m_filter; std::shared_ptr<ModFilterWidget::Filter> m_filter;
ModPlatform::ListModel* listModel = nullptr; ModPlatform::ListModel* listModel = nullptr;
ModPlatform::IndexedPack current; ModPlatform::IndexedPack current;

View File

@ -11,7 +11,7 @@
</rect> </rect>
</property> </property>
<layout class="QGridLayout" name="gridLayout"> <layout class="QGridLayout" name="gridLayout">
<item row="1" column="0" colspan="2"> <item row="1" column="0" colspan="4">
<layout class="QGridLayout" name="gridLayout_3"> <layout class="QGridLayout" name="gridLayout_3">
<item row="1" column="2"> <item row="1" column="2">
<widget class="QTextBrowser" name="packDescription"> <widget class="QTextBrowser" name="packDescription">
@ -41,7 +41,7 @@
</item> </item>
</layout> </layout>
</item> </item>
<item row="0" column="1"> <item row="0" column="3">
<widget class="QPushButton" name="searchButton"> <widget class="QPushButton" name="searchButton">
<property name="text"> <property name="text">
<string>Search</string> <string>Search</string>
@ -55,7 +55,7 @@
</property> </property>
</widget> </widget>
</item> </item>
<item row="2" column="0" colspan="2"> <item row="2" column="0" colspan="4">
<layout class="QGridLayout" name="gridLayout_4" columnstretch="0,0,0"> <layout class="QGridLayout" name="gridLayout_4" columnstretch="0,0,0">
<item row="0" column="2"> <item row="0" column="2">
<widget class="QComboBox" name="versionSelectionBox"/> <widget class="QComboBox" name="versionSelectionBox"/>
@ -80,14 +80,21 @@
</property> </property>
</widget> </widget>
</item> </item>
<item row="1" column="0"> </layout>
</item>
<item row="0" column="1">
<widget class="QPushButton" name="modFilterButton"> <widget class="QPushButton" name="modFilterButton">
<property name="text"> <property name="text">
<string>Filter options</string> <string>Filter options</string>
</property> </property>
</widget> </widget>
</item> </item>
</layout> <item row="0" column="2">
<widget class="Line" name="line">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
</widget>
</item> </item>
</layout> </layout>
</widget> </widget>

View File

@ -67,25 +67,6 @@ auto FlameModPage::validateVersion(ModPlatform::IndexedVersion& ver, QString min
return ver.mcVersion.contains(mineVer); 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<MinecraftInstance*>(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 // 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 // other mod providers start loading before being selected, at least with
// my Qt, so we need to implement this in every derived class... // my Qt, so we need to implement this in every derived class...

View File

@ -56,7 +56,5 @@ class FlameModPage : public ModPage {
auto validateVersion(ModPlatform::IndexedVersion& ver, QString mineVer, QString loaderVer = "") const -> bool override; auto validateVersion(ModPlatform::IndexedVersion& ver, QString mineVer, QString loaderVer = "") const -> bool override;
void filterMods() override;
auto shouldDisplay() const -> bool override; auto shouldDisplay() const -> bool override;
}; };

View File

@ -1,31 +1,28 @@
#include "FilterModsDialog.h" #include "ModFilterWidget.h"
#include "ui_FilterModsDialog.h" #include "ui_ModFilterWidget.h"
FilterModsDialog::FilterModsDialog(Version def, QWidget* parent) ModFilterWidget::ModFilterWidget(Version def, QWidget* parent)
: QDialog(parent), m_filter(new Filter()), m_internal_filter(new Filter()), ui(new Ui::FilterModsDialog) : QTabWidget(parent), m_filter(new Filter()), ui(new Ui::ModFilterWidget)
{ {
ui->setupUi(this); ui->setupUi(this);
m_mcVersion_buttons.addButton(ui->strictVersionButton, VersionButtonID::Strict); m_mcVersion_buttons.addButton(ui->strictVersionButton, VersionButtonID::Strict);
ui->strictVersionButton->click();
m_mcVersion_buttons.addButton(ui->majorVersionButton, VersionButtonID::Major); m_mcVersion_buttons.addButton(ui->majorVersionButton, VersionButtonID::Major);
m_mcVersion_buttons.addButton(ui->allVersionsButton, VersionButtonID::All); 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))); connect(&m_mcVersion_buttons, SIGNAL(idClicked(int)), this, SLOT(onVersionFilterChanged(int)));
m_internal_filter->versions.push_front(def); m_filter->versions.push_front(def);
commitChanges();
setHidden(true);
} }
int FilterModsDialog::execWithInstance(MinecraftInstance* instance) void ModFilterWidget::setInstance(MinecraftInstance* instance)
{ {
m_instance = instance; m_instance = instance;
auto* pressed_button = m_mcVersion_buttons.checkedButton();
// Fix first openening behaviour
onVersionFilterChanged(m_previous_mcVersion_id);
auto mcVersionSplit = mcVersionStr().split("."); auto mcVersionSplit = mcVersionStr().split(".");
ui->strictVersionButton->setText( ui->strictVersionButton->setText(
@ -36,26 +33,15 @@ int FilterModsDialog::execWithInstance(MinecraftInstance* instance)
tr("Any version")); tr("Any version"));
//ui->betweenVersionsButton->setText( //ui->betweenVersionsButton->setText(
// tr("Between two versions")); // 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<Filter>
{
m_last_version_id = m_version_id;
return m_filter;
}
void ModFilterWidget::disableVersionButton(VersionButtonID id)
{ {
switch(id){ switch(id){
case(VersionButtonID::Strict): case(VersionButtonID::Strict):
@ -75,17 +61,7 @@ void FilterModsDialog::disableVersionButton(VersionButtonID id)
} }
} }
// Do deep copy void ModFilterWidget::onVersionFilterChanged(int id)
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); //ui->lowerVersionComboBox->setEnabled(id == VersionButtonID::Between);
//ui->upperVersionComboBox->setEnabled(id == VersionButtonID::Between); //ui->upperVersionComboBox->setEnabled(id == VersionButtonID::Between);
@ -93,15 +69,18 @@ void FilterModsDialog::onVersionFilterChanged(int id)
auto versionSplit = mcVersionStr().split("."); auto versionSplit = mcVersionStr().split(".");
int index = 0; 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): case(VersionButtonID::Strict):
m_internal_filter->versions.push_front(mcVersion()); m_filter->versions.push_front(mcVersion());
break; break;
case(VersionButtonID::Major): case(VersionButtonID::Major):
for(auto i = Version(QString("%1.%2").arg(versionSplit[0], versionSplit[1])); i <= mcVersion(); index++){ 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))); i = Version(QString("%1.%2.%3").arg(versionSplit[0], versionSplit[1], QString("%1").arg(index)));
} }
break; break;
@ -111,12 +90,10 @@ void FilterModsDialog::onVersionFilterChanged(int id)
case(VersionButtonID::Between): case(VersionButtonID::Between):
// TODO // TODO
break; break;
default:
break;
} }
} }
FilterModsDialog::~FilterModsDialog() ModFilterWidget::~ModFilterWidget()
{ {
delete ui; delete ui;
} }

View File

@ -1,6 +1,6 @@
#pragma once #pragma once
#include <QDialog> #include <QTabWidget>
#include <QButtonGroup> #include <QButtonGroup>
#include "Version.h" #include "Version.h"
@ -10,10 +10,10 @@
class MinecraftInstance; class MinecraftInstance;
namespace Ui { namespace Ui {
class FilterModsDialog; class ModFilterWidget;
} }
class FilterModsDialog : public QDialog class ModFilterWidget : public QTabWidget
{ {
Q_OBJECT Q_OBJECT
public: public:
@ -32,34 +32,34 @@ public:
}; };
std::shared_ptr<Filter> m_filter; std::shared_ptr<Filter> m_filter;
std::shared_ptr<Filter> m_internal_filter;
public: public:
explicit FilterModsDialog(Version def, QWidget* parent = nullptr); explicit ModFilterWidget(Version def, QWidget* parent = nullptr);
~FilterModsDialog(); ~ModFilterWidget();
int execWithInstance(MinecraftInstance* instance); void setInstance(MinecraftInstance* instance);
/// By default all buttons are enabled /// By default all buttons are enabled
void disableVersionButton(VersionButtonID); void disableVersionButton(VersionButtonID);
auto getFilter() -> std::shared_ptr<Filter> { return m_filter; } auto getFilter() -> std::shared_ptr<Filter>;
auto changed() const -> bool { return m_last_version_id != m_version_id; }
private: private:
inline auto mcVersionStr() const -> QString { return m_instance ? m_instance->getPackProfile()->getComponentVersion("net.minecraft") : ""; } inline auto mcVersionStr() const -> QString { return m_instance ? m_instance->getPackProfile()->getComponentVersion("net.minecraft") : ""; }
inline auto mcVersion() const -> Version { return { mcVersionStr() }; } inline auto mcVersion() const -> Version { return { mcVersionStr() }; }
void commitChanges();
void revertChanges();
private slots: private slots:
void onVersionFilterChanged(int id); void onVersionFilterChanged(int id);
private: private:
Ui::FilterModsDialog* ui; Ui::ModFilterWidget* ui;
MinecraftInstance* m_instance = nullptr; MinecraftInstance* m_instance = nullptr;
QButtonGroup m_mcVersion_buttons; 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;
}; };

View File

@ -0,0 +1,54 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>ModFilterWidget</class>
<widget class="QTabWidget" name="ModFilterWidget">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>400</width>
<height>300</height>
</rect>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Minimum">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<widget class="QWidget" name="VersionPage">
<attribute name="title">
<string>Minecraft versions</string>
</attribute>
<layout class="QGridLayout" name="gridLayout">
<item row="0" column="0">
<layout class="QFormLayout" name="formLayout">
<item row="2" column="0">
<widget class="QRadioButton" name="allVersionsButton">
<property name="text">
<string>allVersions</string>
</property>
</widget>
</item>
<item row="0" column="0">
<widget class="QRadioButton" name="strictVersionButton">
<property name="text">
<string>strictVersion</string>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QRadioButton" name="majorVersionButton">
<property name="text">
<string>majorVersion</string>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</widget>
</widget>
<resources/>
<connections/>
</ui>