From c8c7dcba5f9d2d786a88414f72dd1178bb91ad31 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lukas=20Br=C3=BCbach?= Date: Mon, 13 Apr 2026 14:42:47 +0200 Subject: [PATCH] Allow toggling between caching methods. Took 1 hour 30 minutes Took 9 seconds --- .../src/client/settings/cache_settings.cpp | 21 ++++--- .../src/client/settings/cache_settings.h | 15 ++--- .../card_picture_loader.cpp | 3 +- .../card_picture_loader_cache_method.h | 30 +++++++++ .../card_picture_loader_worker.cpp | 38 +++++++---- .../widgets/dialogs/dlg_settings.cpp | 63 +++++++++++++++++-- .../interface/widgets/dialogs/dlg_settings.h | 3 + 7 files changed, 138 insertions(+), 35 deletions(-) create mode 100644 cockatrice/src/interface/card_picture_loader/card_picture_loader_cache_method.h diff --git a/cockatrice/src/client/settings/cache_settings.cpp b/cockatrice/src/client/settings/cache_settings.cpp index e7840e61b..910f82535 100644 --- a/cockatrice/src/client/settings/cache_settings.cpp +++ b/cockatrice/src/client/settings/cache_settings.cpp @@ -1,5 +1,6 @@ #include "cache_settings.h" +#include "../../interface/card_picture_loader/card_picture_loader_cache_method.h" #include "../../interface/card_picture_loader/card_picture_loader_local_schemes.h" #include "../network/update/client/release_channel.h" #include "card_counter_settings.h" @@ -265,7 +266,11 @@ SettingsCache::SettingsCache() networkCacheSize = settings->value("personal/networkCacheSize", NETWORK_CACHE_SIZE_DEFAULT).toInt(); redirectCacheTtl = settings->value("personal/redirectCacheTtl", NETWORK_REDIRECT_CACHE_TTL_DEFAULT).toInt(); - saveCardImagesToLocalStorage = settings->value("personal/saveCardImagesToLocalStorage", true).toBool(); + cardPictureLoaderCacheMethod = + settings + ->value("personal/cardPictureLoaderCacheMethod", + static_cast(CardPictureLoaderCacheMethod::CacheMethod::NETWORK_CACHE)) + .toInt(); localCardImageStorageNamingScheme = settings ->value("personal/localCardImageStorageNamingScheme", @@ -1104,6 +1109,13 @@ void SettingsCache::setPixmapCacheSize(const int _pixmapCacheSize) emit pixmapCacheSizeChanged(pixmapCacheSize); } +void SettingsCache::setCardImageCacheMethod(const CardPictureLoaderCacheMethod::CacheMethod _cardImageCachingMethod) +{ + cardPictureLoaderCacheMethod = static_cast(_cardImageCachingMethod); + settings->setValue("personal/cardPictureLoaderCacheMethod", cardPictureLoaderCacheMethod); + emit cardPictureLoaderCacheMethodChanged(cardPictureLoaderCacheMethod); +} + void SettingsCache::setNetworkCacheSizeInMB(const int _networkCacheSize) { networkCacheSize = _networkCacheSize; @@ -1118,13 +1130,6 @@ void SettingsCache::setNetworkRedirectCacheTtl(const int _redirectCacheTtl) emit redirectCacheTtlChanged(redirectCacheTtl); } -void SettingsCache::setSaveCardImagesToLocalStorage(QT_STATE_CHANGED_T _saveCardImagesToLocalStorage) -{ - saveCardImagesToLocalStorage = _saveCardImagesToLocalStorage; - settings->setValue("personal/saveCardImagesToLocalStorage", saveCardImagesToLocalStorage); - emit saveCardImagesToLocalStorageChanged(saveCardImagesToLocalStorage); -} - void SettingsCache::setLocalCardImageStorageNamingScheme( const CardPictureLoaderLocalSchemes::NamingScheme _localCardImageStorageNamingScheme) { diff --git a/cockatrice/src/client/settings/cache_settings.h b/cockatrice/src/client/settings/cache_settings.h index bbd1aaf98..6cb89bb1c 100644 --- a/cockatrice/src/client/settings/cache_settings.h +++ b/cockatrice/src/client/settings/cache_settings.h @@ -7,6 +7,7 @@ #ifndef SETTINGSCACHE_H #define SETTINGSCACHE_H +#include "../../interface/card_picture_loader/card_picture_loader_cache_method.h" #include "../../interface/card_picture_loader/card_picture_loader_local_schemes.h" #include "shortcuts_settings.h" @@ -185,7 +186,7 @@ signals: void pixmapCacheSizeChanged(int newSizeInMBs); void networkCacheSizeChanged(int newSizeInMBs); void redirectCacheTtlChanged(int newTtl); - void saveCardImagesToLocalStorageChanged(bool saveCardImagesToLocalStorage); + void cardPictureLoaderCacheMethodChanged(int cardPictureLoaderCacheMethod); void localCardImageStorageNamingSchemeChanged(int localCardImageStorageNamingScheme); void masterVolumeChanged(int value); void chatMentionCompleterChanged(); @@ -305,7 +306,7 @@ private: int pixmapCacheSize; int networkCacheSize; int redirectCacheTtl; - bool saveCardImagesToLocalStorage; + int cardPictureLoaderCacheMethod; int localCardImageStorageNamingScheme; bool scaleCards; int verticalCardOverlapPercent; @@ -786,6 +787,10 @@ public: { return pixmapCacheSize; } + [[nodiscard]] CardPictureLoaderCacheMethod::CacheMethod getCardPictureLoaderCacheMethod() const + { + return static_cast(cardPictureLoaderCacheMethod); + } [[nodiscard]] int getNetworkCacheSizeInMB() const { return networkCacheSize; @@ -794,10 +799,6 @@ public: { return redirectCacheTtl; } - [[nodiscard]] bool getSaveCardImagesToLocalStorage() const - { - return saveCardImagesToLocalStorage; - } [[nodiscard]] CardPictureLoaderLocalSchemes::NamingScheme getLocalCardImageStorageNamingScheme() const { return static_cast(localCardImageStorageNamingScheme); @@ -1106,9 +1107,9 @@ public slots: void setIgnoreUnregisteredUsers(QT_STATE_CHANGED_T _ignoreUnregisteredUsers); void setIgnoreUnregisteredUserMessages(QT_STATE_CHANGED_T _ignoreUnregisteredUserMessages); void setPixmapCacheSize(const int _pixmapCacheSize); + void setCardImageCacheMethod(CardPictureLoaderCacheMethod::CacheMethod _cardImageCachingMethod); void setNetworkCacheSizeInMB(const int _networkCacheSize); void setNetworkRedirectCacheTtl(const int _redirectCacheTtl); - void setSaveCardImagesToLocalStorage(QT_STATE_CHANGED_T _saveCardImagesToLocalStorage); void setLocalCardImageStorageNamingScheme( const CardPictureLoaderLocalSchemes::NamingScheme _localCardImageStorageNamingScheme); void setCardScaling(const QT_STATE_CHANGED_T _scaleCards); diff --git a/cockatrice/src/interface/card_picture_loader/card_picture_loader.cpp b/cockatrice/src/interface/card_picture_loader/card_picture_loader.cpp index 6a9bc0806..0285b306e 100644 --- a/cockatrice/src/interface/card_picture_loader/card_picture_loader.cpp +++ b/cockatrice/src/interface/card_picture_loader/card_picture_loader.cpp @@ -169,7 +169,8 @@ void CardPictureLoader::imageLoaded(const ExactCard &card, const QImage &image) QPixmapCache::insert(card.getPixmapCacheKey(), finalPixmap); - if (SettingsCache::instance().getSaveCardImagesToLocalStorage()) { + if (SettingsCache::instance().getCardPictureLoaderCacheMethod() == + CardPictureLoaderCacheMethod::CacheMethod::FILESYSTEM_CACHE) { saveCardImageToLocalStorage(card, finalPixmap); } diff --git a/cockatrice/src/interface/card_picture_loader/card_picture_loader_cache_method.h b/cockatrice/src/interface/card_picture_loader/card_picture_loader_cache_method.h new file mode 100644 index 000000000..ead77fea2 --- /dev/null +++ b/cockatrice/src/interface/card_picture_loader/card_picture_loader_cache_method.h @@ -0,0 +1,30 @@ +#ifndef COCKATRICE_CARD_PICTURE_LOADER_CACHE_METHOD_H +#define COCKATRICE_CARD_PICTURE_LOADER_CACHE_METHOD_H +#include +#include + +namespace CardPictureLoaderCacheMethod +{ +enum class CacheMethod +{ + NETWORK_CACHE, + FILESYSTEM_CACHE +}; + +struct CacheMethodInfo +{ + CacheMethod id; + QString displayName; +}; + +static inline const QList methods() +{ + static QList all = { + {CacheMethod::NETWORK_CACHE, "Network Cache"}, + {CacheMethod::FILESYSTEM_CACHE, "Filesystem Cache"}, + }; + return all; +} +} // namespace CardPictureLoaderCacheMethod + +#endif // COCKATRICE_CARD_PICTURE_LOADER_CACHE_METHOD_H diff --git a/cockatrice/src/interface/card_picture_loader/card_picture_loader_worker.cpp b/cockatrice/src/interface/card_picture_loader/card_picture_loader_worker.cpp index a246d74f2..a0f000139 100644 --- a/cockatrice/src/interface/card_picture_loader/card_picture_loader_worker.cpp +++ b/cockatrice/src/interface/card_picture_loader/card_picture_loader_worker.cpp @@ -26,10 +26,14 @@ CardPictureLoaderWorker::CardPictureLoaderWorker() cache->setCacheDirectory(SettingsCache::instance().getNetworkCachePath()); cache->setMaximumCacheSize(1024L * 1024L * static_cast(SettingsCache::instance().getNetworkCacheSizeInMB())); - // Note: the settings is in MB, but QNetworkDiskCache uses bytes - connect(&SettingsCache::instance(), &SettingsCache::networkCacheSizeChanged, this, - [this](int newSizeInMB) { cache->setMaximumCacheSize(1024L * 1024L * static_cast(newSizeInMB)); }); + + connect(&SettingsCache::instance(), &SettingsCache::networkCacheSizeChanged, cache, [this](int newSizeInMB) { + if (cache) + cache->setMaximumCacheSize(1024L * 1024L * static_cast(newSizeInMB)); + }); + networkManager->setCache(cache); + // Use a ManualRedirectPolicy since we keep track of redirects in picDownloadFinished // We can't use NoLessSafeRedirectPolicy because it is not applied with AlwaysCache networkManager->setRedirectPolicy(QNetworkRequest::ManualRedirectPolicy); @@ -65,14 +69,19 @@ void CardPictureLoaderWorker::queueRequest(const QUrl &url, CardPictureLoaderWor QUrl cachedRedirect = getCachedRedirect(url); if (!cachedRedirect.isEmpty()) { queueRequest(cachedRedirect, worker); - } else if (cache->metaData(url).isValid()) { - // If we hit a cached url, we get to make the request for free, since it won't contribute towards the rate-limit - makeRequest(url, worker); - } else { - requestLoadQueue.append(qMakePair(url, worker)); - emit imageRequestQueued(url, worker->cardToDownload.getCard(), worker->cardToDownload.getSetName()); - processQueuedRequests(); + return; } + if (SettingsCache::instance().getCardPictureLoaderCacheMethod() == + CardPictureLoaderCacheMethod::CacheMethod::NETWORK_CACHE && + cache->metaData(url).isValid()) { + // If we hit a cached url, we get to make the request for free, since it won't contribute towards the + // rate-limit + makeRequest(url, worker); + return; + } + requestLoadQueue.append(qMakePair(url, worker)); + emit imageRequestQueued(url, worker->cardToDownload.getCard(), worker->cardToDownload.getSetName()); + processQueuedRequests(); } QNetworkReply *CardPictureLoaderWorker::makeRequest(const QUrl &url, CardPictureLoaderWorkerWork *worker) @@ -87,9 +96,12 @@ QNetworkReply *CardPictureLoaderWorker::makeRequest(const QUrl &url, CardPicture QNetworkRequest req(url); req.setHeader(QNetworkRequest::UserAgentHeader, QString("Cockatrice %1").arg(VERSION_STRING)); req.setRawHeader("Accept", "image/avif,image/webp,image/apng,image/,/*;q=0.8"); - if (!picDownload) { - req.setAttribute(QNetworkRequest::CacheLoadControlAttribute, QNetworkRequest::AlwaysCache); - } + + bool useNetworkCache = !picDownload && SettingsCache::instance().getCardPictureLoaderCacheMethod() == + CardPictureLoaderCacheMethod::CacheMethod::NETWORK_CACHE; + + req.setAttribute(QNetworkRequest::CacheLoadControlAttribute, + useNetworkCache ? QNetworkRequest::AlwaysCache : QNetworkRequest::AlwaysNetwork); QNetworkReply *reply = networkManager->get(req); diff --git a/cockatrice/src/interface/widgets/dialogs/dlg_settings.cpp b/cockatrice/src/interface/widgets/dialogs/dlg_settings.cpp index b5b404246..7f270365e 100644 --- a/cockatrice/src/interface/widgets/dialogs/dlg_settings.cpp +++ b/cockatrice/src/interface/widgets/dialogs/dlg_settings.cpp @@ -1244,6 +1244,41 @@ StorageSettingsPage::StorageSettingsPage() pixmapCacheEdit.setValue(SettingsCache::instance().getPixmapCacheSize()); pixmapCacheEdit.setSuffix(" MB"); + // Caching method + + cardPictureLoaderCacheMethodComboBox = new QComboBox; + for (auto method : CardPictureLoaderCacheMethod::methods()) { + cardPictureLoaderCacheMethodComboBox->addItem(method.displayName, static_cast(method.id)); + } + + int currentCacheMethod = static_cast(SettingsCache::instance().getCardPictureLoaderCacheMethod()); + + int currentIndex = cardPictureLoaderCacheMethodComboBox->findData(currentCacheMethod); + if (currentIndex >= 0) { + cardPictureLoaderCacheMethodComboBox->setCurrentIndex(currentIndex); + } + + connect(cardPictureLoaderCacheMethodComboBox, qOverload(&QComboBox::currentIndexChanged), this, + [this](int index) { + auto cacheMethod = static_cast( + cardPictureLoaderCacheMethodComboBox->itemData(index).toInt()); + + bool useNetworkCache = (cacheMethod == CardPictureLoaderCacheMethod::CacheMethod::NETWORK_CACHE); + + if (useNetworkCache) { + clearImageBackupsButtonClicked(); + } else { + clearDownloadedPicsButtonClicked(); + } + + mpNetworkCacheGroupBox->setEnabled(useNetworkCache); + mpImageBackupGroupBox->setEnabled(!useNetworkCache); + + SettingsCache::instance().setCardImageCacheMethod(cacheMethod); + }); + + // Network Cache + networkCacheEdit.setMinimum(NETWORK_CACHE_SIZE_MIN); networkCacheEdit.setMaximum(NETWORK_CACHE_SIZE_MAX); networkCacheEdit.setSingleStep(1); @@ -1256,10 +1291,6 @@ StorageSettingsPage::StorageSettingsPage() networkRedirectCacheTtlEdit.setValue(SettingsCache::instance().getRedirectCacheTtl()); // Image Backup - saveCardImagesToLocalStorageCheckBox.setChecked(SettingsCache::instance().getSaveCardImagesToLocalStorage()); - connect(&saveCardImagesToLocalStorageCheckBox, &QCheckBox::QT_STATE_CHANGED, &SettingsCache::instance(), - &SettingsCache::setSaveCardImagesToLocalStorage); - localCardImageStorageNamingSchemeComboBox = new QComboBox; for (const auto &scheme : CardPictureLoaderLocalSchemes::exportSchemes()) { localCardImageStorageNamingSchemeComboBox->addItem(scheme.displayName, static_cast(scheme.id)); @@ -1281,7 +1312,12 @@ StorageSettingsPage::StorageSettingsPage() connect(&clearBackupsButton, &QPushButton::clicked, this, &StorageSettingsPage::clearImageBackupsButtonClicked); + auto cacheMethodLayout = new QHBoxLayout; + cacheMethodLayout->addWidget(&cardPictureLoaderCacheMethodLabel); + cacheMethodLayout->addWidget(cardPictureLoaderCacheMethodComboBox); + auto networkCacheLayout = new QHBoxLayout; + networkCacheLayout->addWidget(&clearDownloadedPicsButton); networkCacheLayout->addStretch(); networkCacheLayout->addWidget(&networkCacheLabel); networkCacheLayout->addWidget(&networkCacheEdit); @@ -1299,7 +1335,6 @@ StorageSettingsPage::StorageSettingsPage() lpNetworkCacheGrid->addWidget(&networkCacheExplainerLabel, 0, 0); lpNetworkCacheGrid->addLayout(networkCacheLayout, 1, 0); lpNetworkCacheGrid->addLayout(networkRedirectCacheLayout, 2, 0); - lpNetworkCacheGrid->addWidget(&clearDownloadedPicsButton, 3, 0); // Image Backup Layout lpImageBackupGrid->addWidget(&imageBackupExplainerLabel, 0, 0, 1, 2); @@ -1309,7 +1344,7 @@ StorageSettingsPage::StorageSettingsPage() lpImageBackupGrid->addWidget(&clearBackupsButton, 3, 1); lpPixmapCacheGrid->addWidget(&pixmapCacheExplainerLabel, 0, 0); - lpPixmapCacheGrid->addLayout(pixmapCacheLayout, 1, 0); + lpPixmapCacheGrid->addLayout(pixmapCacheLayout, 1, 1); connect(&pixmapCacheEdit, qOverload(&QSpinBox::valueChanged), &SettingsCache::instance(), &SettingsCache::setPixmapCacheSize); @@ -1318,6 +1353,9 @@ StorageSettingsPage::StorageSettingsPage() connect(&networkRedirectCacheTtlEdit, qOverload(&QSpinBox::valueChanged), &SettingsCache::instance(), &SettingsCache::setNetworkRedirectCacheTtl); + mpCacheMethodGroupBox = new QGroupBox; + mpCacheMethodGroupBox->setLayout(cacheMethodLayout); + mpNetworkCacheGroupBox = new QGroupBox; mpNetworkCacheGroupBox->setLayout(lpNetworkCacheGrid); @@ -1329,12 +1367,19 @@ StorageSettingsPage::StorageSettingsPage() auto *lpMainLayout = new QVBoxLayout; + lpMainLayout->addWidget(mpCacheMethodGroupBox); lpMainLayout->addWidget(mpNetworkCacheGroupBox); lpMainLayout->addWidget(mpImageBackupGroupBox); lpMainLayout->addWidget(mpPixmapCacheGroupBox); setLayout(lpMainLayout); + bool useNetworkCache = SettingsCache::instance().getCardPictureLoaderCacheMethod() == + CardPictureLoaderCacheMethod::CacheMethod::NETWORK_CACHE; + + mpNetworkCacheGroupBox->setEnabled(useNetworkCache); + mpImageBackupGroupBox->setEnabled(!useNetworkCache); + connect(&SettingsCache::instance(), &SettingsCache::langChanged, this, &StorageSettingsPage::retranslateUi); retranslateUi(); } @@ -1342,6 +1387,7 @@ StorageSettingsPage::StorageSettingsPage() void StorageSettingsPage::clearDownloadedPicsButtonClicked() { CardPictureLoader::clearNetworkCache(); + CardPictureLoader::clearPixmapCache(); QMessageBox::information(this, tr("Success"), tr("Cached card pictures have been reset.")); } @@ -1352,6 +1398,8 @@ void StorageSettingsPage::clearImageBackupsButtonClicked() QDir dir(picsPath); bool success = dir.removeRecursively(); + CardPictureLoader::clearPixmapCache(); + if (success) { QMessageBox::information(this, tr("Success"), tr("Downloaded card pictures have been reset.")); } else { @@ -1361,6 +1409,8 @@ void StorageSettingsPage::clearImageBackupsButtonClicked() void StorageSettingsPage::retranslateUi() { + cardPictureLoaderCacheMethodLabel.setText(tr("Card Picture Loader Caching Method:")); + networkCacheExplainerLabel.setText( tr("The network cache is the preferred way of storing images. Downloaded images " "are stored here until the size of the cache exceeds the configured size. Cockatrice automatically monitors " @@ -1383,6 +1433,7 @@ void StorageSettingsPage::retranslateUi() clearDownloadedPicsButton.setText(tr("Delete Cached Images")); clearBackupsButton.setText(tr("Delete Saved Images")); + mpCacheMethodGroupBox->setTitle(tr("Card Picture Loader Cache Method")); mpNetworkCacheGroupBox->setTitle(tr("Network Cache")); mpImageBackupGroupBox->setTitle(tr("Image Backup")); mpPixmapCacheGroupBox->setTitle(tr("In-Memory Picture Cache")); diff --git a/cockatrice/src/interface/widgets/dialogs/dlg_settings.h b/cockatrice/src/interface/widgets/dialogs/dlg_settings.h index 318311f8b..829f21869 100644 --- a/cockatrice/src/interface/widgets/dialogs/dlg_settings.h +++ b/cockatrice/src/interface/widgets/dialogs/dlg_settings.h @@ -249,6 +249,7 @@ private: QPushButton clearDownloadedPicsButton; QPushButton clearBackupsButton; + QGroupBox *mpCacheMethodGroupBox; QGroupBox *mpNetworkCacheGroupBox; QGroupBox *mpImageBackupGroupBox; QGroupBox *mpPixmapCacheGroupBox; @@ -257,6 +258,8 @@ private: QLabel imageBackupExplainerLabel; QLabel pixmapCacheExplainerLabel; + QLabel cardPictureLoaderCacheMethodLabel; + QComboBox *cardPictureLoaderCacheMethodComboBox; QLabel networkCacheLabel; QSpinBox networkCacheEdit; QLabel networkRedirectCacheTtlLabel;