diff --git a/cockatrice/src/client/settings/cache_settings.cpp b/cockatrice/src/client/settings/cache_settings.cpp index 08eccf1e4..fb66a6ebb 100644 --- a/cockatrice/src/client/settings/cache_settings.cpp +++ b/cockatrice/src/client/settings/cache_settings.cpp @@ -50,6 +50,13 @@ SettingsCache &SettingsCache::instance() return *settingsCache; // returns a QT managed singleton reference } +SettingsCache::~SettingsCache() +{ + for (ReleaseChannel *releaseChannel : releaseChannels) { + delete releaseChannel; + } +} + QString SettingsCache::getDataPath() { if (isPortableBuild) { diff --git a/cockatrice/src/client/settings/cache_settings.h b/cockatrice/src/client/settings/cache_settings.h index 5f699247d..472aac44f 100644 --- a/cockatrice/src/client/settings/cache_settings.h +++ b/cockatrice/src/client/settings/cache_settings.h @@ -99,6 +99,7 @@ private: public: SettingsCache(); + ~SettingsCache() override; QString getDataPath(); QString getSettingsPath(); [[nodiscard]] QString getCachePath() const; diff --git a/cockatrice/src/interface/widgets/general/layout_containers/flow_widget.cpp b/cockatrice/src/interface/widgets/general/layout_containers/flow_widget.cpp index caeecad86..6a6025ec2 100644 --- a/cockatrice/src/interface/widgets/general/layout_containers/flow_widget.cpp +++ b/cockatrice/src/interface/widgets/general/layout_containers/flow_widget.cpp @@ -105,9 +105,9 @@ void FlowWidget::addWidget(QWidget *widget_to_add) * * The widget is filtered for arrow-key events so keyboard navigation between * the flow items keeps working even when the flow sits inside a QScrollArea, - * which swallows arrow keys before they can bubble up. Only widgets added - * through this method are affected; anything that needs its own arrow keys - * should use plain addWidget. + * which swallows arrow keys before they can reach FlowWidget::keyPressEvent. + * Only widgets added through this method are affected; anything that needs its + * own arrow keys should use plain addWidget. * * @param widget_to_add The widget to add to the flow layout. */ @@ -207,12 +207,17 @@ QLayoutItem *FlowWidget::itemAt(int index) const return flowLayout->itemAt(index); } +void FlowWidget::keyPressEvent(QKeyEvent *event) +{ + if (moveFocus(event)) { + event->accept(); + return; + } + QWidget::keyPressEvent(event); +} + bool FlowWidget::eventFilter(QObject *watched, QEvent *event) { - // Arrow-key navigation is deliberately scoped to widgets that opted in via - // addNavigableWidget(). Handling arrow keys in keyPressEvent() as well would - // also catch the events ordinary children (QLineEdit, ...) ignore and move - // focus away from the control the user is typing in. if (event->type() == QEvent::KeyPress && moveFocus(static_cast(event))) { return true; } diff --git a/cockatrice/src/interface/widgets/general/layout_containers/flow_widget.h b/cockatrice/src/interface/widgets/general/layout_containers/flow_widget.h index 66f3d9bda..dbf33d07f 100644 --- a/cockatrice/src/interface/widgets/general/layout_containers/flow_widget.h +++ b/cockatrice/src/interface/widgets/general/layout_containers/flow_widget.h @@ -51,6 +51,7 @@ public slots: protected: bool eventFilter(QObject *watched, QEvent *event) override; void resizeEvent(QResizeEvent *event) override; + void keyPressEvent(QKeyEvent *event) override; private: /// @brief Moves keyboard focus to an adjacent flow item for an arrow-key event. diff --git a/libcockatrice_card/libcockatrice/card/database/card_database_querier.cpp b/libcockatrice_card/libcockatrice/card/database/card_database_querier.cpp index 7c41daa3b..2fad5212d 100644 --- a/libcockatrice_card/libcockatrice/card/database/card_database_querier.cpp +++ b/libcockatrice_card/libcockatrice/card/database/card_database_querier.cpp @@ -133,10 +133,6 @@ ExactCard CardDatabaseQuerier::getCard(const CardRef &cardRef) const ExactCard CardDatabaseQuerier::guessCard(const CardRef &cardRef) const { auto card = lookupCardByName(cardRef.name); - if (!card) { - return {}; - } - auto printing = cardRef.providerId.isEmpty() ? getPreferredPrinting(card) : findPrintingWithId(card, cardRef.providerId); @@ -177,14 +173,10 @@ ExactCard CardDatabaseQuerier::getCardFromSameSet(const QString &cardName, const * * @param cardInfo The CardInfo to search * @param providerId The uuid to look for - * @return The PrintingInfo, or a default-constructed PrintingInfo if not found or if cardInfo is null. + * @return The PrintingInfo, or a default-constructed PrintingInfo if not found. */ PrintingInfo CardDatabaseQuerier::findPrintingWithId(const CardInfoPtr &cardInfo, const QString &providerId) const { - if (!cardInfo) { - return PrintingInfo(); - } - for (const auto &printings : cardInfo->getSets()) { for (const auto &printing : printings) { if (printing.getUuid() == providerId) { diff --git a/libcockatrice_filters/libcockatrice/filters/filter_string.cpp b/libcockatrice_filters/libcockatrice/filters/filter_string.cpp index 0acc0eca0..bc137b0f6 100644 --- a/libcockatrice_filters/libcockatrice/filters/filter_string.cpp +++ b/libcockatrice_filters/libcockatrice/filters/filter_string.cpp @@ -43,31 +43,31 @@ SomewhatComplexQueryPart <- [(] QueryPartList [)] / QueryPart QueryPart <- NotQuery / SetQuery / RarityQuery / CMCQuery / FormatQuery / PowerQuery / ToughnessQuery / ColorQuery / TypeQuery / OracleQuery / FieldQuery / GenericQuery NotQuery <- ('NOT' ws/'-') SomewhatComplexQueryPart -SetQuery <- ('e'/'set') ws? SetQueryValue -SetQueryValue <- ([=:] ws? FlexStringValue) / (<[!][=]?> ws? FlexStringValue) / SetExpression -OracleQuery <- 'o' ws? [:] ws? MatcherString +SetQuery <- ('e'/'set') SetQueryValue +SetQueryValue <- ([=:] FlexStringValue) / (<[!][=]?> FlexStringValue) / SetExpression +OracleQuery <- 'o' [:] MatcherString CMCQuery <- ('cmc'/'mv') ws? NumericExpression PowerQuery <- [Pp] 'ow' 'er'? ws? NumericExpression ToughnessQuery <- [Tt] 'ou' 'ghness'? ws? NumericExpression -RarityQuery <- [rR] ws? ':' ws? Rarity +RarityQuery <- [rR] ':' Rarity Rarity <- [Cc] 'ommon'? / [Uu] 'ncommon'? / [Rr] 'are'? / [Mm] 'ythic'? / [Ss] 'pecial'? / [a-zA-Z] [a-z]* -FormatQuery <- 'f' ws? ':' ws? Format / Legality ws? ':' ws? Format +FormatQuery <- 'f' ':' Format / Legality ':' Format Format <- [a-zA-Z] [a-z]* Legality <- [Ll] 'egal'? / [Bb] 'anned'? / [Rr] 'estricted' -TypeQuery <- [tT] 'ype'? ws? [:] ws? StringValue +TypeQuery <- [tT] 'ype'? [:] StringValue Color <- < [Ww] 'hite'? / [Uu] / [Bb] 'lack'? / [Rr] 'ed'? / [Gg] 'reen'? / [Bb] 'lue'? > ColorEx <- Color / [mc] -ColorQuery <- [cC] 'olor'? <[iI]?> ws? <[:!]> ws? ColorEx* +ColorQuery <- [cC] 'olor'? <[iI]?> <[:!]> ColorEx* -FieldQuery <- String ws? [:] ws? MatcherString / String ws? NumericExpression +FieldQuery <- String [:] MatcherString / String ws? NumericExpression NonDoubleQuoteUnlessEscaped <- '\\\"'. / !["]. NonSingleQuoteUnlessEscaped <- "\\\'". / ![']. diff --git a/tests/carddatabase/carddatabase_test.cpp b/tests/carddatabase/carddatabase_test.cpp index 2b216d5b6..1b48d934b 100644 --- a/tests/carddatabase/carddatabase_test.cpp +++ b/tests/carddatabase/carddatabase_test.cpp @@ -1,7 +1,6 @@ #include "libcockatrice/card/database/card_database.h" #include "libcockatrice/card/database/card_database_loader.h" #include "libcockatrice/card/database/card_database_querier.h" -#include "libcockatrice/card/printing/exact_card.h" #include "libcockatrice/card/set/card_set.h" #include "libcockatrice/card/set/card_set_list.h" #include "test_card_database_path_provider.h" @@ -30,7 +29,6 @@ #include #include #include -#include #include namespace @@ -62,31 +60,6 @@ TEST(CardDatabaseTest, LoadXml) ASSERT_EQ(NotLoaded, db->getLoadStatus()) << "Incorrect status after clear"; } -TEST(CardDatabaseTest, GuessCardWithProviderIdOnUnknownCardReturnsEmpty) -{ - // An unknown name plus a providerId used to dereference the missing card - // inside findPrintingWithId(); the lookup must come back empty instead. - NoopCardPreferenceProvider prefs; - TestCardDatabasePathProvider pathProvider; - NoopCardSetPriorityController controller; - CardDatabase db(nullptr, &prefs, &pathProvider, &controller); - - const ExactCard guessed = db.query()->guessCard({"Not a Card", "card_Not a Card_fixture"}); - - EXPECT_TRUE(guessed.isEmpty()); - EXPECT_FALSE(guessed); -} - -TEST(CardDatabaseTest, FindPrintingWithIdOnNullCardInfoReturnsEmpty) -{ - NoopCardPreferenceProvider prefs; - TestCardDatabasePathProvider pathProvider; - NoopCardSetPriorityController controller; - CardDatabase db(nullptr, &prefs, &pathProvider, &controller); - - EXPECT_TRUE(db.query()->findPrintingWithId(nullptr, "card_Not a Card_fixture").isEmpty()); -} - TEST(CardDatabaseTest, Xml4LocalizedDataRoundTrip) { NoopCardSetPriorityController controller; diff --git a/tests/carddatabase/filter_string_test.cpp b/tests/carddatabase/filter_string_test.cpp index e561db590..95225e28c 100644 --- a/tests/carddatabase/filter_string_test.cpp +++ b/tests/carddatabase/filter_string_test.cpp @@ -99,17 +99,6 @@ QUERY(SetCodeWrongSet2, doctor, "set:cat", false) QUERY(BracketNextToUnquotedString, cat, "(o:woof OR o:meow)", true) -// Spaces around the colon are optional for all field queries (e.g. "o: flying") -QUERY(OracleSpaceAfterColon, cat, "o: meow", true) -QUERY(OracleSpaceBeforeColon, cat, "o :meow", true) -QUERY(OracleSpacesAroundColon, cat, "o : meow", true) -QUERY(OracleSpaceAfterColonNoMatch, cat, "o: woof", false) -QUERY(TypeSpaceAfterColon, cat, "t: creature", true) -QUERY(FieldSpaceAfterColon, cat, "pt: \"3/3\"", true) -QUERY(ColorSpaceAfterColon, cat, "c: g", true) -QUERY(ColorSpaceBeforeOperator, cat, "c !g", true) -QUERY(SetSpaceAfterColon, cat, "set: cat", true) - CardInfoPtr localizedCat() { CardInfoPtr localized = CardInfo::newInstance("Cat", "Meow!", false, {}, {}, {}, {}, {}); @@ -118,22 +107,6 @@ CardInfoPtr localizedCat() return localized; } -CardInfoPtr greenIdentityCard() -{ - return CardInfo::newInstance("Identity Cat", "", false, {{"colors", "G"}, {"coloridentity", "G"}}, {}, {}, {}, {}); -} - -// Whitespace belongs around the separator, never inside an operator token: "c i: g" must not -// be read as the color-identity operator "ci" (it is a generic "c" AND a field query on "i"). -TEST_F(CardQuery, ColorIdentityOperatorIsNotSplitByWhitespace) -{ - const CardData identityCard = greenIdentityCard(); - ASSERT_TRUE(FilterString("ci:g").check(identityCard)); - ASSERT_TRUE(FilterString("ci: g").check(identityCard)); - ASSERT_TRUE(FilterString("ci : g").check(identityCard)); - ASSERT_FALSE(FilterString("c i: g").check(identityCard)); -} - TEST_F(CardQuery, SearchLanguageEnglishMatchesOnlyEnglish) { const CardData localized = localizedCat(); @@ -163,13 +136,6 @@ TEST_F(CardQuery, SearchLanguageBothMatchesEitherLanguage) ASSERT_TRUE(FilterString("Kater", CardSearchLanguage{"de", SearchLanguageMode::Both}).check(localized)); } -TEST_F(CardQuery, SearchLanguageBothMatchesOracleTextWithSpaceAfterColon) -{ - const CardData localized = localizedCat(); - ASSERT_TRUE(FilterString("o: Meow", CardSearchLanguage{"de", SearchLanguageMode::Both}).check(localized)); - ASSERT_TRUE(FilterString("o: miaut", CardSearchLanguage{"de", SearchLanguageMode::Both}).check(localized)); -} - TEST_F(CardQuery, SearchLanguageIsBoundPerInstance) { const CardData localized = localizedCat();