From ebf2602f31e4c99963d65a375df3551209793383 Mon Sep 17 00:00:00 2001 From: BruebachL <44814898+BruebachL@users.noreply.github.com> Date: Thu, 10 Apr 2025 04:37:52 +0200 Subject: [PATCH] Add main and sub type as filter options, add helper functions to remove or get specific and all filters. (#5820) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Lukas Brübach --- cockatrice/src/game/filters/filter_card.cpp | 43 +++++++++++++ cockatrice/src/game/filters/filter_card.h | 6 +- cockatrice/src/game/filters/filter_tree.cpp | 27 ++++++++ cockatrice/src/game/filters/filter_tree.h | 4 ++ .../src/game/filters/filter_tree_model.cpp | 61 +++++++++++++++++++ .../src/game/filters/filter_tree_model.h | 6 ++ 6 files changed, 146 insertions(+), 1 deletion(-) diff --git a/cockatrice/src/game/filters/filter_card.cpp b/cockatrice/src/game/filters/filter_card.cpp index d91129147..d49a1b9cb 100644 --- a/cockatrice/src/game/filters/filter_card.cpp +++ b/cockatrice/src/game/filters/filter_card.cpp @@ -1,5 +1,44 @@ #include "filter_card.h" +#include + +QJsonObject CardFilter::toJson() const +{ + QJsonObject obj; + obj["term"] = trm; + obj["type"] = typeName(t); + obj["attr"] = attrName(a); + return obj; +} + +CardFilter *CardFilter::fromJson(const QJsonObject &obj) +{ + QString term = obj["term"].toString(); + QString typeStr = obj["type"].toString(); + QString attrStr = obj["attr"].toString(); + + Type type = TypeEnd; + Attr attr = AttrEnd; + + // Convert type string back to enum + for (int i = 0; i < TypeEnd; i++) { + if (typeName(static_cast(i)) == typeStr) { + type = static_cast(i); + break; + } + } + + // Convert attr string back to enum + for (int i = 0; i < AttrEnd; i++) { + if (attrName(static_cast(i)) == attrStr) { + attr = static_cast(i); + break; + } + } + + return new CardFilter(term, type, attr); +} + const QString CardFilter::typeName(Type t) { switch (t) { @@ -43,6 +82,10 @@ const QString CardFilter::attrName(Attr a) return tr("Loyalty"); case AttrFormat: return tr("Format"); + case AttrMainType: + return tr("Main Type"); + case AttrSubType: + return tr("Sub Type"); default: return QString(""); } diff --git a/cockatrice/src/game/filters/filter_card.h b/cockatrice/src/game/filters/filter_card.h index 7412d0f8d..210d5c062 100644 --- a/cockatrice/src/game/filters/filter_card.h +++ b/cockatrice/src/game/filters/filter_card.h @@ -34,8 +34,10 @@ public: AttrText, AttrTough, AttrType, + AttrMainType, + AttrSubType, AttrFormat, - AttrEnd + AttrEnd, }; private: @@ -59,6 +61,8 @@ public: return a; } + QJsonObject toJson() const; + static CardFilter *fromJson(const QJsonObject &json); static const QString typeName(Type t); static const QString attrName(Attr a); }; diff --git a/cockatrice/src/game/filters/filter_tree.cpp b/cockatrice/src/game/filters/filter_tree.cpp index d36a1d253..03c740742 100644 --- a/cockatrice/src/game/filters/filter_tree.cpp +++ b/cockatrice/src/game/filters/filter_tree.cpp @@ -158,6 +158,18 @@ bool FilterItem::acceptType(const CardInfoPtr info) const return info->getCardType().contains(term, Qt::CaseInsensitive); } +bool FilterItem::acceptMainType(const CardInfoPtr info) const +{ + const QStringList typeParts = info->getCardType().split(" — "); + return !typeParts.isEmpty() && typeParts[0].contains(term, Qt::CaseInsensitive); +} + +bool FilterItem::acceptSubType(const CardInfoPtr info) const +{ + const QStringList typeParts = info->getCardType().split(" — "); + return typeParts.size() > 1 && typeParts[1].contains(term, Qt::CaseInsensitive); +} + bool FilterItem::acceptColor(const CardInfoPtr info) const { QString converted_term = term.trimmed(); @@ -411,6 +423,10 @@ bool FilterItem::acceptCardAttr(const CardInfoPtr info, CardFilter::Attr attr) c return acceptLoyalty(info); case CardFilter::AttrFormat: return acceptFormat(info); + case CardFilter::AttrMainType: + return acceptMainType(info); + case CardFilter::AttrSubType: + return acceptSubType(info); default: return true; /* ignore this attribute */ } @@ -504,6 +520,17 @@ bool FilterTree::acceptsCard(const CardInfoPtr info) const return true; } +void FilterTree::removeFiltersByAttr(CardFilter::Attr filterType) +{ + for (int i = childNodes.size() - 1; i >= 0; --i) { + auto *child = dynamic_cast(childNodes.at(i)); + + if (child && child->attr == filterType) { + deleteAt(i); + } + } +} + void FilterTree::clear() { while (childCount() > 0) { diff --git a/cockatrice/src/game/filters/filter_tree.h b/cockatrice/src/game/filters/filter_tree.h index 08e76584f..895e1c1f7 100644 --- a/cockatrice/src/game/filters/filter_tree.h +++ b/cockatrice/src/game/filters/filter_tree.h @@ -97,6 +97,7 @@ protected: public: virtual ~FilterTreeBranch(); + void removeFiltersByAttr(CardFilter::Attr filterType); FilterTreeNode *nodeAt(int i) const override; void deleteAt(int i) override; int childCount() const override @@ -198,6 +199,8 @@ public: bool acceptName(CardInfoPtr info) const; bool acceptType(CardInfoPtr info) const; + bool acceptMainType(CardInfoPtr info) const; + bool acceptSubType(CardInfoPtr info) const; bool acceptColor(CardInfoPtr info) const; bool acceptText(CardInfoPtr info) const; bool acceptSet(CardInfoPtr info) const; @@ -266,6 +269,7 @@ public: } bool acceptsCard(CardInfoPtr info) const; + void removeFiltersByAttr(CardFilter::Attr filterType); void clear(); }; diff --git a/cockatrice/src/game/filters/filter_tree_model.cpp b/cockatrice/src/game/filters/filter_tree_model.cpp index 7541fc243..e2c5edd13 100644 --- a/cockatrice/src/game/filters/filter_tree_model.cpp +++ b/cockatrice/src/game/filters/filter_tree_model.cpp @@ -78,6 +78,62 @@ void FilterTreeModel::addFilter(const CardFilter *f) emit layoutChanged(); } +void FilterTreeModel::clearFiltersOfType(CardFilter::Attr filterType) +{ + emit layoutAboutToBeChanged(); + + // Recursively remove all nodes with the given filter type + fTree->removeFiltersByAttr(filterType); + + emit layoutChanged(); +} + +QList FilterTreeModel::getFiltersOfType(CardFilter::Attr filterType) const +{ + QList filters; + if (!fTree) { + return filters; + } + + std::function traverse; + traverse = [&](const FilterTreeNode *node) { + if (const auto *filterItem = dynamic_cast(node)) { + if (filterItem->attr() == filterType) { + QString text = filterItem->text(); + filters.append(new CardFilter(text, filterItem->type(), filterItem->attr())); + } + } + for (int i = 0; i < node->childCount(); ++i) { + traverse(node->nodeAt(i)); + } + }; + + traverse(fTree); + return filters; +} + +QList FilterTreeModel::allFilters() const +{ + QList filters; + if (!fTree) { + return filters; + } + + std::function traverse; + traverse = [&](const FilterTreeNode *node) { + if (const auto *filterItem = dynamic_cast(node)) { + QString text = filterItem->text(); + filters.append(new CardFilter(text, filterItem->type(), filterItem->attr())); + } + for (int i = 0; i < node->childCount(); ++i) { + traverse(node->nodeAt(i)); + } + }; + + traverse(fTree); + return filters; +} + int FilterTreeModel::rowCount(const QModelIndex &parent) const { const FilterTreeNode *node; @@ -257,3 +313,8 @@ bool FilterTreeModel::removeRows(int row, int count, const QModelIndex &parent) return true; } + +void FilterTreeModel::clear() +{ + fTree->clear(); +} diff --git a/cockatrice/src/game/filters/filter_tree_model.h b/cockatrice/src/game/filters/filter_tree_model.h index 3ea2c4013..4e98aa02a 100644 --- a/cockatrice/src/game/filters/filter_tree_model.h +++ b/cockatrice/src/game/filters/filter_tree_model.h @@ -1,6 +1,8 @@ #ifndef FILTERTREEMODEL_H #define FILTERTREEMODEL_H +#include "filter_card.h" + #include class FilterTree; @@ -15,6 +17,9 @@ private: public slots: void addFilter(const CardFilter *f); + void clearFiltersOfType(CardFilter::Attr filterType); + QList getFiltersOfType(CardFilter::Attr filterType) const; + QList allFilters() const; private slots: void proxyBeginInsertRow(const FilterTreeNode *, int); @@ -41,6 +46,7 @@ public: QModelIndex parent(const QModelIndex &ind) const override; QModelIndex index(int row, int column, const QModelIndex &parent) const override; bool removeRows(int row, int count, const QModelIndex &parent) override; + void clear(); }; #endif