Connected filters

Signed-off-by: Trial97 <alexandru.tripon97@gmail.com>
This commit is contained in:
Trial97 2023-10-21 18:28:33 +03:00
parent 4850434c67
commit 9e85297f7a
No known key found for this signature in database
GPG Key ID: 55EF5DA53DB36318
23 changed files with 214 additions and 152 deletions

View File

@ -73,6 +73,7 @@ class ResourceAPI {
std::optional<SortingMethod> sorting; std::optional<SortingMethod> sorting;
std::optional<ModPlatform::ModLoaderTypes> loaders; std::optional<ModPlatform::ModLoaderTypes> loaders;
std::optional<std::list<Version> > versions; std::optional<std::list<Version> > versions;
std::optional<QString> side;
}; };
struct SearchCallbacks { struct SearchCallbacks {
std::function<void(QJsonDocument&)> on_succeed; std::function<void(QJsonDocument&)> on_succeed;

View File

@ -79,10 +79,6 @@ void FlameMod::loadIndexedPackVersions(ModPlatform::IndexedPack& pack,
const BaseInstance* inst) const BaseInstance* inst)
{ {
QVector<ModPlatform::IndexedVersion> unsortedVersions; QVector<ModPlatform::IndexedVersion> unsortedVersions;
auto profile = (dynamic_cast<const MinecraftInstance*>(inst))->getPackProfile();
QString mcVersion = profile->getComponentVersion("net.minecraft");
auto loaders = profile->getSupportedModLoaders();
for (auto versionIter : arr) { for (auto versionIter : arr) {
auto obj = versionIter.toObject(); auto obj = versionIter.toObject();
@ -90,8 +86,7 @@ void FlameMod::loadIndexedPackVersions(ModPlatform::IndexedPack& pack,
if (!file.addonId.isValid()) if (!file.addonId.isValid())
file.addonId = pack.addonId; file.addonId = pack.addonId;
if (file.fileId.isValid() && if (file.fileId.isValid()) // Heuristic to check if the returned value is valid
(!loaders.has_value() || !file.loaders || loaders.value() & file.loaders)) // Heuristic to check if the returned value is valid
unsortedVersions.append(file); unsortedVersions.append(file);
} }

View File

@ -56,6 +56,18 @@ class ModrinthAPI : public NetworkResourceAPI {
return l.join(','); return l.join(',');
} }
static auto getSideFilters(QString side) -> const QString
{
if (side.isEmpty() || side == "both") {
return {};
}
if (side == "client")
return QString("\"client_side:required\",\"client_side:optional\"");
if (side == "server")
return QString("\"server_side:required\",\"server_side:optional\"");
return {};
}
private: private:
[[nodiscard]] static QString resourceTypeParameter(ModPlatform::ResourceType type) [[nodiscard]] static QString resourceTypeParameter(ModPlatform::ResourceType type)
{ {
@ -73,6 +85,7 @@ class ModrinthAPI : public NetworkResourceAPI {
return ""; return "";
} }
[[nodiscard]] QString createFacets(SearchArgs const& args) const [[nodiscard]] QString createFacets(SearchArgs const& args) const
{ {
QStringList facets_list; QStringList facets_list;
@ -81,6 +94,11 @@ class ModrinthAPI : public NetworkResourceAPI {
facets_list.append(QString("[%1]").arg(getModLoaderFilters(args.loaders.value()))); facets_list.append(QString("[%1]").arg(getModLoaderFilters(args.loaders.value())));
if (args.versions.has_value()) if (args.versions.has_value())
facets_list.append(QString("[%1]").arg(getGameVersionsArray(args.versions.value()))); facets_list.append(QString("[%1]").arg(getGameVersionsArray(args.versions.value())));
if (args.side.has_value()) {
auto side = getSideFilters(args.side.value());
if (!side.isEmpty())
facets_list.append(QString("[%1]").arg(side));
}
facets_list.append(QString("[\"project_type:%1\"]").arg(resourceTypeParameter(args.type))); facets_list.append(QString("[\"project_type:%1\"]").arg(resourceTypeParameter(args.type)));
return QString("[%1]").arg(facets_list.join(',')); return QString("[%1]").arg(facets_list.join(','));

View File

@ -112,16 +112,11 @@ void Modrinth::loadExtraPackData(ModPlatform::IndexedPack& pack, QJsonObject& ob
void Modrinth::loadIndexedPackVersions(ModPlatform::IndexedPack& pack, QJsonArray& arr, const BaseInstance* inst) void Modrinth::loadIndexedPackVersions(ModPlatform::IndexedPack& pack, QJsonArray& arr, const BaseInstance* inst)
{ {
QVector<ModPlatform::IndexedVersion> unsortedVersions; QVector<ModPlatform::IndexedVersion> unsortedVersions;
auto profile = (dynamic_cast<const MinecraftInstance*>(inst))->getPackProfile();
QString mcVersion = profile->getComponentVersion("net.minecraft");
auto loaders = profile->getSupportedModLoaders();
for (auto versionIter : arr) { for (auto versionIter : arr) {
auto obj = versionIter.toObject(); auto obj = versionIter.toObject();
auto file = loadIndexedPackVersion(obj); auto file = loadIndexedPackVersion(obj);
if (file.fileId.isValid() && if (file.fileId.isValid()) // Heuristic to check if the returned value is valid
(!loaders.has_value() || !file.loaders || loaders.value() & file.loaders)) // Heuristic to check if the returned value is valid
unsortedVersions.append(file); unsortedVersions.append(file);
} }
auto orderSortPredicate = [](const ModPlatform::IndexedVersion& a, const ModPlatform::IndexedVersion& b) -> bool { auto orderSortPredicate = [](const ModPlatform::IndexedVersion& a, const ModPlatform::IndexedVersion& b) -> bool {

View File

@ -27,16 +27,16 @@ ResourceAPI::SearchArgs ModModel::createSearchArguments()
std::optional<std::list<Version>> versions{}; std::optional<std::list<Version>> versions{};
auto loaders = profile->getSupportedModLoaders(); auto loaders = profile->getSupportedModLoaders();
{ // Version filter // Version filter
if (!m_filter->versions.empty()) if (!m_filter->versions.empty())
versions = m_filter->versions; versions = m_filter->versions;
if (m_filter->loaders) if (m_filter->loaders)
loaders = m_filter->loaders; loaders = m_filter->loaders;
} auto side = m_filter->side;
auto sort = getCurrentSortingMethodByIndex(); auto sort = getCurrentSortingMethodByIndex();
return { ModPlatform::ResourceType::MOD, m_next_search_offset, m_search_term, sort, loaders, versions }; return { ModPlatform::ResourceType::MOD, m_next_search_offset, m_search_term, sort, loaders, versions, side };
} }
ResourceAPI::VersionSearchArgs ModModel::createVersionsArguments(QModelIndex& entry) ResourceAPI::VersionSearchArgs ModModel::createVersionsArguments(QModelIndex& entry)
@ -85,4 +85,43 @@ bool ModModel::isPackInstalled(ModPlatform::IndexedPack::Ptr pack) const
}); });
} }
bool checkSide(QString filter, QString value)
{
return filter.isEmpty() || value.isEmpty() || filter == "both" || value == "both" || filter == value;
}
bool checkMcVersions(std::list<Version> filter, QStringList value)
{
bool valid = false;
for (auto mcVersion : filter) {
if (value.contains(mcVersion.toString())) {
valid = true;
break;
}
}
return filter.empty() || valid;
}
bool ModModel::checkFilters(ModPlatform::IndexedPack::Ptr pack)
{
if (!m_filter)
return true;
return !(m_filter->hideInstalled && isPackInstalled(pack)) && checkSide(m_filter->side, pack->side);
}
bool ModModel::checkVersionFilters(const ModPlatform::IndexedVersion& v)
{
if (!m_filter)
return true;
auto loaders = static_cast<MinecraftInstance&>(m_base_instance).getPackProfile()->getSupportedModLoaders();
if (m_filter->loaders)
loaders = m_filter->loaders;
return (!optedOut(v) && // is opted out(aka curseforge download link)
(!loaders.has_value() || !v.loaders || loaders.value() & v.loaders) && // loaders
checkSide(m_filter->side, v.side) && // side
(m_filter->releases.empty() || // releases
std::find(m_filter->releases.cbegin(), m_filter->releases.cend(), v.version_type) != m_filter->releases.cend()) &&
checkMcVersions(m_filter->versions, v.mcVersion)); // mcVersions
}
} // namespace ResourceDownload } // namespace ResourceDownload

View File

@ -45,6 +45,9 @@ class ModModel : public ResourceModel {
auto documentToArray(QJsonDocument& obj) const -> QJsonArray override = 0; auto documentToArray(QJsonDocument& obj) const -> QJsonArray override = 0;
virtual bool isPackInstalled(ModPlatform::IndexedPack::Ptr) const override; virtual bool isPackInstalled(ModPlatform::IndexedPack::Ptr) const override;
virtual bool checkFilters(ModPlatform::IndexedPack::Ptr) override;
virtual bool checkVersionFilters(const ModPlatform::IndexedVersion&) override;
protected: protected:
BaseInstance& m_base_instance; BaseInstance& m_base_instance;

View File

@ -73,6 +73,7 @@ void ModPage::setFilterWidget(unique_qobject_ptr<ModFilterWidget>& widget)
m_filter = m_filter_widget->getFilter(); m_filter = m_filter_widget->getFilter();
connect(m_filter_widget.get(), &ModFilterWidget::filterChanged, this, &ResourcePage::updateVersionList);
connect(m_filter_widget.get(), &ModFilterWidget::filterChanged, this, connect(m_filter_widget.get(), &ModFilterWidget::filterChanged, this,
[&] { m_ui->searchButton->setStyleSheet("text-decoration: underline"); }); [&] { m_ui->searchButton->setStyleSheet("text-decoration: underline"); });
connect(m_filter_widget.get(), &ModFilterWidget::filterUnchanged, this, connect(m_filter_widget.get(), &ModFilterWidget::filterUnchanged, this,
@ -110,43 +111,6 @@ QMap<QString, QString> ModPage::urlHandlers() const
/******** Make changes to the UI ********/ /******** Make changes to the UI ********/
void ModPage::updateVersionList()
{
m_ui->versionSelectionBox->clear();
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)
return;
for (int i = 0; i < current_pack->versions.size(); i++) {
auto version = current_pack->versions[i];
bool valid = false;
for (auto& mcVer : m_filter->versions) {
if (validateVersion(version, mcVer.toString(), loaders)) {
valid = true;
break;
}
}
// Only add the version if it's valid or using the 'Any' filter, but never if the version is opted out
if ((valid || m_filter->versions.empty()) && !optedOut(version)) {
auto release_type = version.version_type.isValid() ? QString(" [%1]").arg(version.version_type.toString()) : "";
m_ui->versionSelectionBox->addItem(QString("%1%2").arg(version.version, release_type), QVariant(i));
}
}
if (m_ui->versionSelectionBox->count() == 0) {
m_ui->versionSelectionBox->addItem(tr("No valid version found!"), QVariant(-1));
m_ui->resourceSelectionButton->setText(tr("Cannot select invalid version :("));
}
updateSelectionButton();
}
void ModPage::addResourceToPage(ModPlatform::IndexedPack::Ptr pack, void ModPage::addResourceToPage(ModPlatform::IndexedPack::Ptr pack,
ModPlatform::IndexedVersion& version, ModPlatform::IndexedVersion& version,
const std::shared_ptr<ResourceFolderModel> base_model) const std::shared_ptr<ResourceFolderModel> base_model)

View File

@ -31,7 +31,7 @@ class ModPage : public ResourcePage {
auto page = new T(dialog, instance); auto page = new T(dialog, instance);
auto model = static_cast<ModModel*>(page->getModel()); auto model = static_cast<ModModel*>(page->getModel());
auto filter_widget = ModFilterWidget::create(&static_cast<MinecraftInstance&>(instance), page); auto filter_widget = page->createFilterWidget();
page->setFilterWidget(filter_widget); page->setFilterWidget(filter_widget);
model->setFilter(page->getFilter()); model->setFilter(page->getFilter());
@ -52,17 +52,12 @@ class ModPage : public ResourcePage {
ModPlatform::IndexedVersion&, ModPlatform::IndexedVersion&,
const std::shared_ptr<ResourceFolderModel>) override; const std::shared_ptr<ResourceFolderModel>) override;
virtual auto validateVersion(ModPlatform::IndexedVersion& ver, virtual unique_qobject_ptr<ModFilterWidget> createFilterWidget() = 0;
QString mineVer,
std::optional<ModPlatform::ModLoaderTypes> loaders = {}) const -> bool = 0;
[[nodiscard]] bool supportsFiltering() const override { return true; }; [[nodiscard]] bool supportsFiltering() const override { return true; };
auto getFilter() const -> const std::shared_ptr<ModFilterWidget::Filter> { return m_filter; } auto getFilter() const -> const std::shared_ptr<ModFilterWidget::Filter> { return m_filter; }
void setFilterWidget(unique_qobject_ptr<ModFilterWidget>&); void setFilterWidget(unique_qobject_ptr<ModFilterWidget>&);
public slots:
void updateVersionList() override;
protected: protected:
ModPage(ModDownloadDialog* dialog, BaseInstance& instance); ModPage(ModDownloadDialog* dialog, BaseInstance& instance);

View File

@ -399,12 +399,17 @@ void ResourceModel::searchRequestSucceeded(QJsonDocument& doc)
m_search_state = SearchState::CanFetchMore; m_search_state = SearchState::CanFetchMore;
} }
QList<ModPlatform::IndexedPack::Ptr> filteredNewList;
for (auto p : newList)
if (checkFilters(p))
filteredNewList << p;
// When you have a Qt build with assertions turned on, proceeding here will abort the application // When you have a Qt build with assertions turned on, proceeding here will abort the application
if (newList.size() == 0) if (filteredNewList.size() == 0)
return; return;
beginInsertRows(QModelIndex(), m_packs.size(), m_packs.size() + newList.size() - 1); beginInsertRows(QModelIndex(), m_packs.size(), m_packs.size() + filteredNewList.size() - 1);
m_packs.append(newList); m_packs.append(filteredNewList);
endInsertRows(); endInsertRows();
} }
@ -547,4 +552,8 @@ void ResourceModel::removePack(const QString& rem)
ver.is_currently_selected = false; ver.is_currently_selected = false;
} }
bool ResourceModel::checkVersionFilters(const ModPlatform::IndexedVersion& v)
{
return (!optedOut(v));
}
} // namespace ResourceDownload } // namespace ResourceDownload

View File

@ -11,6 +11,7 @@
#include "QObjectPtr.h" #include "QObjectPtr.h"
#include "ResourceDownloadTask.h" #include "ResourceDownloadTask.h"
#include "modplatform/ModIndex.h"
#include "modplatform/ResourceAPI.h" #include "modplatform/ResourceAPI.h"
#include "tasks/ConcurrentTask.h" #include "tasks/ConcurrentTask.h"
@ -55,6 +56,16 @@ class ResourceModel : public QAbstractListModel {
[[nodiscard]] auto getSortingMethods() const { return m_api->getSortingMethods(); } [[nodiscard]] auto getSortingMethods() const { return m_api->getSortingMethods(); }
/** Whether the version is opted out or not. Currently only makes sense in CF. */
virtual bool optedOut(const ModPlatform::IndexedVersion& ver) const
{
Q_UNUSED(ver);
return false;
};
virtual bool checkFilters(ModPlatform::IndexedPack::Ptr) { return true; }
virtual bool checkVersionFilters(const ModPlatform::IndexedVersion&);
public slots: public slots:
void fetchMore(const QModelIndex& parent) override; void fetchMore(const QModelIndex& parent) override;
// NOTE: Can't use [[nodiscard]] here because of https://bugreports.qt.io/browse/QTBUG-58628 on Qt 5.12 // NOTE: Can't use [[nodiscard]] here because of https://bugreports.qt.io/browse/QTBUG-58628 on Qt 5.12

View File

@ -263,7 +263,7 @@ void ResourcePage::updateVersionList()
if (current_pack) if (current_pack)
for (int i = 0; i < current_pack->versions.size(); i++) { for (int i = 0; i < current_pack->versions.size(); i++) {
auto& version = current_pack->versions[i]; auto& version = current_pack->versions[i];
if (optedOut(version)) if (!m_model->checkVersionFilters(version))
continue; continue;
auto release_type = current_pack->versions[i].version_type.isValid() auto release_type = current_pack->versions[i].version_type.isValid()

View File

@ -96,13 +96,6 @@ class ResourcePage : public QWidget, public BasePage {
virtual QMap<QString, QString> urlHandlers() const = 0; virtual QMap<QString, QString> urlHandlers() const = 0;
virtual void openUrl(const QUrl&); virtual void openUrl(const QUrl&);
/** Whether the version is opted out or not. Currently only makes sense in CF. */
virtual bool optedOut(ModPlatform::IndexedVersion& ver) const
{
Q_UNUSED(ver);
return false;
};
public: public:
BaseInstance& m_base_instance; BaseInstance& m_base_instance;

View File

@ -12,6 +12,11 @@
namespace ResourceDownload { namespace ResourceDownload {
static bool isOptedOut(const ModPlatform::IndexedVersion& ver)
{
return ver.downloadUrl.isEmpty();
}
FlameModModel::FlameModModel(BaseInstance& base) : ModModel(base, new FlameAPI) {} FlameModModel::FlameModModel(BaseInstance& base) : ModModel(base, new FlameAPI) {}
void FlameModModel::loadIndexedPack(ModPlatform::IndexedPack& m, QJsonObject& obj) void FlameModModel::loadIndexedPack(ModPlatform::IndexedPack& m, QJsonObject& obj)
@ -35,6 +40,11 @@ auto FlameModModel::loadDependencyVersions(const ModPlatform::Dependency& m, QJs
return FlameMod::loadDependencyVersions(m, arr, &m_base_instance); return FlameMod::loadDependencyVersions(m, arr, &m_base_instance);
} }
bool FlameModModel::optedOut(const ModPlatform::IndexedVersion& ver) const
{
return isOptedOut(ver);
}
auto FlameModModel::documentToArray(QJsonDocument& obj) const -> QJsonArray auto FlameModModel::documentToArray(QJsonDocument& obj) const -> QJsonArray
{ {
return Json::ensureArray(obj.object(), "data"); return Json::ensureArray(obj.object(), "data");
@ -58,6 +68,11 @@ void FlameResourcePackModel::loadIndexedPackVersions(ModPlatform::IndexedPack& m
FlameMod::loadIndexedPackVersions(m, arr, APPLICATION->network(), &m_base_instance); FlameMod::loadIndexedPackVersions(m, arr, APPLICATION->network(), &m_base_instance);
} }
bool FlameResourcePackModel::optedOut(const ModPlatform::IndexedVersion& ver) const
{
return isOptedOut(ver);
}
auto FlameResourcePackModel::documentToArray(QJsonDocument& obj) const -> QJsonArray auto FlameResourcePackModel::documentToArray(QJsonDocument& obj) const -> QJsonArray
{ {
return Json::ensureArray(obj.object(), "data"); return Json::ensureArray(obj.object(), "data");
@ -117,6 +132,11 @@ ResourceAPI::VersionSearchArgs FlameTexturePackModel::createVersionsArguments(QM
return args; return args;
} }
bool FlameTexturePackModel::optedOut(const ModPlatform::IndexedVersion& ver) const
{
return isOptedOut(ver);
}
auto FlameTexturePackModel::documentToArray(QJsonDocument& obj) const -> QJsonArray auto FlameTexturePackModel::documentToArray(QJsonDocument& obj) const -> QJsonArray
{ {
return Json::ensureArray(obj.object(), "data"); return Json::ensureArray(obj.object(), "data");
@ -140,6 +160,11 @@ void FlameShaderPackModel::loadIndexedPackVersions(ModPlatform::IndexedPack& m,
FlameMod::loadIndexedPackVersions(m, arr, APPLICATION->network(), &m_base_instance); FlameMod::loadIndexedPackVersions(m, arr, APPLICATION->network(), &m_base_instance);
} }
bool FlameShaderPackModel::optedOut(const ModPlatform::IndexedVersion& ver) const
{
return isOptedOut(ver);
}
auto FlameShaderPackModel::documentToArray(QJsonDocument& obj) const -> QJsonArray auto FlameShaderPackModel::documentToArray(QJsonDocument& obj) const -> QJsonArray
{ {
return Json::ensureArray(obj.object(), "data"); return Json::ensureArray(obj.object(), "data");

View File

@ -17,6 +17,8 @@ class FlameModModel : public ModModel {
FlameModModel(BaseInstance&); FlameModModel(BaseInstance&);
~FlameModModel() override = default; ~FlameModModel() override = default;
bool optedOut(const ModPlatform::IndexedVersion& ver) const override;
private: private:
[[nodiscard]] QString debugName() const override { return Flame::debugName() + " (Model)"; } [[nodiscard]] QString debugName() const override { return Flame::debugName() + " (Model)"; }
[[nodiscard]] QString metaEntryBase() const override { return Flame::metaEntryBase(); } [[nodiscard]] QString metaEntryBase() const override { return Flame::metaEntryBase(); }
@ -36,6 +38,8 @@ class FlameResourcePackModel : public ResourcePackResourceModel {
FlameResourcePackModel(const BaseInstance&); FlameResourcePackModel(const BaseInstance&);
~FlameResourcePackModel() override = default; ~FlameResourcePackModel() override = default;
bool optedOut(const ModPlatform::IndexedVersion& ver) const override;
private: private:
[[nodiscard]] QString debugName() const override { return Flame::debugName() + " (Model)"; } [[nodiscard]] QString debugName() const override { return Flame::debugName() + " (Model)"; }
[[nodiscard]] QString metaEntryBase() const override { return Flame::metaEntryBase(); } [[nodiscard]] QString metaEntryBase() const override { return Flame::metaEntryBase(); }
@ -54,6 +58,8 @@ class FlameTexturePackModel : public TexturePackResourceModel {
FlameTexturePackModel(const BaseInstance&); FlameTexturePackModel(const BaseInstance&);
~FlameTexturePackModel() override = default; ~FlameTexturePackModel() override = default;
bool optedOut(const ModPlatform::IndexedVersion& ver) const override;
private: private:
[[nodiscard]] QString debugName() const override { return Flame::debugName() + " (Model)"; } [[nodiscard]] QString debugName() const override { return Flame::debugName() + " (Model)"; }
[[nodiscard]] QString metaEntryBase() const override { return Flame::metaEntryBase(); } [[nodiscard]] QString metaEntryBase() const override { return Flame::metaEntryBase(); }
@ -75,6 +81,8 @@ class FlameShaderPackModel : public ShaderPackResourceModel {
FlameShaderPackModel(const BaseInstance&); FlameShaderPackModel(const BaseInstance&);
~FlameShaderPackModel() override = default; ~FlameShaderPackModel() override = default;
bool optedOut(const ModPlatform::IndexedVersion& ver) const override;
private: private:
[[nodiscard]] QString debugName() const override { return Flame::debugName() + " (Model)"; } [[nodiscard]] QString debugName() const override { return Flame::debugName() + " (Model)"; }
[[nodiscard]] QString metaEntryBase() const override { return Flame::metaEntryBase(); } [[nodiscard]] QString metaEntryBase() const override { return Flame::metaEntryBase(); }

View File

@ -44,11 +44,6 @@
namespace ResourceDownload { namespace ResourceDownload {
static bool isOptedOut(ModPlatform::IndexedVersion const& ver)
{
return ver.downloadUrl.isEmpty();
}
FlameModPage::FlameModPage(ModDownloadDialog* dialog, BaseInstance& instance) : ModPage(dialog, instance) FlameModPage::FlameModPage(ModDownloadDialog* dialog, BaseInstance& instance) : ModPage(dialog, instance)
{ {
m_model = new FlameModModel(instance); m_model = new FlameModModel(instance);
@ -66,19 +61,6 @@ FlameModPage::FlameModPage(ModDownloadDialog* dialog, BaseInstance& instance) :
m_ui->packDescription->setMetaEntry(metaEntryBase()); m_ui->packDescription->setMetaEntry(metaEntryBase());
} }
auto FlameModPage::validateVersion(ModPlatform::IndexedVersion& ver,
QString mineVer,
std::optional<ModPlatform::ModLoaderTypes> loaders) const -> bool
{
return ver.mcVersion.contains(mineVer) && !ver.downloadUrl.isEmpty() &&
(!loaders.has_value() || !ver.loaders || loaders.value() & ver.loaders);
}
bool FlameModPage::optedOut(ModPlatform::IndexedVersion& ver) const
{
return isOptedOut(ver);
}
void FlameModPage::openUrl(const QUrl& url) void FlameModPage::openUrl(const QUrl& url)
{ {
if (url.scheme().isEmpty()) { if (url.scheme().isEmpty()) {
@ -113,11 +95,6 @@ FlameResourcePackPage::FlameResourcePackPage(ResourcePackDownloadDialog* dialog,
m_ui->packDescription->setMetaEntry(metaEntryBase()); m_ui->packDescription->setMetaEntry(metaEntryBase());
} }
bool FlameResourcePackPage::optedOut(ModPlatform::IndexedVersion& ver) const
{
return isOptedOut(ver);
}
void FlameResourcePackPage::openUrl(const QUrl& url) void FlameResourcePackPage::openUrl(const QUrl& url)
{ {
if (url.scheme().isEmpty()) { if (url.scheme().isEmpty()) {
@ -152,11 +129,6 @@ FlameTexturePackPage::FlameTexturePackPage(TexturePackDownloadDialog* dialog, Ba
m_ui->packDescription->setMetaEntry(metaEntryBase()); m_ui->packDescription->setMetaEntry(metaEntryBase());
} }
bool FlameTexturePackPage::optedOut(ModPlatform::IndexedVersion& ver) const
{
return isOptedOut(ver);
}
void FlameTexturePackPage::openUrl(const QUrl& url) void FlameTexturePackPage::openUrl(const QUrl& url)
{ {
if (url.scheme().isEmpty()) { if (url.scheme().isEmpty()) {
@ -191,11 +163,6 @@ FlameShaderPackPage::FlameShaderPackPage(ShaderPackDownloadDialog* dialog, BaseI
m_ui->packDescription->setMetaEntry(metaEntryBase()); m_ui->packDescription->setMetaEntry(metaEntryBase());
} }
bool FlameShaderPackPage::optedOut(ModPlatform::IndexedVersion& ver) const
{
return isOptedOut(ver);
}
void FlameShaderPackPage::openUrl(const QUrl& url) void FlameShaderPackPage::openUrl(const QUrl& url)
{ {
if (url.scheme().isEmpty()) { if (url.scheme().isEmpty()) {
@ -232,4 +199,9 @@ auto FlameShaderPackPage::shouldDisplay() const -> bool
return true; return true;
} }
unique_qobject_ptr<ModFilterWidget> FlameModPage::createFilterWidget()
{
return ModFilterWidget::create(&static_cast<MinecraftInstance&>(m_base_instance), false, this);
}
} // namespace ResourceDownload } // namespace ResourceDownload

View File

@ -94,12 +94,8 @@ class FlameModPage : public ModPage {
[[nodiscard]] inline auto helpPage() const -> QString override { return "Mod-platform"; } [[nodiscard]] inline auto helpPage() const -> QString override { return "Mod-platform"; }
bool validateVersion(ModPlatform::IndexedVersion& ver,
QString mineVer,
std::optional<ModPlatform::ModLoaderTypes> loaders = {}) const override;
bool optedOut(ModPlatform::IndexedVersion& ver) const override;
void openUrl(const QUrl& url) override; void openUrl(const QUrl& url) override;
unique_qobject_ptr<ModFilterWidget> createFilterWidget() override;
}; };
class FlameResourcePackPage : public ResourcePackResourcePage { class FlameResourcePackPage : public ResourcePackResourcePage {
@ -124,8 +120,6 @@ class FlameResourcePackPage : public ResourcePackResourcePage {
[[nodiscard]] inline auto helpPage() const -> QString override { return ""; } [[nodiscard]] inline auto helpPage() const -> QString override { return ""; }
bool optedOut(ModPlatform::IndexedVersion& ver) const override;
void openUrl(const QUrl& url) override; void openUrl(const QUrl& url) override;
}; };
@ -151,8 +145,6 @@ class FlameTexturePackPage : public TexturePackResourcePage {
[[nodiscard]] inline auto helpPage() const -> QString override { return ""; } [[nodiscard]] inline auto helpPage() const -> QString override { return ""; }
bool optedOut(ModPlatform::IndexedVersion& ver) const override;
void openUrl(const QUrl& url) override; void openUrl(const QUrl& url) override;
}; };
@ -178,8 +170,6 @@ class FlameShaderPackPage : public ShaderPackResourcePage {
[[nodiscard]] inline auto helpPage() const -> QString override { return ""; } [[nodiscard]] inline auto helpPage() const -> QString override { return ""; }
bool optedOut(ModPlatform::IndexedVersion& ver) const override;
void openUrl(const QUrl& url) override; void openUrl(const QUrl& url) override;
}; };

View File

@ -63,13 +63,6 @@ ModrinthModPage::ModrinthModPage(ModDownloadDialog* dialog, BaseInstance& instan
m_ui->packDescription->setMetaEntry(metaEntryBase()); m_ui->packDescription->setMetaEntry(metaEntryBase());
} }
auto ModrinthModPage::validateVersion(ModPlatform::IndexedVersion& ver,
QString mineVer,
std::optional<ModPlatform::ModLoaderTypes> loaders) const -> bool
{
return ver.mcVersion.contains(mineVer) && (!loaders.has_value() || !ver.loaders || loaders.value() & ver.loaders);
}
ModrinthResourcePackPage::ModrinthResourcePackPage(ResourcePackDownloadDialog* dialog, BaseInstance& instance) ModrinthResourcePackPage::ModrinthResourcePackPage(ResourcePackDownloadDialog* dialog, BaseInstance& instance)
: ResourcePackResourcePage(dialog, instance) : ResourcePackResourcePage(dialog, instance)
{ {
@ -144,4 +137,8 @@ auto ModrinthShaderPackPage::shouldDisplay() const -> bool
return true; return true;
} }
unique_qobject_ptr<ModFilterWidget> ModrinthModPage::createFilterWidget()
{
return ModFilterWidget::create(&static_cast<MinecraftInstance&>(m_base_instance), true, this);
}
} // namespace ResourceDownload } // namespace ResourceDownload

View File

@ -93,8 +93,7 @@ class ModrinthModPage : public ModPage {
[[nodiscard]] inline auto helpPage() const -> QString override { return "Mod-platform"; } [[nodiscard]] inline auto helpPage() const -> QString override { return "Mod-platform"; }
auto validateVersion(ModPlatform::IndexedVersion& ver, QString mineVer, std::optional<ModPlatform::ModLoaderTypes> loaders = {}) const unique_qobject_ptr<ModFilterWidget> createFilterWidget() override;
-> bool override;
}; };
class ModrinthResourcePackPage : public ResourcePackResourcePage { class ModrinthResourcePackPage : public ResourcePackResourcePage {

View File

@ -84,7 +84,7 @@ CheckComboBox::CheckComboBox(QWidget* parent) : QComboBox(parent), m_separator("
this->installEventFilter(this); this->installEventFilter(this);
} }
void CheckComboBox::setModel(QAbstractItemModel* new_model) void CheckComboBox::setSourceModel(QAbstractItemModel* new_model)
{ {
auto proxy = new CheckComboModel(this); auto proxy = new CheckComboModel(this);
proxy->setSourceModel(new_model); proxy->setSourceModel(new_model);

View File

@ -28,7 +28,7 @@ class CheckComboBox : public QComboBox {
explicit CheckComboBox(QWidget* parent = nullptr); explicit CheckComboBox(QWidget* parent = nullptr);
virtual ~CheckComboBox() = default; virtual ~CheckComboBox() = default;
virtual void hidePopup() override; void hidePopup() override;
QString defaultText() const; QString defaultText() const;
void setDefaultText(const QString& text); void setDefaultText(const QString& text);
@ -41,7 +41,7 @@ class CheckComboBox : public QComboBox {
QStringList checkedItems() const; QStringList checkedItems() const;
virtual void setModel(QAbstractItemModel* model) override; void setSourceModel(QAbstractItemModel* model);
public slots: public slots:
void setCheckedItems(const QStringList& items); void setCheckedItems(const QStringList& items);

View File

@ -9,9 +9,9 @@
#include "Application.h" #include "Application.h"
#include "minecraft/PackProfile.h" #include "minecraft/PackProfile.h"
unique_qobject_ptr<ModFilterWidget> ModFilterWidget::create(MinecraftInstance* instance, QWidget* parent) unique_qobject_ptr<ModFilterWidget> ModFilterWidget::create(MinecraftInstance* instance, bool extendedSupport, QWidget* parent)
{ {
return unique_qobject_ptr<ModFilterWidget>(new ModFilterWidget(instance, parent)); return unique_qobject_ptr<ModFilterWidget>(new ModFilterWidget(instance, extendedSupport, parent));
} }
class VersionBasicModel : public QIdentityProxyModel { class VersionBasicModel : public QIdentityProxyModel {
@ -28,23 +28,33 @@ class VersionBasicModel : public QIdentityProxyModel {
} }
}; };
ModFilterWidget::ModFilterWidget(MinecraftInstance* instance, QWidget* parent) ModFilterWidget::ModFilterWidget(MinecraftInstance* instance, bool extendedSupport, QWidget* parent)
: QTabWidget(parent), ui(new Ui::ModFilterWidget), m_instance(instance), m_filter(new Filter()) : QTabWidget(parent), ui(new Ui::ModFilterWidget), m_instance(instance), m_filter(new Filter())
{ {
ui->setupUi(this); ui->setupUi(this);
m_versions_proxy = new VersionProxyModel(this); m_versions_proxy = new VersionProxyModel(this);
m_versions_proxy->setFilter(BaseVersionList::TypeRole, new RegexpFilter("(release)", false));
auto proxy = new VersionBasicModel(this); auto proxy = new VersionBasicModel(this);
proxy->setSourceModel(m_versions_proxy); proxy->setSourceModel(m_versions_proxy);
ui->versionsCb->setModel(proxy);
ui->versionsCb->setSeparator("| ");
m_versions_proxy->setFilter(BaseVersionList::TypeRole, new RegexpFilter("(release)", false)); if (!extendedSupport) {
ui->versionsSimpleCb->setModel(proxy);
ui->versionsCb->hide();
ui->snapshotsCb->hide();
ui->envBox->hide();
} else {
ui->versionsCb->setSourceModel(proxy);
ui->versionsCb->setSeparator("| ");
ui->versionsSimpleCb->hide();
}
ui->versionsCb->setStyleSheet("combobox-popup: 0;"); ui->versionsCb->setStyleSheet("combobox-popup: 0;");
ui->versionsSimpleCb->setStyleSheet("combobox-popup: 0;");
connect(ui->snapshotsCb, &QCheckBox::stateChanged, this, &ModFilterWidget::onIncludeSnapshotsChanged); connect(ui->snapshotsCb, &QCheckBox::stateChanged, this, &ModFilterWidget::onIncludeSnapshotsChanged);
connect(ui->versionsCb, &QComboBox::currentIndexChanged, this, &ModFilterWidget::onVersionFilterChanged); connect(ui->versionsCb, &QComboBox::currentIndexChanged, this, &ModFilterWidget::onVersionFilterChanged);
connect(ui->versionsSimpleCb, &QComboBox::currentTextChanged, this, &ModFilterWidget::onVersionFilterTextChanged);
connect(ui->neoForgeCb, &QCheckBox::stateChanged, this, &ModFilterWidget::onLoadersFilterChanged); connect(ui->neoForgeCb, &QCheckBox::stateChanged, this, &ModFilterWidget::onLoadersFilterChanged);
connect(ui->forgeCb, &QCheckBox::stateChanged, this, &ModFilterWidget::onLoadersFilterChanged); connect(ui->forgeCb, &QCheckBox::stateChanged, this, &ModFilterWidget::onLoadersFilterChanged);
@ -61,6 +71,11 @@ ModFilterWidget::ModFilterWidget(MinecraftInstance* instance, QWidget* parent)
connect(ui->hide_installed, &QCheckBox::stateChanged, this, &ModFilterWidget::onHideInstalledFilterChanged); connect(ui->hide_installed, &QCheckBox::stateChanged, this, &ModFilterWidget::onHideInstalledFilterChanged);
connect(ui->releaseCb, &QCheckBox::stateChanged, this, &ModFilterWidget::onReleaseFilterChanged);
connect(ui->betaCb, &QCheckBox::stateChanged, this, &ModFilterWidget::onReleaseFilterChanged);
connect(ui->alphaCb, &QCheckBox::stateChanged, this, &ModFilterWidget::onReleaseFilterChanged);
connect(ui->unknownCb, &QCheckBox::stateChanged, this, &ModFilterWidget::onReleaseFilterChanged);
setHidden(true); setHidden(true);
loadVersionList(); loadVersionList();
prepareBasicFilter(); prepareBasicFilter();
@ -196,4 +211,31 @@ void ModFilterWidget::onHideInstalledFilterChanged()
emit filterUnchanged(); emit filterUnchanged();
} }
void ModFilterWidget::onReleaseFilterChanged()
{
std::list<ModPlatform::IndexedVersionType> releases;
if (ui->releaseCb->isChecked())
releases.push_back(ModPlatform::IndexedVersionType(ModPlatform::IndexedVersionType::VersionType::Release));
if (ui->betaCb->isChecked())
releases.push_back(ModPlatform::IndexedVersionType(ModPlatform::IndexedVersionType::VersionType::Beta));
if (ui->alphaCb->isChecked())
releases.push_back(ModPlatform::IndexedVersionType(ModPlatform::IndexedVersionType::VersionType::Alpha));
if (ui->unknownCb->isChecked())
releases.push_back(ModPlatform::IndexedVersionType(ModPlatform::IndexedVersionType::VersionType::Unknown));
m_filter_changed = releases != m_filter->releases;
m_filter->releases = releases;
if (m_filter_changed)
emit filterChanged();
else
emit filterUnchanged();
}
void ModFilterWidget::onVersionFilterTextChanged(QString version)
{
m_filter->versions.clear();
m_filter->versions.push_front(version);
m_filter_changed = true;
emit filterChanged();
}
#include "ModFilterWidget.moc" #include "ModFilterWidget.moc"

View File

@ -22,41 +22,44 @@ class ModFilterWidget : public QTabWidget {
public: public:
struct Filter { struct Filter {
std::list<Version> versions; std::list<Version> versions;
std::list<ModPlatform::IndexedVersionType> releases;
ModPlatform::ModLoaderTypes loaders; ModPlatform::ModLoaderTypes loaders;
QString side; QString side;
bool hideInstalled; bool hideInstalled;
bool operator==(const Filter& other) const bool operator==(const Filter& other) const
{ {
return hideInstalled == other.hideInstalled && side == other.side && loaders == other.loaders && versions == other.versions; return hideInstalled == other.hideInstalled && side == other.side && loaders == other.loaders && versions == other.versions &&
releases == other.releases;
} }
bool operator!=(const Filter& other) const { return !(*this == other); } bool operator!=(const Filter& other) const { return !(*this == other); }
}; };
static unique_qobject_ptr<ModFilterWidget> create(MinecraftInstance* instance, QWidget* parent = nullptr); static unique_qobject_ptr<ModFilterWidget> create(MinecraftInstance* instance, bool extendedSupport, QWidget* parent = nullptr);
virtual ~ModFilterWidget(); virtual ~ModFilterWidget();
auto getFilter() -> std::shared_ptr<Filter>; auto getFilter() -> std::shared_ptr<Filter>;
auto changed() const -> bool { return m_filter_changed; } auto changed() const -> bool { return m_filter_changed; }
signals:
void filterChanged();
void filterUnchanged();
private: private:
ModFilterWidget(MinecraftInstance* instance, QWidget* parent = nullptr); ModFilterWidget(MinecraftInstance* instance, bool extendedSupport, QWidget* parent = nullptr);
void loadVersionList(); void loadVersionList();
void prepareBasicFilter(); void prepareBasicFilter();
private slots: private slots:
void onVersionFilterChanged(); void onVersionFilterChanged();
void onVersionFilterTextChanged(QString version);
void onReleaseFilterChanged();
void onLoadersFilterChanged(); void onLoadersFilterChanged();
void onSideFilterChanged(); void onSideFilterChanged();
void onHideInstalledFilterChanged(); void onHideInstalledFilterChanged();
void onIncludeSnapshotsChanged(); void onIncludeSnapshotsChanged();
public:
signals:
void filterChanged();
void filterUnchanged();
private: private:
Ui::ModFilterWidget* ui; Ui::ModFilterWidget* ui;

View File

@ -6,7 +6,7 @@
<rect> <rect>
<x>0</x> <x>0</x>
<y>0</y> <y>0</y>
<width>400</width> <width>460</width>
<height>127</height> <height>127</height>
</rect> </rect>
</property> </property>
@ -17,13 +17,20 @@
</sizepolicy> </sizepolicy>
</property> </property>
<property name="currentIndex"> <property name="currentIndex">
<number>2</number> <number>0</number>
</property> </property>
<widget class="QWidget" name="VersionPage"> <widget class="QWidget" name="VersionPage">
<attribute name="title"> <attribute name="title">
<string>Minecraft versions</string> <string>Minecraft versions</string>
</attribute> </attribute>
<layout class="QGridLayout" name="gridLayout"> <layout class="QGridLayout" name="gridLayout">
<item row="1" column="1">
<widget class="QCheckBox" name="snapshotsCb">
<property name="text">
<string>Include Snapshots</string>
</property>
</widget>
</item>
<item row="1" column="0"> <item row="1" column="0">
<widget class="CheckComboBox" name="versionsCb"> <widget class="CheckComboBox" name="versionsCb">
<property name="sizePolicy"> <property name="sizePolicy">
@ -40,12 +47,8 @@
</property> </property>
</widget> </widget>
</item> </item>
<item row="1" column="1"> <item row="2" column="0">
<widget class="QCheckBox" name="snapshotsCb"> <widget class="QComboBox" name="versionsSimpleCb"/>
<property name="text">
<string>Include Snapshots</string>
</property>
</widget>
</item> </item>
</layout> </layout>
</widget> </widget>