From 7a41dfe17543134c2cd40da2b5e12a2604d886f5 Mon Sep 17 00:00:00 2001 From: BruebachL <44814898+BruebachL@users.noreply.github.com> Date: Mon, 21 Sep 2026 21:48:34 +0200 Subject: [PATCH] [PictureLoader] Fix custom-folder pictures in subdirectories not loading (#7340) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit CardPictureLoaderLocal compared the full file name (including extension) of the custom-folder candidate against the extension-stripped base name of each directory entry, so a CUSTOM subfolder image like pics/CUSTOM/poker/1 of Hearts.png never matched and the card fell through to the network. Compare the complete base names instead. Add matcher tests covering CUSTOM subfolder resolution. Co-authored-by: Lukas BrĂ¼bach --- .../card_picture_loader_local.cpp | 2 +- tests/loader_local_matching_test.cpp | 34 +++++++++++++++++++ 2 files changed, 35 insertions(+), 1 deletion(-) diff --git a/cockatrice/src/interface/card_picture_loader/card_picture_loader_local.cpp b/cockatrice/src/interface/card_picture_loader/card_picture_loader_local.cpp index c82fca403..12165e8f3 100644 --- a/cockatrice/src/interface/card_picture_loader/card_picture_loader_local.cpp +++ b/cockatrice/src/interface/card_picture_loader/card_picture_loader_local.cpp @@ -101,7 +101,7 @@ QImage CardPictureLoaderLocal::tryLoadCardImageFromDisk(const QString &setName, for (const QString &path : candidatePaths) { QFileInfo fileInfo(path); QDir dir = fileInfo.dir(); - QString baseName = fileInfo.fileName(); + QString baseName = fileInfo.completeBaseName(); if (!dir.exists()) { continue; diff --git a/tests/loader_local_matching_test.cpp b/tests/loader_local_matching_test.cpp index 7ffa7157d..6ce684fdd 100644 --- a/tests/loader_local_matching_test.cpp +++ b/tests/loader_local_matching_test.cpp @@ -68,6 +68,18 @@ protected: loader = nullptr; } + /** + * @brief Destroys and rebuilds the loader so the CUSTOM index is re-scanned. + * + * The CUSTOM-folder index is snapshotted at construction; rebuild it after + * writing files so freshly placed images are discoverable. + */ + void rebuildLoader() + { + delete loader; + loader = new CardPictureLoaderLocal(nullptr); + } + /** * @brief Writes a valid 1x1 PNG under the sandboxed pics path. */ @@ -162,6 +174,28 @@ TEST_F(LocalMatcherTest, SetFolderCandidateTakesPrecedenceOverRootFallback) EXPECT_EQ(image.pixelColor(0, 0), QColor(Qt::red)) << "The set-folder candidate must be preferred"; } +TEST_F(LocalMatcherTest, CustomSubfolderResolvesExactFile) +{ + // Images in the CUSTOM folder are indexed by their full file path (extension included), + // unlike the extension-less candidate paths built from the naming schemes. + writePngUnderPics("CUSTOM/poker/TestCard.png"); + rebuildLoader(); + + const QImage image = loader->tryLoad(cardFor("TestCard", "", "")); + + EXPECT_FALSE(image.isNull()) << "A CUSTOM-folder image in a subdirectory must resolve"; +} + +TEST_F(LocalMatcherTest, CustomSubfolderIgnoresSuffixedFiles) +{ + writePngUnderPics("CUSTOM/poker/TestCard (1).png"); + rebuildLoader(); + + const QImage image = loader->tryLoad(cardFor("TestCard", "", "")); + + EXPECT_TRUE(image.isNull()) << "A suffixed CUSTOM-folder file must not satisfy an exact name lookup"; +} + } // namespace int main(int argc, char **argv)