diff --git a/cockatrice/src/dlg_settings.cpp b/cockatrice/src/dlg_settings.cpp index 0182f7c5..b4f90662 100644 --- a/cockatrice/src/dlg_settings.cpp +++ b/cockatrice/src/dlg_settings.cpp @@ -3,6 +3,7 @@ #include "carddatabase.h" #include "gettextwithmax.h" #include "main.h" +#include "pictureloader.h" #include "releasechannel.h" #include "sequenceEdit/sequenceedit.h" #include "settingscache.h" @@ -68,18 +69,9 @@ GeneralSettingsPage::GeneralSettingsPage() updateNotificationCheckBox.setChecked(settings.getNotifyAboutUpdates()); newVersionOracleCheckBox.setChecked(settings.getNotifyAboutNewVersion()); - // pixmap cache - pixmapCacheEdit.setMinimum(PIXMAPCACHE_SIZE_MIN); - // 2047 is the max value to avoid overflowing of QPixmapCache::setCacheLimit(int size) - pixmapCacheEdit.setMaximum(PIXMAPCACHE_SIZE_MAX); - pixmapCacheEdit.setSingleStep(64); - pixmapCacheEdit.setValue(settings.getPixmapCacheSize()); - pixmapCacheEdit.setSuffix(" MB"); - showTipsOnStartup.setChecked(settings.getShowTipsOnStartup()); connect(&languageBox, SIGNAL(currentIndexChanged(int)), this, SLOT(languageBoxChanged(int))); - connect(&pixmapCacheEdit, SIGNAL(valueChanged(int)), &settings, SLOT(setPixmapCacheSize(int))); connect(&updateReleaseChannelBox, SIGNAL(currentIndexChanged(int)), &settings, SLOT(setUpdateReleaseChannel(int))); connect(&updateNotificationCheckBox, SIGNAL(stateChanged(int)), &settings, SLOT(setNotifyAboutUpdate(int))); connect(&newVersionOracleCheckBox, SIGNAL(stateChanged(int)), &settings, SLOT(setNotifyAboutNewVersion(int))); @@ -90,8 +82,6 @@ GeneralSettingsPage::GeneralSettingsPage() personalGrid->addWidget(&languageBox, 0, 1); personalGrid->addWidget(&updateReleaseChannelLabel, 1, 0); personalGrid->addWidget(&updateReleaseChannelBox, 1, 1); - personalGrid->addWidget(&pixmapCacheLabel, 2, 0); - personalGrid->addWidget(&pixmapCacheEdit, 2, 1); personalGrid->addWidget(&updateNotificationCheckBox, 3, 0, 1, 2); personalGrid->addWidget(&newVersionOracleCheckBox, 4, 0, 1, 2); personalGrid->addWidget(&showTipsOnStartup, 5, 0, 1, 2); @@ -301,7 +291,6 @@ void GeneralSettingsPage::retranslateUi() cardDatabasePathLabel.setText(tr("Card database:")); customCardDatabasePathLabel.setText(tr("Custom database directory:")); tokenDatabasePathLabel.setText(tr("Token database:")); - pixmapCacheLabel.setText(tr("Picture cache size:")); updateReleaseChannelLabel.setText(tr("Update channel")); updateNotificationCheckBox.setText(tr("Notify if a feature supported by the server is missing in my client")); newVersionOracleCheckBox.setText(tr("Automatically run Oracle when running a new version of Cockatrice")); @@ -591,12 +580,38 @@ DeckEditorSettingsPage::DeckEditorSettingsPage() messageListLayout->addWidget(messageToolBar); messageListLayout->addWidget(urlList); + // pixmap cache + pixmapCacheEdit.setMinimum(PIXMAPCACHE_SIZE_MIN); + // 2047 is the max value to avoid overflowing of QPixmapCache::setCacheLimit(int size) + pixmapCacheEdit.setMaximum(PIXMAPCACHE_SIZE_MAX); + pixmapCacheEdit.setSingleStep(64); + pixmapCacheEdit.setValue(SettingsCache::instance().getPixmapCacheSize()); + pixmapCacheEdit.setSuffix(" MB"); + + networkCacheEdit.setMinimum(NETWORK_CACHE_SIZE_MIN); + networkCacheEdit.setMaximum(NETWORK_CACHE_SIZE_MAX); + networkCacheEdit.setSingleStep(1); + networkCacheEdit.setValue(SettingsCache::instance().getNetworkCacheSizeInMB()); + networkCacheEdit.setSuffix(tr(" MB")); + + auto networkCacheLayout = new QHBoxLayout; + networkCacheLayout->addStretch(); + networkCacheLayout->addWidget(&networkCacheLabel); + networkCacheLayout->addWidget(&networkCacheEdit); + + auto pixmapCacheLayout = new QHBoxLayout; + pixmapCacheLayout->addStretch(); + pixmapCacheLayout->addWidget(&pixmapCacheLabel); + pixmapCacheLayout->addWidget(&pixmapCacheEdit); + // Top Layout lpGeneralGrid->addWidget(&picDownloadCheckBox, 0, 0); lpGeneralGrid->addWidget(&resetDownloadURLs, 0, 1); lpGeneralGrid->addLayout(messageListLayout, 1, 0, 1, 2); - lpGeneralGrid->addWidget(&urlLinkLabel, 2, 0); - lpGeneralGrid->addWidget(&clearDownloadedPicsButton, 2, 1); + lpGeneralGrid->addLayout(networkCacheLayout, 2, 0, 1, 2); + lpGeneralGrid->addLayout(pixmapCacheLayout, 3, 0, 1, 2); + lpGeneralGrid->addWidget(&urlLinkLabel, 4, 0); + lpGeneralGrid->addWidget(&clearDownloadedPicsButton, 4, 1); // Spoiler Layout lpSpoilerGrid->addWidget(&mcDownloadSpoilersCheckBox, 0, 0); @@ -611,6 +626,9 @@ DeckEditorSettingsPage::DeckEditorSettingsPage() connect(&mcDownloadSpoilersCheckBox, SIGNAL(toggled(bool)), &SettingsCache::instance(), SLOT(setDownloadSpoilerStatus(bool))); connect(&mcDownloadSpoilersCheckBox, SIGNAL(toggled(bool)), this, SLOT(setSpoilersEnabled(bool))); + connect(&pixmapCacheEdit, SIGNAL(valueChanged(int)), &SettingsCache::instance(), SLOT(setPixmapCacheSize(int))); + connect(&networkCacheEdit, SIGNAL(valueChanged(int)), &SettingsCache::instance(), + SLOT(setNetworkCacheSizeInMB(int))); mpGeneralGroupBox = new QGroupBox; mpGeneralGroupBox->setLayout(lpGeneralGrid); @@ -635,6 +653,11 @@ void DeckEditorSettingsPage::resetDownloadedURLsButtonClicked() void DeckEditorSettingsPage::clearDownloadedPicsButtonClicked() { + PictureLoader::clearNetworkCache(); + + // These are not used anymore, but we don't delete them automatically, so + // we should do it here lest we leave pictures hanging around on users' + // machines. QString picsPath = SettingsCache::instance().getPicsPath() + "/downloadedPics/"; QStringList dirs = QDir(picsPath).entryList(QDir::AllDirs | QDir::NoDotAndDotDot); bool outerSuccessRemove = true; @@ -662,6 +685,7 @@ void DeckEditorSettingsPage::clearDownloadedPicsButtonClicked() } if (outerSuccessRemove) { QMessageBox::information(this, tr("Success"), tr("Downloaded card pictures have been reset.")); + QDir(SettingsCache::instance().getPicsPath()).rmdir("downloadedPics"); } else { QMessageBox::critical(this, tr("Error"), tr("One or more downloaded card pictures could not be cleared.")); } @@ -785,6 +809,10 @@ void DeckEditorSettingsPage::retranslateUi() urlLinkLabel.setText(QString("%2").arg(WIKI_CUSTOM_PIC_URL).arg(tr("How to add a custom URL"))); clearDownloadedPicsButton.setText(tr("Delete Downloaded Images")); resetDownloadURLs.setText(tr("Reset Download URLs")); + networkCacheLabel.setText(tr("Downloaded images directory size:")); + networkCacheEdit.setToolTip(tr("On-disk cache for downloaded pictures")); + pixmapCacheLabel.setText(tr("Picture cache size:")); + pixmapCacheEdit.setToolTip(tr("In-memory cache for pictures not currently on screen")); } MessagesSettingsPage::MessagesSettingsPage() diff --git a/cockatrice/src/dlg_settings.h b/cockatrice/src/dlg_settings.h index 416def89..d6dd1718 100644 --- a/cockatrice/src/dlg_settings.h +++ b/cockatrice/src/dlg_settings.h @@ -58,7 +58,6 @@ private: QLineEdit *tokenDatabasePathEdit; QPushButton *resetAllPathsButton; QLabel *allPathsResetLabel; - QSpinBox pixmapCacheEdit; QGroupBox *personalGroupBox; QGroupBox *pathsGroupBox; QComboBox languageBox; @@ -66,7 +65,6 @@ private: QCheckBox newVersionOracleCheckBox; QComboBox updateReleaseChannelBox; QLabel languageLabel; - QLabel pixmapCacheLabel; QLabel deckPathLabel; QLabel replaysPathLabel; QLabel picsPathLabel; @@ -168,6 +166,10 @@ private: QLabel infoOnSpoilersLabel; QPushButton *mpSpoilerPathButton; QPushButton *updateNowButton; + QLabel networkCacheLabel; + QSpinBox networkCacheEdit; + QSpinBox pixmapCacheEdit; + QLabel pixmapCacheLabel; }; class MessagesSettingsPage : public AbstractSettingsPage diff --git a/cockatrice/src/pictureloader.cpp b/cockatrice/src/pictureloader.cpp index 966e9c30..4ca0d528 100644 --- a/cockatrice/src/pictureloader.cpp +++ b/cockatrice/src/pictureloader.cpp @@ -13,6 +13,7 @@ #include #include #include +#include #include #include #include @@ -116,6 +117,21 @@ PictureLoaderWorker::PictureLoaderWorker() connect(&SettingsCache::instance(), SIGNAL(picDownloadChanged()), this, SLOT(picDownloadChanged())); networkManager = new QNetworkAccessManager(this); + // We need a timeout to ensure requests don't hang indefinitely in case of + // cache corruption, see related Qt bug: https://bugreports.qt.io/browse/QTBUG-111397 + // Use Qt's default timeout (30s, as of 2023-02-22) +#if (QT_VERSION >= QT_VERSION_CHECK(5, 15, 0)) + networkManager->setTransferTimeout(); +#endif + auto cache = new QNetworkDiskCache(this); + cache->setCacheDirectory(SettingsCache::instance().getNetworkCachePath()); + // Note: the settings is in MB, but QNetworkDiskCache uses bytes + connect(&SettingsCache::instance(), &SettingsCache::networkCacheSizeChanged, cache, + [cache](int newSizeInMB) { 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); connect(networkManager, SIGNAL(finished(QNetworkReply *)), this, SLOT(picDownloadFinished(QNetworkReply *))); pictureLoaderThread = new QThread; @@ -149,37 +165,19 @@ void PictureLoaderWorker::processLoadQueue() QString cardName = cardBeingLoaded.getCard()->getName(); QString correctedCardName = cardBeingLoaded.getCard()->getCorrectedName(); - qDebug() << "PictureLoader: [card: " << cardName << " set: " << setName << "]: Trying to load picture"; + qDebug().nospace() << "PictureLoader: [card: " << cardName << " set: " << setName + << "]: Trying to load picture"; if (cardImageExistsOnDisk(setName, correctedCardName)) { continue; } - if (picDownload) { - qDebug() << "PictureLoader: [card: " << cardName << " set: " << setName - << "]: Picture not found on disk, trying to download"; - cardsToDownload.append(cardBeingLoaded); - cardBeingLoaded.clear(); - if (!downloadRunning) { - startNextPicDownload(); - } - } else { - if (cardBeingLoaded.nextSet()) { - qDebug() << "PictureLoader: [card: " << cardName << " set: " << setName - << "]: Picture NOT found and download disabled, moving to next " - "set (new set: " - << setName << " card: " << cardName << ")"; - mutex.lock(); - loadQueue.prepend(cardBeingLoaded); - cardBeingLoaded.clear(); - mutex.unlock(); - } else { - qDebug() << "PictureLoader: [card: " << cardName << " set: " << setName - << "]: Picture NOT found, download disabled, no more sets to " - "try: BAILING OUT (old set: " - << setName << " card: " << cardName << ")"; - imageLoaded(cardBeingLoaded.getCard(), QImage()); - } + qDebug().nospace() << "PictureLoader: [card: " << cardName << " set: " << setName + << "]: No custom picture, trying to download"; + cardsToDownload.append(cardBeingLoaded); + cardBeingLoaded.clear(); + if (!downloadRunning) { + startNextPicDownload(); } } } @@ -206,6 +204,8 @@ bool PictureLoaderWorker::cardImageExistsOnDisk(QString &setName, QString &corre if (!setName.isEmpty()) { picsPaths << picsPath + "/" + setName + "/" + correctedCardname + // We no longer store downloaded images there, but don't just ignore + // stuff that old versions have put there. << picsPath + "/downloadedPics/" + setName + "/" + correctedCardname; } @@ -215,22 +215,22 @@ bool PictureLoaderWorker::cardImageExistsOnDisk(QString &setName, QString &corre for (const auto &picsPath : picsPaths) { imgReader.setFileName(picsPath); if (imgReader.read(&image)) { - qDebug() << "PictureLoader: [card: " << correctedCardname << " set: " << setName - << "]: Picture found on disk."; + qDebug().nospace() << "PictureLoader: [card: " << correctedCardname << " set: " << setName + << "]: Picture found on disk."; imageLoaded(cardBeingLoaded.getCard(), image); return true; } imgReader.setFileName(picsPath + ".full"); if (imgReader.read(&image)) { - qDebug() << "PictureLoader: [card: " << correctedCardname << " set: " << setName - << "]: Picture.full found on disk."; + qDebug().nospace() << "PictureLoader: [card: " << correctedCardname << " set: " << setName + << "]: Picture.full found on disk."; imageLoaded(cardBeingLoaded.getCard(), image); return true; } imgReader.setFileName(picsPath + ".xlhq"); if (imgReader.read(&image)) { - qDebug() << "PictureLoader: [card: " << correctedCardname << " set: " << setName - << "]: Picture.xlhq found on disk."; + qDebug().nospace() << "PictureLoader: [card: " << correctedCardname << " set: " << setName + << "]: Picture.xlhq found on disk."; imageLoaded(cardBeingLoaded.getCard(), image); return true; } @@ -385,11 +385,10 @@ void PictureLoaderWorker::startNextPicDownload() picDownloadFailed(); } else { QUrl url(picUrl); - QNetworkRequest req(url); - qDebug() << "PictureLoader: [card: " << cardBeingDownloaded.getCard()->getCorrectedName() - << " set: " << cardBeingDownloaded.getSetName() - << "]: Trying to download picture from url:" << url.toDisplayString(); - networkManager->get(req); + qDebug().nospace() << "PictureLoader: [card: " << cardBeingDownloaded.getCard()->getCorrectedName() + << " set: " << cardBeingDownloaded.getSetName() << "]: Trying to fetch picture from url " + << url.toDisplayString(); + makeRequest(url); } } @@ -404,10 +403,10 @@ void PictureLoaderWorker::picDownloadFailed() loadQueue.prepend(cardBeingDownloaded); mutex.unlock(); } else { - qDebug() << "PictureLoader: [card: " << cardBeingDownloaded.getCard()->getCorrectedName() - << " set: " << cardBeingDownloaded.getSetName() - << "]: Picture NOT found, download failed, no more url combinations " - "to try: BAILING OUT"; + qDebug().nospace() << "PictureLoader: [card: " << cardBeingDownloaded.getCard()->getCorrectedName() + << " set: " << cardBeingDownloaded.getSetName() << "]: Picture NOT found, " + << (picDownload ? "download failed" : "downloads disabled") + << ", no more url combinations to try: BAILING OUT"; imageLoaded(cardBeingDownloaded.getCard(), QImage()); cardBeingDownloaded.clear(); } @@ -420,20 +419,53 @@ bool PictureLoaderWorker::imageIsBlackListed(const QByteArray &picData) return md5Blacklist.contains(md5sum); } +QNetworkReply *PictureLoaderWorker::makeRequest(const QUrl &url) +{ + QNetworkRequest req(url); + if (!picDownload) { + req.setAttribute(QNetworkRequest::CacheLoadControlAttribute, QNetworkRequest::AlwaysCache); + } + return networkManager->get(req); +} + void PictureLoaderWorker::picDownloadFinished(QNetworkReply *reply) { + bool isFromCache = reply->attribute(QNetworkRequest::SourceIsFromCacheAttribute).toBool(); + if (reply->error()) { - qDebug() << "PictureLoader: [card: " << cardBeingDownloaded.getCard()->getName() - << " set: " << cardBeingDownloaded.getSetName() << "]: Download failed:" << reply->errorString(); + if (isFromCache) { + qDebug().nospace() << "PictureLoader: [card: " << cardBeingDownloaded.getCard()->getName() + << " set: " << cardBeingDownloaded.getSetName() + << "]: Removing corrupted cache file for url " << reply->url().toDisplayString() + << " and retrying (" << reply->errorString() << ")"; + + networkManager->cache()->remove(reply->url()); + + makeRequest(reply->url()); + } else { + qDebug().nospace() << "PictureLoader: [card: " << cardBeingDownloaded.getCard()->getName() + << " set: " << cardBeingDownloaded.getSetName() + << "]: " << (picDownload ? "Download" : "Cache search") << " failed for url " + << reply->url().toDisplayString() << " (" << reply->errorString() << ")"; + + picDownloadFailed(); + startNextPicDownload(); + } + + reply->deleteLater(); + return; } + // List of status codes from https://doc.qt.io/qt-6/qnetworkreply.html#redirected int statusCode = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt(); - if (statusCode == 301 || statusCode == 302) { - QUrl redirectUrl = reply->attribute(QNetworkRequest::RedirectionTargetAttribute).toUrl(); - QNetworkRequest req(redirectUrl); - qDebug() << "PictureLoader: [card: " << cardBeingDownloaded.getCard()->getName() - << " set: " << cardBeingDownloaded.getSetName() << "]: following redirect:" << req.url().toString(); - networkManager->get(req); + if (statusCode == 301 || statusCode == 302 || statusCode == 303 || statusCode == 305 || statusCode == 307 || + statusCode == 308) { + QUrl redirectUrl = reply->header(QNetworkRequest::LocationHeader).toUrl(); + qDebug().nospace() << "PictureLoader: [card: " << cardBeingDownloaded.getCard()->getName() + << " set: " << cardBeingDownloaded.getSetName() << "]: following " + << (isFromCache ? "cached redirect" : "redirect") << " to " << redirectUrl.toDisplayString(); + makeRequest(redirectUrl); + reply->deleteLater(); return; } @@ -441,10 +473,10 @@ void PictureLoaderWorker::picDownloadFinished(QNetworkReply *reply) const QByteArray &picData = reply->peek(reply->size()); if (imageIsBlackListed(picData)) { - qDebug() << "PictureLoader: [card: " << cardBeingDownloaded.getCard()->getName() - << " set: " << cardBeingDownloaded.getSetName() - << "]:Picture downloaded, but blacklisted, will consider it as " - "not found"; + qDebug().nospace() << "PictureLoader: [card: " << cardBeingDownloaded.getCard()->getName() + << " set: " << cardBeingDownloaded.getSetName() + << "]: Picture found, but blacklisted, will consider it as not found"; + picDownloadFailed(); reply->deleteLater(); startNextPicDownload(); @@ -456,40 +488,19 @@ void PictureLoaderWorker::picDownloadFinished(QNetworkReply *reply) QImageReader imgReader; imgReader.setDecideFormatFromContent(true); imgReader.setDevice(reply); - // the format is determined prior to reading the QImageReader data into a QImage object, as that wipes the - // QImageReader buffer - QString extension = "." + imgReader.format(); - if (extension == ".jpeg") { - extension = ".jpg"; - } if (imgReader.read(&testImage)) { - QString setName = cardBeingDownloaded.getSetName(); - if (!setName.isEmpty()) { - if (!QDir().mkpath(picsPath + "/downloadedPics/" + setName)) { - qDebug() << "PictureLoader: [card: " << cardBeingDownloaded.getCard()->getName() - << " set: " << cardBeingDownloaded.getSetName() - << "]: " << picsPath + "/downloadedPics/" + setName + " could not be created."; - return; - } - - QFile newPic(picsPath + "/downloadedPics/" + setName + "/" + - cardBeingDownloaded.getCard()->getCorrectedName() + extension); - if (!newPic.open(QIODevice::WriteOnly)) { - return; - } - newPic.write(picData); - newPic.close(); - } - imageLoaded(cardBeingDownloaded.getCard(), testImage); - qDebug() << "PictureLoader: [card: " << cardBeingDownloaded.getCard()->getName() - << " set: " << cardBeingDownloaded.getSetName() << "]: Image successfully downloaded from " - << reply->request().url().toDisplayString(); + qDebug().nospace() << "PictureLoader: [card: " << cardBeingDownloaded.getCard()->getName() + << " set: " << cardBeingDownloaded.getSetName() << "]: Image successfully " + << (isFromCache ? "loaded from cached" : "downloaded from") << " url " + << reply->url().toDisplayString(); } else { - qDebug() << "PictureLoader: [card: " << cardBeingDownloaded.getCard()->getName() - << " set: " << cardBeingDownloaded.getSetName() << "]: Possible picture at " - << reply->request().url().toDisplayString() << " could not be loaded"; + qDebug().nospace() << "PictureLoader: [card: " << cardBeingDownloaded.getCard()->getName() + << " set: " << cardBeingDownloaded.getSetName() << "]: Possible " + << (isFromCache ? "cached" : "downloaded") << " picture at " + << reply->url().toDisplayString() << " could not be loaded"; + picDownloadFailed(); } @@ -533,6 +544,11 @@ void PictureLoaderWorker::picsPathChanged() customPicsPath = SettingsCache::instance().getCustomPicsPath(); } +void PictureLoaderWorker::clearNetworkCache() +{ + networkManager->cache()->clear(); +} + PictureLoader::PictureLoader() : QObject(nullptr) { worker = new PictureLoaderWorker; @@ -613,6 +629,11 @@ void PictureLoader::clearPixmapCache() QPixmapCache::clear(); } +void PictureLoader::clearNetworkCache() +{ + getInstance().worker->clearNetworkCache(); +} + void PictureLoader::cacheCardPixmaps(QList cards) { QPixmap tmp; diff --git a/cockatrice/src/pictureloader.h b/cockatrice/src/pictureloader.h index f085ecde..65eafaea 100644 --- a/cockatrice/src/pictureloader.h +++ b/cockatrice/src/pictureloader.h @@ -73,6 +73,7 @@ public: ~PictureLoaderWorker() override; void enqueueImageLoad(CardInfoPtr card); + void clearNetworkCache(); private: static QStringList md5Blacklist; @@ -87,8 +88,9 @@ private: PictureToLoad cardBeingDownloaded; bool picDownload, downloadRunning, loadQueueRunning; void startNextPicDownload(); - bool cardImageExistsOnDisk(QString &, QString &); + bool cardImageExistsOnDisk(QString &setName, QString &correctedCardName); bool imageIsBlackListed(const QByteArray &); + QNetworkReply *makeRequest(const QUrl &url); private slots: void picDownloadFinished(QNetworkReply *reply); void picDownloadFailed(); @@ -97,6 +99,7 @@ private slots: void picsPathChanged(); public slots: void processLoadQueue(); + signals: void startLoadQueue(); void imageLoaded(CardInfoPtr card, const QImage &image); @@ -127,9 +130,14 @@ public: static void clearPixmapCache(CardInfoPtr card); static void clearPixmapCache(); static void cacheCardPixmaps(QList cards); + +public slots: + static void clearNetworkCache(); + private slots: void picDownloadChanged(); void picsPathChanged(); + public slots: void imageLoaded(CardInfoPtr card, const QImage &image); }; diff --git a/cockatrice/src/settingscache.cpp b/cockatrice/src/settingscache.cpp index 8e95fe4b..696cc7b7 100644 --- a/cockatrice/src/settingscache.cpp +++ b/cockatrice/src/settingscache.cpp @@ -26,6 +26,19 @@ QString SettingsCache::getSettingsPath() return getDataPath() + "/settings/"; } +QString SettingsCache::getCachePath() const +{ + if (isPortableBuild) + return qApp->applicationDirPath() + "/cache"; + else + return QStandardPaths::writableLocation(QStandardPaths::CacheLocation); +} + +QString SettingsCache::getNetworkCachePath() const +{ + return getCachePath() + "/downloaded/"; +} + void SettingsCache::translateLegacySettings() { if (isPortableBuild) @@ -206,6 +219,8 @@ SettingsCache::SettingsCache() if (pixmapCacheSize < PIXMAPCACHE_SIZE_MIN || pixmapCacheSize > PIXMAPCACHE_SIZE_MAX) pixmapCacheSize = PIXMAPCACHE_SIZE_DEFAULT; + networkCacheSize = settings->value("personal/networkCacheSize", NETWORK_CACHE_SIZE_DEFAULT).toInt(); + picDownload = settings->value("personal/picturedownload", true).toBool(); mainWindowGeometry = settings->value("interface/main_window_geometry").toByteArray(); @@ -609,6 +624,13 @@ void SettingsCache::setPixmapCacheSize(const int _pixmapCacheSize) emit pixmapCacheSizeChanged(pixmapCacheSize); } +void SettingsCache::setNetworkCacheSizeInMB(const int _networkCacheSize) +{ + networkCacheSize = _networkCacheSize; + settings->setValue("personal/networkCacheSize", networkCacheSize); + emit networkCacheSizeChanged(networkCacheSize); +} + void SettingsCache::setClientID(const QString &_clientID) { clientID = _clientID; diff --git a/cockatrice/src/settingscache.h b/cockatrice/src/settingscache.h index a12a1023..01d6aafc 100644 --- a/cockatrice/src/settingscache.h +++ b/cockatrice/src/settingscache.h @@ -20,6 +20,11 @@ class ReleaseChannel; #define PIXMAPCACHE_SIZE_MIN 64 #define PIXMAPCACHE_SIZE_MAX 2047 +// In MB +constexpr int NETWORK_CACHE_SIZE_DEFAULT = 1024 * 4; // 4 GB +constexpr int NETWORK_CACHE_SIZE_MIN = 1; // 1 MB +constexpr int NETWORK_CACHE_SIZE_MAX = 1024 * 1024; // 1 TB + #define DEFAULT_LANG_NAME "English" #define CLIENT_INFO_NOT_SET "notset" @@ -46,6 +51,7 @@ signals: void ignoreUnregisteredUsersChanged(); void ignoreUnregisteredUserMessagesChanged(); void pixmapCacheSizeChanged(int newSizeInMBs); + void networkCacheSizeChanged(int newSizeInMBs); void masterVolumeChanged(int value); void chatMentionCompleterChanged(); void downloadSpoilerTimeIndexChanged(); @@ -106,6 +112,7 @@ private: QString knownMissingFeatures; bool useTearOffMenus; int pixmapCacheSize; + int networkCacheSize; bool scaleCards; bool showMessagePopups; bool showMentionPopups; @@ -137,6 +144,8 @@ public: SettingsCache(); QString getDataPath(); QString getSettingsPath(); + QString getCachePath() const; + QString getNetworkCachePath() const; const QByteArray &getMainWindowGeometry() const { return mainWindowGeometry; @@ -330,6 +339,10 @@ public: { return pixmapCacheSize; } + int getNetworkCacheSizeInMB() const + { + return networkCacheSize; + } bool getScaleCards() const { return scaleCards; @@ -520,6 +533,7 @@ public slots: void setIgnoreUnregisteredUsers(int _ignoreUnregisteredUsers); void setIgnoreUnregisteredUserMessages(int _ignoreUnregisteredUserMessages); void setPixmapCacheSize(const int _pixmapCacheSize); + void setNetworkCacheSizeInMB(const int _networkCacheSize); void setCardScaling(const int _scaleCards); void setShowMessagePopups(const int _showMessagePopups); void setShowMentionPopups(const int _showMentionPopups); diff --git a/dbconverter/src/mocks.cpp b/dbconverter/src/mocks.cpp index 999da190..867a406c 100644 --- a/dbconverter/src/mocks.cpp +++ b/dbconverter/src/mocks.cpp @@ -202,6 +202,9 @@ void SettingsCache::setTokenDialogGeometry(const QByteArray & /* _tokenDialogGeo void SettingsCache::setPixmapCacheSize(const int /* _pixmapCacheSize */) { } +void SettingsCache::setNetworkCacheSizeInMB(const int /* _networkCacheSize */) +{ +} void SettingsCache::setClientID(const QString & /* _clientID */) { } diff --git a/tests/carddatabase/mocks.cpp b/tests/carddatabase/mocks.cpp index c780574f..b78a17b3 100644 --- a/tests/carddatabase/mocks.cpp +++ b/tests/carddatabase/mocks.cpp @@ -206,6 +206,9 @@ void SettingsCache::setTokenDialogGeometry(const QByteArray & /* _tokenDialogGeo void SettingsCache::setPixmapCacheSize(const int /* _pixmapCacheSize */) { } +void SettingsCache::setNetworkCacheSizeInMB(const int /* _networkCacheSize */) +{ +} void SettingsCache::setClientID(const QString & /* _clientID */) { }