From 04f77bd9f73d58d09c5dfc4695deb61450fcbe2d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lukas=20Br=C3=BCbach?= Date: Sat, 19 Sep 2026 10:53:18 +0200 Subject: [PATCH] [Card] Pass the card search language to deck and zone card searches Wire the two remaining FilterString consumers to the configured card search language so card-name matches respect it everywhere: - DeckFilterString now takes the search language and mode, exposes them to its [[card name]] rule action via a thread-local parse context (same pattern as FilterString), and the engine's card database uses them for content search. - ZoneViewZone reads the card language from CardsDisplaySettings when applying its search filter, and the reveal-zone widget re-applies the active search when the language setting changes. - The deck-storage search re-runs its filter against the current card language setting, including live re-application when the setting changes. Game-action targeting (DlgMoveTopCardsUntil) intentionally keeps evaluating against English card names. --- cockatrice/src/filters/deck_filter_string.cpp | 21 +++++++++++++++++-- cockatrice/src/filters/deck_filter_string.h | 5 ++++- .../src/game_graphics/zones/view_zone.cpp | 7 ++++++- .../game_graphics/zones/view_zone_widget.cpp | 6 ++++++ ...l_deck_storage_sort_filter_proxy_model.cpp | 7 ++++++- .../visual_deck_storage_widget.cpp | 8 +++++++ 6 files changed, 49 insertions(+), 5 deletions(-) diff --git a/cockatrice/src/filters/deck_filter_string.cpp b/cockatrice/src/filters/deck_filter_string.cpp index 4abb8210c..3f4fe9569 100644 --- a/cockatrice/src/filters/deck_filter_string.cpp +++ b/cockatrice/src/filters/deck_filter_string.cpp @@ -43,6 +43,17 @@ NumericValue <- [0-9]+ static std::once_flag init; +// The peglib parser is a single permanent object, so the rule actions below cannot see +// per-instance state. The card language that the nested [[card name]] search matches +// against is passed through this thread-local context, which is live only while a +// DeckFilterString is being parsed, and copied into the nested FilterString closures. +struct DeckSearchLanguageContext +{ + QString searchLanguage; + CardSearchLanguage searchLanguageMode = CardSearchLanguage::English; +}; +thread_local DeckSearchLanguageContext deckSearchLanguageContext; + static void setupParserRules() { // plumbing @@ -116,7 +127,9 @@ static void setupParserRules() // actual functionality search["DeckContentQuery"] = [](const peg::SemanticValues &sv) -> DeckFilter { - auto cardFilter = FilterString(std::any_cast(sv[0])); + const QString searchLanguage = deckSearchLanguageContext.searchLanguage; + const CardSearchLanguage searchLanguageMode = deckSearchLanguageContext.searchLanguageMode; + auto cardFilter = FilterString(std::any_cast(sv[0]), searchLanguage, searchLanguageMode); auto numberMatcher = sv.size() > 1 ? std::any_cast(sv[1]) : [](int count) { return count > 0; }; return [=](const DeckSearchData &data) -> bool { @@ -186,7 +199,9 @@ DeckFilterString::DeckFilterString() _error = "Not initialized"; } -DeckFilterString::DeckFilterString(const QString &expr) +DeckFilterString::DeckFilterString(const QString &expr, + const QString &searchLanguage, + CardSearchLanguage searchLanguageMode) { QByteArray ba = expr.simplified().toUtf8(); @@ -199,6 +214,8 @@ DeckFilterString::DeckFilterString(const QString &expr) return; } + deckSearchLanguageContext = DeckSearchLanguageContext{searchLanguage, searchLanguageMode}; + search.set_logger([&](size_t /*ln*/, size_t col, const std::string &msg) { _error = QString("Error at position %1: %2").arg(col).arg(QString::fromStdString(msg)); }); diff --git a/cockatrice/src/filters/deck_filter_string.h b/cockatrice/src/filters/deck_filter_string.h index 90a6a17eb..ef380459c 100644 --- a/cockatrice/src/filters/deck_filter_string.h +++ b/cockatrice/src/filters/deck_filter_string.h @@ -12,6 +12,7 @@ #include #include #include +#include inline Q_LOGGING_CATEGORY(DeckFilterStringLog, "deck_filter_string"); @@ -35,7 +36,9 @@ class DeckFilterString { public: DeckFilterString(); - explicit DeckFilterString(const QString &expr); + explicit DeckFilterString(const QString &expr, + const QString &searchLanguage = QString(), + CardSearchLanguage searchLanguageMode = CardSearchLanguage::English); bool check(const DeckSearchData &data) const { return filter(data); diff --git a/cockatrice/src/game_graphics/zones/view_zone.cpp b/cockatrice/src/game_graphics/zones/view_zone.cpp index baf7b8b30..c4e781789 100644 --- a/cockatrice/src/game_graphics/zones/view_zone.cpp +++ b/cockatrice/src/game_graphics/zones/view_zone.cpp @@ -1,5 +1,6 @@ #include "view_zone.h" +#include "../../client/settings/cache_settings.h" #include "../../game/player/player_actions.h" #include "../../game/player/player_logic.h" #include "../../game/zones/view_zone_logic.h" @@ -11,11 +12,13 @@ #include #include #include +#include #include #include #include #include #include +#include /** * @param parent the parent QGraphicsWidget containing the reveal zone @@ -253,7 +256,9 @@ ZoneViewZone::GridSize ZoneViewZone::positionCardsForDisplay(CardList &cards, Ca void ZoneViewZone::setFilterString(const QString &_filterString) { - filterString = FilterString(_filterString); + const CardsDisplaySettings &cardsDisplay = SettingsCache::instance().cardsDisplay(); + filterString = FilterString(_filterString, cardsDisplay.getCardLang(), + static_cast(cardsDisplay.getCardSearchLanguage())); reorganizeCards(); } diff --git a/cockatrice/src/game_graphics/zones/view_zone_widget.cpp b/cockatrice/src/game_graphics/zones/view_zone_widget.cpp index c13b79fea..f659ec8ff 100644 --- a/cockatrice/src/game_graphics/zones/view_zone_widget.cpp +++ b/cockatrice/src/game_graphics/zones/view_zone_widget.cpp @@ -21,6 +21,7 @@ #include #include #include +#include #include namespace @@ -168,6 +169,11 @@ ZoneViewWidget::ZoneViewWidget(PlayerLogic *_player, } connect(&searchEdit, &QLineEdit::textChanged, zone, &ZoneViewZone::setFilterString); + + CardsDisplaySettings *cardsDisplay = &SettingsCache::instance().cardsDisplay(); + const auto applyCardSearchLanguage = [this] { zone->setFilterString(searchEdit.text()); }; + connect(cardsDisplay, &CardsDisplaySettings::cardLangChanged, this, applyCardSearchLanguage); + connect(cardsDisplay, &CardsDisplaySettings::cardSearchLanguageChanged, this, applyCardSearchLanguage); } setLayout(vbox); diff --git a/cockatrice/src/interface/widgets/visual_deck_storage/visual_deck_storage_sort_filter_proxy_model.cpp b/cockatrice/src/interface/widgets/visual_deck_storage/visual_deck_storage_sort_filter_proxy_model.cpp index c05da1cb3..f22de3c62 100644 --- a/cockatrice/src/interface/widgets/visual_deck_storage/visual_deck_storage_sort_filter_proxy_model.cpp +++ b/cockatrice/src/interface/widgets/visual_deck_storage/visual_deck_storage_sort_filter_proxy_model.cpp @@ -1,9 +1,12 @@ #include "visual_deck_storage_sort_filter_proxy_model.h" +#include "../../../client/settings/cache_settings.h" #include "../../filters/deck_filter_string.h" #include #include +#include +#include VisualDeckStorageSortFilterProxyModel::VisualDeckStorageSortFilterProxyModel(QObject *parent) : QSortFilterProxyModel(parent) @@ -187,7 +190,9 @@ void VisualDeckStorageSortFilterProxyModel::updateSearchMatches() return; } - DeckFilterString filterString(searchText); + const auto &cardsDisplay = SettingsCache::instance().cardsDisplay(); + DeckFilterString filterString(searchText, cardsDisplay.getCardLang(), + static_cast(cardsDisplay.getCardSearchLanguage())); for (int row = 0; row < count; ++row) { const DeckPreviewData &data = source->dataForRow(row); diff --git a/cockatrice/src/interface/widgets/visual_deck_storage/visual_deck_storage_widget.cpp b/cockatrice/src/interface/widgets/visual_deck_storage/visual_deck_storage_widget.cpp index da7ddc368..c4f259e3d 100644 --- a/cockatrice/src/interface/widgets/visual_deck_storage/visual_deck_storage_widget.cpp +++ b/cockatrice/src/interface/widgets/visual_deck_storage/visual_deck_storage_widget.cpp @@ -15,6 +15,7 @@ #include #include #include +#include #include #include @@ -108,6 +109,13 @@ VisualDeckStorageWidget::VisualDeckStorageWidget(QWidget *parent) : QWidget(pare connect(searchWidget, &VisualDeckStorageSearchWidget::searchTextChanged, this, &VisualDeckStorageWidget::updateSearchFilter); + // The deck content search matches card names in the configured card language; + // re-run it whenever that setting changes so active searches follow immediately. + CardsDisplaySettings *cardsDisplay = &SettingsCache::instance().cardsDisplay(); + const auto reapplySearchForLanguage = [this] { storageProxyModel->reapplyFilters(); }; + connect(cardsDisplay, &CardsDisplaySettings::cardLangChanged, this, reapplySearchForLanguage); + connect(cardsDisplay, &CardsDisplaySettings::cardSearchLanguageChanged, this, reapplySearchForLanguage); + connect(CardDatabaseManager::getInstance(), &CardDatabase::cardDatabaseLoadingFinished, this, &VisualDeckStorageWidget::createRootFolderWidget);