diff --git a/cockatrice/src/filters/deck_filter_string.cpp b/cockatrice/src/filters/deck_filter_string.cpp index dd873cfa5..4abb8210c 100644 --- a/cockatrice/src/filters/deck_filter_string.cpp +++ b/cockatrice/src/filters/deck_filter_string.cpp @@ -52,18 +52,14 @@ static void setupParserRules() search["Start"] = passthru; search["QueryPartList"] = [](const peg::SemanticValues &sv) -> DeckFilter { - return [=](const DeckPreviewWidget *deck, const ExtraDeckSearchInfo &info) { - auto matchesFilter = [&deck, &info](const std::any &query) { - return std::any_cast(query)(deck, info); - }; + return [=](const DeckSearchData &data) { + auto matchesFilter = [&data](const std::any &query) { return std::any_cast(query)(data); }; return std::all_of(sv.begin(), sv.end(), matchesFilter); }; }; search["ComplexQueryPart"] = [](const peg::SemanticValues &sv) -> DeckFilter { - return [=](const DeckPreviewWidget *deck, const ExtraDeckSearchInfo &info) { - auto matchesFilter = [&deck, &info](const std::any &query) { - return std::any_cast(query)(deck, info); - }; + return [=](const DeckSearchData &data) { + auto matchesFilter = [&data](const std::any &query) { return std::any_cast(query)(data); }; return std::any_of(sv.begin(), sv.end(), matchesFilter); }; }; @@ -71,9 +67,7 @@ static void setupParserRules() search["QueryPart"] = passthru; search["NotQuery"] = [](const peg::SemanticValues &sv) -> DeckFilter { const auto dependent = std::any_cast(sv[0]); - return [=](const DeckPreviewWidget *deck, const ExtraDeckSearchInfo &info) -> bool { - return !dependent(deck, info); - }; + return [=](const DeckSearchData &data) -> bool { return !dependent(data); }; }; search["String"] = [](const peg::SemanticValues &sv) -> QString { @@ -125,9 +119,9 @@ static void setupParserRules() auto cardFilter = FilterString(std::any_cast(sv[0])); auto numberMatcher = sv.size() > 1 ? std::any_cast(sv[1]) : [](int count) { return count > 0; }; - return [=](const DeckPreviewWidget *deck, const ExtraDeckSearchInfo &) -> bool { + return [=](const DeckSearchData &data) -> bool { int count = 0; - auto cardNodes = deck->deckLoader->getDeck().deckList.getCardNodes(); + auto cardNodes = data.deck->deckList.getCardNodes(); for (auto node : cardNodes) { auto cardInfoPtr = CardDatabaseManager::query()->getCardInfo(node->getName()); if (!cardInfoPtr.isNull() && cardFilter.check(cardInfoPtr)) { @@ -146,53 +140,49 @@ static void setupParserRules() search["DeckNameQuery"] = [](const peg::SemanticValues &sv) -> DeckFilter { auto name = std::any_cast(sv[0]); - return [=](const DeckPreviewWidget *deck, const ExtraDeckSearchInfo &) { - return deck->deckLoader->getDeck().deckList.getName().contains(name, Qt::CaseInsensitive); + return [=](const DeckSearchData &data) { + return data.deck->deckList.getName().contains(name, Qt::CaseInsensitive); }; }; search["FileNameQuery"] = [](const peg::SemanticValues &sv) -> DeckFilter { auto name = std::any_cast(sv[0]); - return [=](const DeckPreviewWidget *deck, const ExtraDeckSearchInfo &) { - auto filename = QFileInfo(deck->filePath).fileName(); + return [=](const DeckSearchData &data) { + auto filename = QFileInfo(data.filePath).fileName(); return filename.contains(name, Qt::CaseInsensitive); }; }; search["PathQuery"] = [](const peg::SemanticValues &sv) -> DeckFilter { auto name = std::any_cast(sv[0]); - return [=](const DeckPreviewWidget *, const ExtraDeckSearchInfo &info) { - return info.relativeFilePath.contains(name, Qt::CaseInsensitive); - }; + return [=](const DeckSearchData &data) { return data.relativeFilePath.contains(name, Qt::CaseInsensitive); }; }; search["FormatQuery"] = [](const peg::SemanticValues &sv) -> DeckFilter { auto format = std::any_cast(sv[0]); - return [=](const DeckPreviewWidget *deck, const ExtraDeckSearchInfo &) { - auto gameFormat = deck->deckLoader->getDeck().deckList.getGameFormat(); + return [=](const DeckSearchData &data) { + auto gameFormat = data.deck->deckList.getGameFormat(); return QString::compare(format, gameFormat, Qt::CaseInsensitive) == 0; }; }; search["CommentQuery"] = [](const peg::SemanticValues &sv) -> DeckFilter { auto value = std::any_cast(sv[0]); - return [=](const DeckPreviewWidget *deck, const ExtraDeckSearchInfo &) { - auto comments = deck->deckLoader->getDeck().deckList.getComments(); + return [=](const DeckSearchData &data) { + auto comments = data.deck->deckList.getComments(); return comments.contains(value, Qt::CaseInsensitive); }; }; search["GenericQuery"] = [](const peg::SemanticValues &sv) -> DeckFilter { auto name = std::any_cast(sv[0]); - return [=](const DeckPreviewWidget *deck, const ExtraDeckSearchInfo &) { - return deck->getDisplayName().contains(name, Qt::CaseInsensitive); - }; + return [=](const DeckSearchData &data) { return data.displayName.contains(name, Qt::CaseInsensitive); }; }; } DeckFilterString::DeckFilterString() { - filter = [](const DeckPreviewWidget *, const ExtraDeckSearchInfo &) { return false; }; + filter = [](const DeckSearchData &) { return false; }; _error = "Not initialized"; } @@ -205,7 +195,7 @@ DeckFilterString::DeckFilterString(const QString &expr) _error = QString(); if (ba.isEmpty()) { - filter = [](const DeckPreviewWidget *, const ExtraDeckSearchInfo &) { return true; }; + filter = [](const DeckSearchData &) { return true; }; return; } @@ -215,6 +205,6 @@ DeckFilterString::DeckFilterString(const QString &expr) if (!search.parse(ba.data(), filter)) { qCInfo(DeckFilterStringLog).nospace() << "DeckFilterString error for " << expr << "; " << qPrintable(_error); - filter = [](const DeckPreviewWidget *, const ExtraDeckSearchInfo &) { return false; }; + filter = [](const DeckSearchData &) { return false; }; } -} \ No newline at end of file +} diff --git a/cockatrice/src/filters/deck_filter_string.h b/cockatrice/src/filters/deck_filter_string.h index 916b629ee..90a6a17eb 100644 --- a/cockatrice/src/filters/deck_filter_string.h +++ b/cockatrice/src/filters/deck_filter_string.h @@ -7,7 +7,7 @@ #ifndef DECK_FILTER_STRING_H #define DECK_FILTER_STRING_H -#include "../interface/widgets/visual_deck_storage/deck_preview/deck_preview_widget.h" +#include "../interface/deck_loader/loaded_deck.h" #include #include @@ -16,26 +16,29 @@ inline Q_LOGGING_CATEGORY(DeckFilterStringLog, "deck_filter_string"); /** - * Extra info relevant to filtering that isn't present in the DeckPreviewWidget + * The data a deck search expression is evaluated against. + * + * This is a data view rather than a widget pointer, so the same filter + * expression can be evaluated against a model or a live widget. */ -struct ExtraDeckSearchInfo +struct DeckSearchData { - /** - * The relative filepath starting from the deck folder - */ - QString relativeFilePath; + const LoadedDeck *deck = nullptr; ///< The loaded deck. Must not be null. + QString filePath; ///< Absolute path of the deck file. + QString displayName; ///< Deck name, or the file name if the deck has no name. + QString relativeFilePath; ///< File path relative to the deck folder. }; -typedef std::function DeckFilter; +typedef std::function DeckFilter; class DeckFilterString { public: DeckFilterString(); explicit DeckFilterString(const QString &expr); - bool check(const DeckPreviewWidget *deck, const ExtraDeckSearchInfo &info) const + bool check(const DeckSearchData &data) const { - return filter(deck, info); + return filter(data); } [[nodiscard]] bool valid() const diff --git a/cockatrice/src/interface/widgets/visual_deck_storage/visual_deck_storage_search_widget.cpp b/cockatrice/src/interface/widgets/visual_deck_storage/visual_deck_storage_search_widget.cpp index 07ee55105..0580126c4 100644 --- a/cockatrice/src/interface/widgets/visual_deck_storage/visual_deck_storage_search_widget.cpp +++ b/cockatrice/src/interface/widgets/visual_deck_storage/visual_deck_storage_search_widget.cpp @@ -73,10 +73,14 @@ static QString toRelativeFilepath(const QString &filePath) void VisualDeckStorageSearchWidget::filterWidgets(QList widgets, const QString &searchText) { - auto filterString = DeckFilterString(searchText); + const auto filterString = DeckFilterString(searchText); for (auto widget : widgets) { - QString relativeFilePath = toRelativeFilepath(widget->filePath); - widget->filteredBySearch = !filterString.check(widget, {relativeFilePath}); + const DeckSearchData searchData{.deck = &widget->deckLoader->getDeck(), + .filePath = widget->filePath, + .displayName = widget->getDisplayName(), + .relativeFilePath = toRelativeFilepath(widget->filePath)}; + + widget->filteredBySearch = !filterString.check(searchData); } }