diff --git a/cockatrice/src/abstractcarditem.cpp b/cockatrice/src/abstractcarditem.cpp index 26359929..97c45afa 100644 --- a/cockatrice/src/abstractcarditem.cpp +++ b/cockatrice/src/abstractcarditem.cpp @@ -90,15 +90,11 @@ void AbstractCardItem::paintPicture(QPainter *painter, const QSizeF &translatedS qreal scaleFactor = translatedSize.width() / boundingRect().width(); CardInfo *imageSource = facedown ? db->getCard() : info; - QPixmap *translatedPixmap = imageSource->getPixmap(translatedSize.toSize()); + QPixmap translatedPixmap; + imageSource->getPixmap(translatedSize.toSize(), translatedPixmap); painter->save(); QColor bgColor = Qt::transparent; - if (translatedPixmap) { - painter->save(); - transformPainter(painter, translatedSize, angle); - painter->drawPixmap(QPointF(0, 0), *translatedPixmap); - painter->restore(); - } else { + if (translatedPixmap.isNull()) { QString colorStr; if (!color.isEmpty()) colorStr = color; @@ -121,6 +117,11 @@ void AbstractCardItem::paintPicture(QPainter *painter, const QSizeF &translatedS bgColor = QColor(250, 190, 30); else bgColor = QColor(230, 230, 230); + } else { + painter->save(); + transformPainter(painter, translatedSize, angle); + painter->drawPixmap(QPointF(0, 0), translatedPixmap); + painter->restore(); } painter->setBrush(bgColor); QPen pen(Qt::black); @@ -128,7 +129,7 @@ void AbstractCardItem::paintPicture(QPainter *painter, const QSizeF &translatedS painter->setPen(pen); painter->drawRect(QRectF(1, 1, CARD_WIDTH - 2, CARD_HEIGHT - 2)); - if (!translatedPixmap || settingsCache->getDisplayCardNames() || facedown) { + if (translatedPixmap.isNull() || settingsCache->getDisplayCardNames() || facedown) { painter->save(); transformPainter(painter, translatedSize, angle); painter->setPen(Qt::white); diff --git a/cockatrice/src/carddatabase.cpp b/cockatrice/src/carddatabase.cpp index e2020dd9..3cd9f313 100644 --- a/cockatrice/src/carddatabase.cpp +++ b/cockatrice/src/carddatabase.cpp @@ -390,9 +390,10 @@ CardInfo::CardInfo(CardDatabase *_db, customPicURLsHq(_customPicURLsHq), muIds(_muIds), cipt(_cipt), - tableRow(_tableRow), - pixmap(NULL) + tableRow(_tableRow) { + pixmapCacheKey = QLatin1String("card_") + name; + for (int i = 0; i < sets.size(); i++) sets[i]->append(this); } @@ -446,72 +447,67 @@ void CardInfo::addToSet(CardSet *set) sets << set; } -QPixmap *CardInfo::loadPixmap() +void CardInfo::loadPixmap(QPixmap &pixmap) { - if (pixmap) - return pixmap; - pixmap = new QPixmap(); + if(QPixmapCache::find(pixmapCacheKey, &pixmap)) + return; + + pixmap = QPixmap(); if (getName().isEmpty()) { - pixmap->load(settingsCache->getCardBackPicturePath()); - return pixmap; + pixmap.load(settingsCache->getCardBackPicturePath()); + return; } + db->loadImage(this); - return pixmap; } void CardInfo::imageLoaded(const QImage &image) { if (!image.isNull()) { - *pixmap = QPixmap::fromImage(image); + QPixmapCache::insert(pixmapCacheKey, QPixmap::fromImage(image)); emit pixmapUpdated(); } } -QPixmap *CardInfo::getPixmap(QSize size) +void CardInfo::getPixmap(QSize size, QPixmap &pixmap) { - QPixmap *cachedPixmap = scaledPixmapCache.value(size.width()); - if (cachedPixmap) - return cachedPixmap; - QPixmap *bigPixmap = loadPixmap(); - QPixmap *result; - if (bigPixmap->isNull()) { - if (!getName().isEmpty()) - return 0; - else { - result = new QPixmap(size); - result->fill(Qt::transparent); + QString key = QLatin1String("card_") + name + QLatin1Char('_') + QString::number(size.width()); + if(QPixmapCache::find(key, &pixmap)) + return; + + QPixmap bigPixmap; + loadPixmap(bigPixmap); + if (bigPixmap.isNull()) { + if (!getName().isEmpty()) { + pixmap = QPixmap(); // null + return; + } else { + pixmap = QPixmap(size); + pixmap.fill(Qt::transparent); QSvgRenderer svg(QString(":/back.svg")); - QPainter painter(result); + QPainter painter(&pixmap); svg.render(&painter, QRectF(0, 0, size.width(), size.height())); } - } else - result = new QPixmap(bigPixmap->scaled(size, Qt::IgnoreAspectRatio, Qt::SmoothTransformation)); - scaledPixmapCache.insert(size.width(), result); - return result; + } else { + pixmap = bigPixmap.scaled(size, Qt::IgnoreAspectRatio, Qt::SmoothTransformation); + } + QPixmapCache::insert(key, pixmap); } void CardInfo::clearPixmapCache() { - if (pixmap) { - qDebug() << "Deleting pixmap for" << name; - delete pixmap; - pixmap = 0; - QMapIterator i(scaledPixmapCache); - while (i.hasNext()) { - i.next(); - qDebug() << " Deleting cached pixmap for width" << i.key(); - delete i.value(); - } - scaledPixmapCache.clear(); - } + qDebug() << "Deleting pixmap for" << name; + QPixmapCache::remove(pixmapCacheKey); } void CardInfo::clearPixmapCacheMiss() { - if (!pixmap) + QPixmap pixmap; + if(!QPixmapCache::find(pixmapCacheKey, &pixmap)) return; - if (pixmap->isNull()) + + if (pixmap.isNull()) clearPixmapCache(); } @@ -519,8 +515,9 @@ void CardInfo::updatePixmapCache() { qDebug() << "Updating pixmap cache for" << name; clearPixmapCache(); - loadPixmap(); - + QPixmap tmp; + loadPixmap(tmp); + emit pixmapUpdated(); } @@ -609,7 +606,8 @@ CardDatabase::CardDatabase(QObject *parent) pictureLoaderThread->start(QThread::LowPriority); noCard = new CardInfo(this); - noCard->loadPixmap(); // cache pixmap for card back + QPixmap tmp; + noCard->loadPixmap(tmp); // cache pixmap for card back connect(settingsCache, SIGNAL(cardBackPicturePathChanged()), noCard, SLOT(updatePixmapCache())); } @@ -954,8 +952,9 @@ QStringList CardDatabase::getAllMainCardTypes() const void CardDatabase::cacheCardPixmaps(const QStringList &cardNames) { + QPixmap tmp; for (int i = 0; i < cardNames.size(); ++i) - getCard(cardNames[i])->loadPixmap(); + getCard(cardNames[i])->loadPixmap(tmp); } void CardDatabase::loadImage(CardInfo *card) diff --git a/cockatrice/src/carddatabase.h b/cockatrice/src/carddatabase.h index e9b693f8..bbd0260f 100644 --- a/cockatrice/src/carddatabase.h +++ b/cockatrice/src/carddatabase.h @@ -12,6 +12,7 @@ #include #include #include +#include class CardDatabase; class CardInfo; @@ -119,8 +120,7 @@ private: MuidMap muIds; bool cipt; int tableRow; - QPixmap *pixmap; - QMap scaledPixmapCache; + QString pixmapCacheKey; public: CardInfo(CardDatabase *_db, const QString &_name = QString(), @@ -165,8 +165,8 @@ public: void setCustomPicURLHq(const QString &_set, const QString &_customPicURL) { customPicURLsHq.insert(_set, _customPicURL); } void setMuId(const QString &_set, const int &_muId) { muIds.insert(_set, _muId); } void addToSet(CardSet *set); - QPixmap *loadPixmap(); - QPixmap *getPixmap(QSize size); + void loadPixmap(QPixmap &pixmap); + void getPixmap(QSize size, QPixmap &pixmap); void clearPixmapCache(); void clearPixmapCacheMiss(); void imageLoaded(const QImage &image); diff --git a/cockatrice/src/cardinfopicture.cpp b/cockatrice/src/cardinfopicture.cpp index 8b560958..165fb295 100644 --- a/cockatrice/src/cardinfopicture.cpp +++ b/cockatrice/src/cardinfopicture.cpp @@ -41,13 +41,14 @@ void CardInfoPicture::updatePixmap() return; } - QPixmap *resizedPixmap = info->getPixmap(QSize(pixmapWidth, pixmapWidth * aspectRatio)); - if (resizedPixmap) { - setNoPicture(false); - this->setPixmap(*resizedPixmap); - } - else { + QPixmap resizedPixmap; + info->getPixmap(QSize(pixmapWidth, pixmapWidth * aspectRatio), resizedPixmap); + + if (resizedPixmap.isNull()) { setNoPicture(true); - this->setPixmap(*(db->getCard()->getPixmap(QSize(pixmapWidth, pixmapWidth * aspectRatio)))); + db->getCard()->getPixmap(QSize(pixmapWidth, pixmapWidth * aspectRatio), resizedPixmap); + } else { + setNoPicture(false); } + this->setPixmap(resizedPixmap); } diff --git a/cockatrice/src/cardinfowidget.cpp b/cockatrice/src/cardinfowidget.cpp index 21b00a13..57d59552 100644 --- a/cockatrice/src/cardinfowidget.cpp +++ b/cockatrice/src/cardinfowidget.cpp @@ -188,11 +188,12 @@ void CardInfoWidget::updatePixmap() if (pixmapWidth == 0) return; - QPixmap *resizedPixmap = info->getPixmap(QSize(pixmapWidth, pixmapWidth * aspectRatio)); - if (resizedPixmap) - cardPicture->setPixmap(*resizedPixmap); - else - cardPicture->setPixmap(*(getCard()->getPixmap(QSize(pixmapWidth, pixmapWidth * aspectRatio)))); + QPixmap resizedPixmap; + info->getPixmap(QSize(pixmapWidth, pixmapWidth * aspectRatio), resizedPixmap); + + if (resizedPixmap.isNull()) + getCard()->getPixmap(QSize(pixmapWidth, pixmapWidth * aspectRatio), resizedPixmap); + cardPicture->setPixmap(resizedPixmap); } void CardInfoWidget::retranslateUi() diff --git a/cockatrice/src/dlg_settings.cpp b/cockatrice/src/dlg_settings.cpp index fb76d06b..5e7511f8 100644 --- a/cockatrice/src/dlg_settings.cpp +++ b/cockatrice/src/dlg_settings.cpp @@ -50,16 +50,27 @@ GeneralSettingsPage::GeneralSettingsPage() picDownloadHqCheckBox = new QCheckBox; picDownloadHqCheckBox->setChecked(settingsCache->getPicDownloadHq()); + pixmapCacheLabel = new QLabel; + pixmapCacheEdit = new QSpinBox; + pixmapCacheEdit->setMinimum(64); + pixmapCacheEdit->setMaximum(8192); + pixmapCacheEdit->setSingleStep(64); + pixmapCacheEdit->setValue(settingsCache->getPixmapCacheSize()); + pixmapCacheEdit->setSuffix(" MB"); + connect(languageBox, SIGNAL(currentIndexChanged(int)), this, SLOT(languageBoxChanged(int))); connect(picDownloadCheckBox, SIGNAL(stateChanged(int)), settingsCache, SLOT(setPicDownload(int))); connect(picDownloadHqCheckBox, SIGNAL(stateChanged(int)), settingsCache, SLOT(setPicDownloadHq(int))); + connect(pixmapCacheEdit, SIGNAL(valueChanged(int)), settingsCache, SLOT(setPixmapCacheSize(int))); QGridLayout *personalGrid = new QGridLayout; personalGrid->addWidget(languageLabel, 0, 0); personalGrid->addWidget(languageBox, 0, 1); - personalGrid->addWidget(picDownloadCheckBox, 1, 0, 1, 2); - personalGrid->addWidget(picDownloadHqCheckBox, 2, 0, 1, 2); - personalGrid->addWidget(clearDownloadedPicsButton, 3, 0, 1, 1); + personalGrid->addWidget(pixmapCacheLabel, 1, 0, 1, 1); + personalGrid->addWidget(pixmapCacheEdit, 1, 1, 1, 1); + personalGrid->addWidget(picDownloadCheckBox, 2, 0, 1, 2); + personalGrid->addWidget(picDownloadHqCheckBox, 3, 0, 1, 2); + personalGrid->addWidget(clearDownloadedPicsButton, 4, 0, 1, 1); personalGroupBox = new QGroupBox; personalGroupBox->setLayout(personalGrid); @@ -227,6 +238,7 @@ void GeneralSettingsPage::retranslateUi() picsPathLabel->setText(tr("Pictures directory:")); cardDatabasePathLabel->setText(tr("Card database:")); tokenDatabasePathLabel->setText(tr("Token database:")); + pixmapCacheLabel->setText(tr("Picture cache size:")); clearDownloadedPicsButton->setText(tr("Reset/Clear Downloaded Pictures")); } diff --git a/cockatrice/src/dlg_settings.h b/cockatrice/src/dlg_settings.h index 842fa5f2..0383183d 100644 --- a/cockatrice/src/dlg_settings.h +++ b/cockatrice/src/dlg_settings.h @@ -16,6 +16,7 @@ class QLabel; class QCloseEvent; class QSpinBox; class QRadioButton; +class QSpinBox; class AbstractSettingsPage : public QWidget { public: @@ -39,11 +40,12 @@ private: QStringList findQmFiles(); QString languageName(const QString &qmFile); QLineEdit *deckPathEdit, *replaysPathEdit, *picsPathEdit, *cardDatabasePathEdit, *tokenDatabasePathEdit; + QSpinBox *pixmapCacheEdit; QGroupBox *personalGroupBox, *pathsGroupBox; QComboBox *languageBox; QCheckBox *picDownloadCheckBox; QCheckBox *picDownloadHqCheckBox; - QLabel *languageLabel, *deckPathLabel, *replaysPathLabel, *picsPathLabel, *cardDatabasePathLabel, *tokenDatabasePathLabel; + QLabel *languageLabel, *deckPathLabel, *replaysPathLabel, *picsPathLabel, *cardDatabasePathLabel, *tokenDatabasePathLabel, *pixmapCacheLabel; QPushButton *clearDownloadedPicsButton; }; diff --git a/cockatrice/src/settingscache.cpp b/cockatrice/src/settingscache.cpp index 8374bdb5..424b64b4 100644 --- a/cockatrice/src/settingscache.cpp +++ b/cockatrice/src/settingscache.cpp @@ -23,6 +23,7 @@ SettingsCache::SettingsCache() picDownload = settings->value("personal/picturedownload", true).toBool(); picDownloadHq = settings->value("personal/picturedownloadhq", false).toBool(); + pixmapCacheSize = settings->value("personal/pixmapCacheSize", PIXMAPCACHE_SIZE_DEFAULT).toInt(); picUrl = settings->value("personal/picUrl", PIC_URL_DEFAULT).toString(); picUrlHq = settings->value("personal/picUrlHq", PIC_URL_HQ_DEFAULT).toString(); picUrlFallback = settings->value("personal/picUrlFallback", PIC_URL_FALLBACK).toString(); @@ -289,6 +290,13 @@ void SettingsCache::setAutoConnect(const bool &_autoConnect) settings->setValue("server/auto_connect", attemptAutoConnect ? 1 : 0); } +void SettingsCache::setPixmapCacheSize(const int _pixmapCacheSize) +{ + pixmapCacheSize = _pixmapCacheSize; + settings->setValue("personal/pixmapCacheSize", pixmapCacheSize); + emit pixmapCacheSizeChanged(pixmapCacheSize); +} + void SettingsCache::copyPath(const QString &src, const QString &dst) { // test source && return if inexistent diff --git a/cockatrice/src/settingscache.h b/cockatrice/src/settingscache.h index 3b1908a9..2c9f6c89 100644 --- a/cockatrice/src/settingscache.h +++ b/cockatrice/src/settingscache.h @@ -7,6 +7,8 @@ #define PIC_URL_FALLBACK "http://mtgimage.com/set/!setcode!/!name!.jpg" #define PIC_URL_HQ_DEFAULT "http://mtgimage.com/multiverseid/!cardid!.jpg" #define PIC_URL_HQ_FALLBACK "http://mtgimage.com/set/!setcode!/!name!.jpg" +// size should be a multiple of 64 +#define PIXMAPCACHE_SIZE_DEFAULT 256 class QSettings; @@ -32,6 +34,7 @@ signals: void soundPathChanged(); void priceTagFeatureChanged(int enabled); void ignoreUnregisteredUsersChanged(); + void pixmapCacheSizeChanged(int newSizeInMBs); private: QSettings *settings; @@ -62,6 +65,7 @@ private: QString picUrlFallback; QString picUrlHqFallback; bool attemptAutoConnect; + int pixmapCacheSize; public: SettingsCache(); const QByteArray &getMainWindowGeometry() const { return mainWindowGeometry; } @@ -101,6 +105,7 @@ public: QString getPicUrlHqFallback() const { return picUrlHqFallback; } void copyPath(const QString &src, const QString &dst); bool getAutoConnect() const { return attemptAutoConnect; } + int getPixmapCacheSize() const { return pixmapCacheSize; } public slots: void setMainWindowGeometry(const QByteArray &_mainWindowGeometry); void setLang(const QString &_lang); @@ -138,6 +143,7 @@ public slots: void setPicUrlFallback(const QString &_picUrlFallback); void setPicUrlHqFallback(const QString &_picUrlHqFallback); void setAutoConnect(const bool &_autoConnect); + void setPixmapCacheSize(const int _pixmapCacheSize); }; extern SettingsCache *settingsCache; diff --git a/cockatrice/src/window_main.cpp b/cockatrice/src/window_main.cpp index 87f6a646..82f0cab1 100644 --- a/cockatrice/src/window_main.cpp +++ b/cockatrice/src/window_main.cpp @@ -362,7 +362,8 @@ void MainWindow::createMenus() MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), localServer(0), bHasActivated(false) { - QPixmapCache::setCacheLimit(200000); + connect(settingsCache, SIGNAL(pixmapCacheSizeChanged(int)), this, SLOT(pixmapCacheSizeChanged(int))); + pixmapCacheSizeChanged(settingsCache->getPixmapCacheSize()); client = new RemoteClient; connect(client, SIGNAL(connectionClosedEventReceived(const Event_ConnectionClosed &)), this, SLOT(processConnectionClosedEvent(const Event_ConnectionClosed &))); @@ -431,3 +432,10 @@ void MainWindow::changeEvent(QEvent *event) QMainWindow::changeEvent(event); } + +void MainWindow::pixmapCacheSizeChanged(int newSizeInMBs) +{ + //qDebug() << "Setting pixmap cache size to " << value << " MBs"; + // translate MBs to KBs + QPixmapCache::setCacheLimit(newSizeInMBs * 1024); +} diff --git a/cockatrice/src/window_main.h b/cockatrice/src/window_main.h index e804bbe6..8e2b48e2 100644 --- a/cockatrice/src/window_main.h +++ b/cockatrice/src/window_main.h @@ -44,6 +44,7 @@ private slots: void protocolVersionMismatch(int localVersion, int remoteVersion); void userInfoReceived(const ServerInfo_User &userInfo); void localGameEnded(); + void pixmapCacheSizeChanged(int newSizeInMBs); void actConnect(); void actDisconnect();