Updated filters

Signed-off-by: Trial97 <alexandru.tripon97@gmail.com>
This commit is contained in:
Trial97 2023-10-18 09:00:45 +03:00
parent b54376062e
commit fea4c4eba8
No known key found for this signature in database
GPG Key ID: 55EF5DA53DB36318
10 changed files with 311 additions and 178 deletions

View File

@ -23,6 +23,7 @@
#include <memory>
#include "Json.h"
#include "QObjectPtr.h"
#include "minecraft/PackProfile.h"
#include "minecraft/mod/MetadataHandler.h"
#include "modplatform/ModIndex.h"
#include "modplatform/ResourceAPI.h"

View File

@ -94,10 +94,9 @@ auto ProviderCapabilities::hash(ResourceProvider p, QIODevice* device, QString t
{
QCryptographicHash::Algorithm algo = QCryptographicHash::Sha1;
switch (p) {
case ResourceProvider::MODRINTH: {
case ResourceProvider::MODRINTH:
algo = (type == "sha1") ? QCryptographicHash::Sha1 : QCryptographicHash::Sha512;
break;
}
case ResourceProvider::FLAME:
algo = (type == "sha1") ? QCryptographicHash::Sha1 : QCryptographicHash::Md5;
break;

View File

@ -27,6 +27,7 @@
#include "Application.h"
#include "ResourceDownloadTask.h"
#include "minecraft/PackProfile.h"
#include "minecraft/mod/ModFolderModel.h"
#include "minecraft/mod/ResourcePackFolderModel.h"
#include "minecraft/mod/ShaderPackFolderModel.h"

View File

@ -25,15 +25,18 @@ ResourceAPI::SearchArgs ModModel::createSearchArguments()
Q_ASSERT(m_filter);
std::optional<std::list<Version>> versions{};
auto loaders = profile->getSupportedModLoaders();
{ // Version filter
if (!m_filter->versions.empty())
versions = m_filter->versions;
if (m_filter->loaders)
loaders = m_filter->loaders;
}
auto sort = getCurrentSortingMethodByIndex();
return { ModPlatform::ResourceType::MOD, m_next_search_offset, m_search_term, sort, profile->getSupportedModLoaders(), versions };
return { ModPlatform::ResourceType::MOD, m_next_search_offset, m_search_term, sort, loaders, versions };
}
ResourceAPI::VersionSearchArgs ModModel::createVersionsArguments(QModelIndex& entry)
@ -45,10 +48,13 @@ ResourceAPI::VersionSearchArgs ModModel::createVersionsArguments(QModelIndex& en
Q_ASSERT(m_filter);
std::optional<std::list<Version>> versions{};
auto loaders = profile->getSupportedModLoaders();
if (!m_filter->versions.empty())
versions = m_filter->versions;
if (m_filter->loaders)
loaders = m_filter->loaders;
return { pack, versions, profile->getSupportedModLoaders() };
return { pack, versions, loaders };
}
ResourceAPI::ProjectInfoArgs ModModel::createInfoArguments(QModelIndex& entry)

View File

@ -71,7 +71,6 @@ void ModPage::setFilterWidget(unique_qobject_ptr<ModFilterWidget>& widget)
m_ui->gridLayout_3->addWidget(m_filter_widget.get(), 0, 0, 1, m_ui->gridLayout_3->columnCount());
m_filter_widget->setInstance(&static_cast<MinecraftInstance&>(m_base_instance));
m_filter = m_filter_widget->getFilter();
connect(m_filter_widget.get(), &ModFilterWidget::filterChanged, this,
@ -89,13 +88,14 @@ void ModPage::filterMods()
void ModPage::triggerSearch()
{
auto changed = m_filter_widget->changed();
m_filter = m_filter_widget->getFilter();
m_ui->packView->clearSelection();
m_ui->packDescription->clear();
m_ui->versionSelectionBox->clear();
updateSelectionButton();
static_cast<ModModel*>(m_model)->searchWithTerm(getSearchTerm(), m_ui->sortByBox->currentData().toUInt(), m_filter_widget->changed());
static_cast<ModModel*>(m_model)->searchWithTerm(getSearchTerm(), m_ui->sortByBox->currentData().toUInt(), changed);
m_fetch_progress.watch(m_model->activeSearchJob().get());
}
@ -116,6 +116,9 @@ void ModPage::updateVersionList()
auto packProfile = (dynamic_cast<MinecraftInstance&>(m_base_instance)).getPackProfile();
QString mcVersion = packProfile->getComponentVersion("net.minecraft");
auto loaders = packProfile->getSupportedModLoaders();
if (m_filter->loaders)
loaders = m_filter->loaders;
auto current_pack = getCurrentPack();
if (!current_pack)
@ -124,7 +127,7 @@ void ModPage::updateVersionList()
auto version = current_pack->versions[i];
bool valid = false;
for (auto& mcVer : m_filter->versions) {
if (validateVersion(version, mcVer.toString(), packProfile->getSupportedModLoaders())) {
if (validateVersion(version, mcVer.toString(), loaders)) {
valid = true;
break;
}

View File

@ -31,8 +31,7 @@ class ModPage : public ResourcePage {
auto page = new T(dialog, instance);
auto model = static_cast<ModModel*>(page->getModel());
auto filter_widget =
ModFilterWidget::create(static_cast<MinecraftInstance&>(instance).getPackProfile()->getComponentVersion("net.minecraft"), page);
auto filter_widget = ModFilterWidget::create(&static_cast<MinecraftInstance&>(instance), page);
page->setFilterWidget(filter_widget);
model->setFilter(page->getFilter());

View File

@ -6,6 +6,7 @@
#include "Json.h"
#include "minecraft/PackProfile.h"
#include "modplatform/flame/FlameAPI.h"
#include "modplatform/flame/FlameModIndex.h"

View File

@ -1,13 +1,70 @@
#include "ModFilterWidget.h"
#include <qcheckbox.h>
#include <qcombobox.h>
#include "BaseVersionList.h"
#include "meta/Index.h"
#include "modplatform/ModIndex.h"
#include "ui_ModFilterWidget.h"
#include "Application.h"
#include "minecraft/PackProfile.h"
unique_qobject_ptr<ModFilterWidget> ModFilterWidget::create(Version default_version, QWidget* parent)
unique_qobject_ptr<ModFilterWidget> ModFilterWidget::create(MinecraftInstance* instance, QWidget* parent)
{
auto filter_widget = new ModFilterWidget(default_version, parent);
return unique_qobject_ptr<ModFilterWidget>(new ModFilterWidget(instance, parent));
}
if (!filter_widget->versionList()->isLoaded()) {
ModFilterWidget::ModFilterWidget(MinecraftInstance* instance, QWidget* parent)
: QTabWidget(parent), ui(new Ui::ModFilterWidget), m_instance(instance), m_filter(new Filter())
{
ui->setupUi(this);
m_versions_proxy = new VersionProxyModel(this);
ui->versionsCb->setModel(m_versions_proxy);
m_versions_proxy->setFilter(BaseVersionList::TypeRole, new RegexpFilter("(release)", false));
ui->versionsCb->setStyleSheet("combobox-popup: 0;");
connect(ui->snapshotsCb, &QCheckBox::stateChanged, this, &ModFilterWidget::onIncludeSnapshotsChanged);
connect(ui->versionsCb, &QComboBox::currentIndexChanged, this, &ModFilterWidget::onVersionFilterChanged);
connect(ui->neoForgeCb, &QCheckBox::stateChanged, this, &ModFilterWidget::onLoadersFilterChanged);
connect(ui->forgeCb, &QCheckBox::stateChanged, this, &ModFilterWidget::onLoadersFilterChanged);
connect(ui->fabricCb, &QCheckBox::stateChanged, this, &ModFilterWidget::onLoadersFilterChanged);
connect(ui->quiltCb, &QCheckBox::stateChanged, this, &ModFilterWidget::onLoadersFilterChanged);
connect(ui->liteLoaderCb, &QCheckBox::stateChanged, this, &ModFilterWidget::onLoadersFilterChanged);
connect(ui->cauldronCb, &QCheckBox::stateChanged, this, &ModFilterWidget::onLoadersFilterChanged);
ui->liteLoaderCb->hide();
ui->cauldronCb->hide();
connect(ui->serverEnv, &QCheckBox::stateChanged, this, &ModFilterWidget::onSideFilterChanged);
connect(ui->clientEnv, &QCheckBox::stateChanged, this, &ModFilterWidget::onSideFilterChanged);
connect(ui->hide_installed, &QCheckBox::stateChanged, this, &ModFilterWidget::onHideInstalledFilterChanged);
setHidden(true);
loadVersionList();
prepareBasicFilter();
}
auto ModFilterWidget::getFilter() -> std::shared_ptr<Filter>
{
m_filter_changed = false;
emit filterUnchanged();
return m_filter;
}
ModFilterWidget::~ModFilterWidget()
{
delete ui;
}
void ModFilterWidget::loadVersionList()
{
m_version_list = APPLICATION->metadataIndex()->get("net.minecraft");
if (!m_version_list->isLoaded()) {
QEventLoop load_version_list_loop;
QTimer time_limit_for_list_load;
@ -16,10 +73,12 @@ unique_qobject_ptr<ModFilterWidget> ModFilterWidget::create(Version default_vers
time_limit_for_list_load.callOnTimeout(&load_version_list_loop, &QEventLoop::quit);
time_limit_for_list_load.start(4000);
auto task = filter_widget->versionList()->getLoadTask();
auto task = m_version_list->getLoadTask();
connect(task.get(), &Task::failed,
[filter_widget] { filter_widget->disableVersionButton(VersionButtonID::Major, tr("failed to get version index")); });
connect(task.get(), &Task::failed, [this] {
ui->versionsCb->setEnabled(false);
ui->snapshotsCb->setEnabled(false);
});
connect(task.get(), &Task::finished, &load_version_list_loop, &QEventLoop::quit);
if (!task->isRunning())
@ -29,128 +88,93 @@ unique_qobject_ptr<ModFilterWidget> ModFilterWidget::create(Version default_vers
if (time_limit_for_list_load.isActive())
time_limit_for_list_load.stop();
}
return unique_qobject_ptr<ModFilterWidget>(filter_widget);
m_versions_proxy->setSourceModel(m_version_list.get());
}
ModFilterWidget::ModFilterWidget(Version def, QWidget* parent) : QTabWidget(parent), m_filter(new Filter()), ui(new Ui::ModFilterWidget)
void ModFilterWidget::prepareBasicFilter()
{
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_filter->versions.push_front(def);
m_version_list = APPLICATION->metadataIndex()->get("net.minecraft");
setHidden(true);
m_filter->hideInstalled = false;
m_filter->side = ""; // or "both"t
auto loaders = m_instance->getPackProfile()->getSupportedModLoaders().value();
ui->neoForgeCb->setChecked(loaders & ModPlatform::NeoForge);
ui->forgeCb->setChecked(loaders & ModPlatform::Forge);
ui->fabricCb->setChecked(loaders & ModPlatform::Fabric);
ui->quiltCb->setChecked(loaders & ModPlatform::Quilt);
ui->liteLoaderCb->setChecked(loaders & ModPlatform::LiteLoader);
ui->cauldronCb->setChecked(loaders & ModPlatform::Cauldron);
m_filter->loaders = loaders;
auto def = m_instance->getPackProfile()->getComponentVersion("net.minecraft");
m_filter->versions.push_front(Version{ def });
m_versions_proxy->setCurrentVersion(def);
ui->versionsCb->setCurrentIndex(m_versions_proxy->getVersion(def).row());
}
void ModFilterWidget::setInstance(MinecraftInstance* instance)
void ModFilterWidget::onIncludeSnapshotsChanged()
{
m_instance = instance;
ui->strictVersionButton->setText(tr("Strict match (= %1)").arg(mcVersionStr()));
// we can't do this for snapshots sadly
if (mcVersionStr().contains('.')) {
auto mcVersionSplit = mcVersionStr().split(".");
ui->majorVersionButton->setText(tr("Major version match (= %1.%2.x)").arg(mcVersionSplit[0], mcVersionSplit[1]));
} else {
ui->majorVersionButton->setText(tr("Major version match (unsupported)"));
disableVersionButton(Major);
}
ui->allVersionsButton->setText(tr("Any version"));
// ui->betweenVersionsButton->setText(
// tr("Between two versions"));
QString filter = "(release)";
if (ui->snapshotsCb->isChecked())
filter += "|(snapshot)";
m_versions_proxy->setFilter(BaseVersionList::TypeRole, new RegexpFilter(filter, false));
}
auto ModFilterWidget::getFilter() -> std::shared_ptr<Filter>
void ModFilterWidget::onVersionFilterChanged()
{
m_last_version_id = m_version_id;
emit filterUnchanged();
return m_filter;
}
void ModFilterWidget::disableVersionButton(VersionButtonID id, QString reason)
{
QAbstractButton* btn = nullptr;
switch (id) {
case (VersionButtonID::Strict):
btn = ui->strictVersionButton;
break;
case (VersionButtonID::Major):
btn = ui->majorVersionButton;
break;
case (VersionButtonID::All):
btn = ui->allVersionsButton;
break;
case (VersionButtonID::Between):
default:
break;
}
if (btn) {
btn->setEnabled(false);
if (!reason.isEmpty())
btn->setText(btn->text() + QString(" (%1)").arg(reason));
}
}
void ModFilterWidget::onVersionFilterChanged(int id)
{
// ui->lowerVersionComboBox->setEnabled(id == VersionButtonID::Between);
// ui->upperVersionComboBox->setEnabled(id == VersionButtonID::Between);
int index = 1;
auto cast_id = (VersionButtonID)id;
if (cast_id != m_version_id) {
m_version_id = cast_id;
} else {
return;
}
auto version = ui->versionsCb->currentData(BaseVersionList::VersionIdRole).toString();
m_filter->versions.clear();
m_filter->versions.push_front(version);
m_filter_changed = true;
emit filterChanged();
}
switch (cast_id) {
case (VersionButtonID::Strict):
m_filter->versions.push_front(mcVersion());
break;
case (VersionButtonID::Major): {
auto versionSplit = mcVersionStr().split(".");
auto major_version = QString("%1.%2").arg(versionSplit[0], versionSplit[1]);
QString version_str = major_version;
while (m_version_list->hasVersion(version_str)) {
m_filter->versions.emplace_back(version_str);
version_str = QString("%1.%2").arg(major_version, QString::number(index++));
}
break;
}
case (VersionButtonID::All):
// Empty list to avoid enumerating all versions :P
break;
case (VersionButtonID::Between):
// TODO
break;
}
if (changed())
void ModFilterWidget::onLoadersFilterChanged()
{
ModPlatform::ModLoaderTypes loaders;
if (ui->neoForgeCb->isChecked())
loaders |= ModPlatform::NeoForge;
if (ui->forgeCb->isChecked())
loaders |= ModPlatform::Forge;
if (ui->fabricCb->isChecked())
loaders |= ModPlatform::Fabric;
if (ui->quiltCb->isChecked())
loaders |= ModPlatform::Quilt;
if (ui->cauldronCb->isChecked())
loaders |= ModPlatform::Cauldron;
if (ui->liteLoaderCb->isChecked())
loaders |= ModPlatform::LiteLoader;
m_filter_changed = loaders != m_filter->loaders;
m_filter->loaders = loaders;
if (m_filter_changed)
emit filterChanged();
else
emit filterUnchanged();
}
ModFilterWidget::~ModFilterWidget()
void ModFilterWidget::onSideFilterChanged()
{
delete ui;
QString side;
if (ui->serverEnv->isChecked())
side = "server";
if (ui->clientEnv->isChecked()) {
if (side.isEmpty())
side = "client";
else
side = ""; // or both
}
m_filter_changed = side != m_filter->side;
m_filter->side = side;
if (m_filter_changed)
emit filterChanged();
else
emit filterUnchanged();
}
void ModFilterWidget::onHideInstalledFilterChanged()
{
auto hide = ui->hide_installed->isChecked();
m_filter_changed = hide != m_filter->hideInstalled;
m_filter->hideInstalled = hide;
if (m_filter_changed)
emit filterChanged();
else
emit filterUnchanged();
}

View File

@ -5,11 +5,11 @@
#include "Version.h"
#include "meta/Index.h"
#include "VersionProxyModel.h"
#include "meta/VersionList.h"
#include "minecraft/MinecraftInstance.h"
#include "minecraft/PackProfile.h"
#include "modplatform/ModIndex.h"
class MinecraftInstance;
@ -20,42 +20,37 @@ class ModFilterWidget;
class ModFilterWidget : public QTabWidget {
Q_OBJECT
public:
enum VersionButtonID { Strict = 0, Major = 1, All = 2, Between = 3 };
struct Filter {
std::list<Version> versions;
ModPlatform::ModLoaderTypes loaders;
QString side;
bool hideInstalled;
bool operator==(const Filter& other) const { return versions == other.versions; }
bool operator==(const Filter& other) const
{
return hideInstalled == other.hideInstalled && side == other.side && loaders == other.loaders && versions == other.versions;
}
bool operator!=(const Filter& other) const { return !(*this == other); }
};
std::shared_ptr<Filter> m_filter;
public:
static unique_qobject_ptr<ModFilterWidget> create(Version default_version, QWidget* parent = nullptr);
~ModFilterWidget();
void setInstance(MinecraftInstance* instance);
/// By default all buttons are enabled
void disableVersionButton(VersionButtonID, QString reason = {});
static unique_qobject_ptr<ModFilterWidget> create(MinecraftInstance* instance, QWidget* parent = nullptr);
virtual ~ModFilterWidget();
auto getFilter() -> std::shared_ptr<Filter>;
auto changed() const -> bool { return m_last_version_id != m_version_id; }
Meta::VersionList::Ptr versionList() { return m_version_list; }
auto changed() const -> bool { return m_filter_changed; }
private:
ModFilterWidget(Version def, QWidget* parent = nullptr);
ModFilterWidget(MinecraftInstance* instance, QWidget* parent = nullptr);
inline auto mcVersionStr() const -> QString
{
return m_instance ? m_instance->getPackProfile()->getComponentVersion("net.minecraft") : "";
}
inline auto mcVersion() const -> Version { return { mcVersionStr() }; }
void loadVersionList();
void prepareBasicFilter();
private slots:
void onVersionFilterChanged(int id);
void onVersionFilterChanged();
void onLoadersFilterChanged();
void onSideFilterChanged();
void onHideInstalledFilterChanged();
void onIncludeSnapshotsChanged();
public:
signals:
@ -66,13 +61,9 @@ class ModFilterWidget : public QTabWidget {
Ui::ModFilterWidget* ui;
MinecraftInstance* m_instance = nullptr;
/* Version stuff */
QButtonGroup m_mcVersion_buttons;
std::shared_ptr<Filter> m_filter;
bool m_filter_changed = false;
Meta::VersionList::Ptr m_version_list;
/* 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;
VersionProxyModel* m_versions_proxy = nullptr;
};

View File

@ -7,7 +7,7 @@
<x>0</x>
<y>0</y>
<width>400</width>
<height>300</height>
<height>127</height>
</rect>
</property>
<property name="sizePolicy">
@ -16,35 +16,143 @@
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="currentIndex">
<number>0</number>
</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 notr="true">allVersions</string>
</property>
</widget>
</item>
<item row="0" column="0">
<widget class="QRadioButton" name="strictVersionButton">
<property name="text">
<string notr="true">strictVersion</string>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QRadioButton" name="majorVersionButton">
<widget class="QComboBox" name="versionsCb">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="maxVisibleItems">
<number>5</number>
</property>
<property name="sizeAdjustPolicy">
<enum>QComboBox::AdjustToContentsOnFirstShow</enum>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QCheckBox" name="snapshotsCb">
<property name="text">
<string notr="true">majorVersion</string>
<string>Include Snapshots</string>
</property>
</widget>
</item>
</layout>
</widget>
<widget class="QWidget" name="LoadersPage">
<attribute name="title">
<string>Loaders</string>
</attribute>
<layout class="QGridLayout" name="gridLayout_2">
<property name="sizeConstraint">
<enum>QLayout::SetMinimumSize</enum>
</property>
<item row="3" column="3">
<widget class="QCheckBox" name="liteLoaderCb">
<property name="enabled">
<bool>false</bool>
</property>
<property name="text">
<string>LiteLoader</string>
</property>
</widget>
</item>
<item row="3" column="0">
<widget class="QCheckBox" name="cauldronCb">
<property name="enabled">
<bool>false</bool>
</property>
<property name="text">
<string>Cauldron</string>
</property>
</widget>
</item>
<item row="0" column="0">
<widget class="QCheckBox" name="neoForgeCb">
<property name="text">
<string>NeoForge</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QCheckBox" name="forgeCb">
<property name="text">
<string>Forge</string>
</property>
</widget>
</item>
<item row="0" column="3">
<widget class="QCheckBox" name="quiltCb">
<property name="text">
<string>Quilt</string>
</property>
</widget>
</item>
<item row="0" column="2">
<widget class="QCheckBox" name="fabricCb">
<property name="text">
<string>Fabric</string>
</property>
</widget>
</item>
</layout>
</widget>
<widget class="QWidget" name="ModPage">
<attribute name="title">
<string>Others</string>
</attribute>
<layout class="QGridLayout" name="gridLayout1">
<item row="0" column="0">
<widget class="QGroupBox" name="envBox">
<property name="title">
<string>Environments</string>
</property>
<layout class="QHBoxLayout" name="horizontalLayout">
<property name="sizeConstraint">
<enum>QLayout::SetDefaultConstraint</enum>
</property>
<item>
<widget class="QCheckBox" name="clientEnv">
<property name="text">
<string>Client</string>
</property>
</widget>
</item>
<item>
<widget class="QCheckBox" name="serverEnv">
<property name="text">
<string>Server</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item row="0" column="1">
<widget class="QGroupBox" name="groupBox">
<property name="title">
<string>Instaled status</string>
</property>
<layout class="QHBoxLayout" name="horizontalLayout_2">
<item>
<widget class="QCheckBox" name="hide_installed">
<property name="text">
<string>Hide already installed</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
</layout>
</widget>