Merge pull request #498 from ctrlaltca/pixmap_memory_2nd_attempt

Pixmap memory, 2nd attempt
This commit is contained in:
Gavin Bisesi 2015-01-07 15:41:20 -05:00
commit 621d33638f
11 changed files with 113 additions and 74 deletions

View file

@ -90,15 +90,11 @@ void AbstractCardItem::paintPicture(QPainter *painter, const QSizeF &translatedS
qreal scaleFactor = translatedSize.width() / boundingRect().width(); qreal scaleFactor = translatedSize.width() / boundingRect().width();
CardInfo *imageSource = facedown ? db->getCard() : info; CardInfo *imageSource = facedown ? db->getCard() : info;
QPixmap *translatedPixmap = imageSource->getPixmap(translatedSize.toSize()); QPixmap translatedPixmap;
imageSource->getPixmap(translatedSize.toSize(), translatedPixmap);
painter->save(); painter->save();
QColor bgColor = Qt::transparent; QColor bgColor = Qt::transparent;
if (translatedPixmap) { if (translatedPixmap.isNull()) {
painter->save();
transformPainter(painter, translatedSize, angle);
painter->drawPixmap(QPointF(0, 0), *translatedPixmap);
painter->restore();
} else {
QString colorStr; QString colorStr;
if (!color.isEmpty()) if (!color.isEmpty())
colorStr = color; colorStr = color;
@ -121,6 +117,11 @@ void AbstractCardItem::paintPicture(QPainter *painter, const QSizeF &translatedS
bgColor = QColor(250, 190, 30); bgColor = QColor(250, 190, 30);
else else
bgColor = QColor(230, 230, 230); bgColor = QColor(230, 230, 230);
} else {
painter->save();
transformPainter(painter, translatedSize, angle);
painter->drawPixmap(QPointF(0, 0), translatedPixmap);
painter->restore();
} }
painter->setBrush(bgColor); painter->setBrush(bgColor);
QPen pen(Qt::black); QPen pen(Qt::black);
@ -128,7 +129,7 @@ void AbstractCardItem::paintPicture(QPainter *painter, const QSizeF &translatedS
painter->setPen(pen); painter->setPen(pen);
painter->drawRect(QRectF(1, 1, CARD_WIDTH - 2, CARD_HEIGHT - 2)); painter->drawRect(QRectF(1, 1, CARD_WIDTH - 2, CARD_HEIGHT - 2));
if (!translatedPixmap || settingsCache->getDisplayCardNames() || facedown) { if (translatedPixmap.isNull() || settingsCache->getDisplayCardNames() || facedown) {
painter->save(); painter->save();
transformPainter(painter, translatedSize, angle); transformPainter(painter, translatedSize, angle);
painter->setPen(Qt::white); painter->setPen(Qt::white);

View file

@ -390,9 +390,10 @@ CardInfo::CardInfo(CardDatabase *_db,
customPicURLsHq(_customPicURLsHq), customPicURLsHq(_customPicURLsHq),
muIds(_muIds), muIds(_muIds),
cipt(_cipt), cipt(_cipt),
tableRow(_tableRow), tableRow(_tableRow)
pixmap(NULL)
{ {
pixmapCacheKey = QLatin1String("card_") + name;
for (int i = 0; i < sets.size(); i++) for (int i = 0; i < sets.size(); i++)
sets[i]->append(this); sets[i]->append(this);
} }
@ -446,72 +447,67 @@ void CardInfo::addToSet(CardSet *set)
sets << set; sets << set;
} }
QPixmap *CardInfo::loadPixmap() void CardInfo::loadPixmap(QPixmap &pixmap)
{ {
if (pixmap) if(QPixmapCache::find(pixmapCacheKey, &pixmap))
return pixmap; return;
pixmap = new QPixmap();
pixmap = QPixmap();
if (getName().isEmpty()) { if (getName().isEmpty()) {
pixmap->load(settingsCache->getCardBackPicturePath()); pixmap.load(settingsCache->getCardBackPicturePath());
return pixmap; return;
} }
db->loadImage(this); db->loadImage(this);
return pixmap;
} }
void CardInfo::imageLoaded(const QImage &image) void CardInfo::imageLoaded(const QImage &image)
{ {
if (!image.isNull()) { if (!image.isNull()) {
*pixmap = QPixmap::fromImage(image); QPixmapCache::insert(pixmapCacheKey, QPixmap::fromImage(image));
emit pixmapUpdated(); emit pixmapUpdated();
} }
} }
QPixmap *CardInfo::getPixmap(QSize size) void CardInfo::getPixmap(QSize size, QPixmap &pixmap)
{ {
QPixmap *cachedPixmap = scaledPixmapCache.value(size.width()); QString key = QLatin1String("card_") + name + QLatin1Char('_') + QString::number(size.width());
if (cachedPixmap) if(QPixmapCache::find(key, &pixmap))
return cachedPixmap; return;
QPixmap *bigPixmap = loadPixmap();
QPixmap *result; QPixmap bigPixmap;
if (bigPixmap->isNull()) { loadPixmap(bigPixmap);
if (!getName().isEmpty()) if (bigPixmap.isNull()) {
return 0; if (!getName().isEmpty()) {
else { pixmap = QPixmap(); // null
result = new QPixmap(size); return;
result->fill(Qt::transparent); } else {
pixmap = QPixmap(size);
pixmap.fill(Qt::transparent);
QSvgRenderer svg(QString(":/back.svg")); QSvgRenderer svg(QString(":/back.svg"));
QPainter painter(result); QPainter painter(&pixmap);
svg.render(&painter, QRectF(0, 0, size.width(), size.height())); svg.render(&painter, QRectF(0, 0, size.width(), size.height()));
} }
} else } else {
result = new QPixmap(bigPixmap->scaled(size, Qt::IgnoreAspectRatio, Qt::SmoothTransformation)); pixmap = bigPixmap.scaled(size, Qt::IgnoreAspectRatio, Qt::SmoothTransformation);
scaledPixmapCache.insert(size.width(), result); }
return result; QPixmapCache::insert(key, pixmap);
} }
void CardInfo::clearPixmapCache() void CardInfo::clearPixmapCache()
{ {
if (pixmap) { qDebug() << "Deleting pixmap for" << name;
qDebug() << "Deleting pixmap for" << name; QPixmapCache::remove(pixmapCacheKey);
delete pixmap;
pixmap = 0;
QMapIterator<int, QPixmap *> i(scaledPixmapCache);
while (i.hasNext()) {
i.next();
qDebug() << " Deleting cached pixmap for width" << i.key();
delete i.value();
}
scaledPixmapCache.clear();
}
} }
void CardInfo::clearPixmapCacheMiss() void CardInfo::clearPixmapCacheMiss()
{ {
if (!pixmap) QPixmap pixmap;
if(!QPixmapCache::find(pixmapCacheKey, &pixmap))
return; return;
if (pixmap->isNull())
if (pixmap.isNull())
clearPixmapCache(); clearPixmapCache();
} }
@ -519,8 +515,9 @@ void CardInfo::updatePixmapCache()
{ {
qDebug() << "Updating pixmap cache for" << name; qDebug() << "Updating pixmap cache for" << name;
clearPixmapCache(); clearPixmapCache();
loadPixmap(); QPixmap tmp;
loadPixmap(tmp);
emit pixmapUpdated(); emit pixmapUpdated();
} }
@ -609,7 +606,8 @@ CardDatabase::CardDatabase(QObject *parent)
pictureLoaderThread->start(QThread::LowPriority); pictureLoaderThread->start(QThread::LowPriority);
noCard = new CardInfo(this); 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())); connect(settingsCache, SIGNAL(cardBackPicturePathChanged()), noCard, SLOT(updatePixmapCache()));
} }
@ -954,8 +952,9 @@ QStringList CardDatabase::getAllMainCardTypes() const
void CardDatabase::cacheCardPixmaps(const QStringList &cardNames) void CardDatabase::cacheCardPixmaps(const QStringList &cardNames)
{ {
QPixmap tmp;
for (int i = 0; i < cardNames.size(); ++i) for (int i = 0; i < cardNames.size(); ++i)
getCard(cardNames[i])->loadPixmap(); getCard(cardNames[i])->loadPixmap(tmp);
} }
void CardDatabase::loadImage(CardInfo *card) void CardDatabase::loadImage(CardInfo *card)

View file

@ -12,6 +12,7 @@
#include <QThread> #include <QThread>
#include <QMutex> #include <QMutex>
#include <QWaitCondition> #include <QWaitCondition>
#include <QPixmapCache>
class CardDatabase; class CardDatabase;
class CardInfo; class CardInfo;
@ -119,8 +120,7 @@ private:
MuidMap muIds; MuidMap muIds;
bool cipt; bool cipt;
int tableRow; int tableRow;
QPixmap *pixmap; QString pixmapCacheKey;
QMap<int, QPixmap *> scaledPixmapCache;
public: public:
CardInfo(CardDatabase *_db, CardInfo(CardDatabase *_db,
const QString &_name = QString(), const QString &_name = QString(),
@ -165,8 +165,8 @@ public:
void setCustomPicURLHq(const QString &_set, const QString &_customPicURL) { customPicURLsHq.insert(_set, _customPicURL); } 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 setMuId(const QString &_set, const int &_muId) { muIds.insert(_set, _muId); }
void addToSet(CardSet *set); void addToSet(CardSet *set);
QPixmap *loadPixmap(); void loadPixmap(QPixmap &pixmap);
QPixmap *getPixmap(QSize size); void getPixmap(QSize size, QPixmap &pixmap);
void clearPixmapCache(); void clearPixmapCache();
void clearPixmapCacheMiss(); void clearPixmapCacheMiss();
void imageLoaded(const QImage &image); void imageLoaded(const QImage &image);

View file

@ -41,13 +41,14 @@ void CardInfoPicture::updatePixmap()
return; return;
} }
QPixmap *resizedPixmap = info->getPixmap(QSize(pixmapWidth, pixmapWidth * aspectRatio)); QPixmap resizedPixmap;
if (resizedPixmap) { info->getPixmap(QSize(pixmapWidth, pixmapWidth * aspectRatio), resizedPixmap);
setNoPicture(false);
this->setPixmap(*resizedPixmap); if (resizedPixmap.isNull()) {
}
else {
setNoPicture(true); 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);
} }

View file

@ -188,11 +188,12 @@ void CardInfoWidget::updatePixmap()
if (pixmapWidth == 0) if (pixmapWidth == 0)
return; return;
QPixmap *resizedPixmap = info->getPixmap(QSize(pixmapWidth, pixmapWidth * aspectRatio)); QPixmap resizedPixmap;
if (resizedPixmap) info->getPixmap(QSize(pixmapWidth, pixmapWidth * aspectRatio), resizedPixmap);
cardPicture->setPixmap(*resizedPixmap);
else if (resizedPixmap.isNull())
cardPicture->setPixmap(*(getCard()->getPixmap(QSize(pixmapWidth, pixmapWidth * aspectRatio)))); getCard()->getPixmap(QSize(pixmapWidth, pixmapWidth * aspectRatio), resizedPixmap);
cardPicture->setPixmap(resizedPixmap);
} }
void CardInfoWidget::retranslateUi() void CardInfoWidget::retranslateUi()

View file

@ -50,16 +50,27 @@ GeneralSettingsPage::GeneralSettingsPage()
picDownloadHqCheckBox = new QCheckBox; picDownloadHqCheckBox = new QCheckBox;
picDownloadHqCheckBox->setChecked(settingsCache->getPicDownloadHq()); 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(languageBox, SIGNAL(currentIndexChanged(int)), this, SLOT(languageBoxChanged(int)));
connect(picDownloadCheckBox, SIGNAL(stateChanged(int)), settingsCache, SLOT(setPicDownload(int))); connect(picDownloadCheckBox, SIGNAL(stateChanged(int)), settingsCache, SLOT(setPicDownload(int)));
connect(picDownloadHqCheckBox, SIGNAL(stateChanged(int)), settingsCache, SLOT(setPicDownloadHq(int))); connect(picDownloadHqCheckBox, SIGNAL(stateChanged(int)), settingsCache, SLOT(setPicDownloadHq(int)));
connect(pixmapCacheEdit, SIGNAL(valueChanged(int)), settingsCache, SLOT(setPixmapCacheSize(int)));
QGridLayout *personalGrid = new QGridLayout; QGridLayout *personalGrid = new QGridLayout;
personalGrid->addWidget(languageLabel, 0, 0); personalGrid->addWidget(languageLabel, 0, 0);
personalGrid->addWidget(languageBox, 0, 1); personalGrid->addWidget(languageBox, 0, 1);
personalGrid->addWidget(picDownloadCheckBox, 1, 0, 1, 2); personalGrid->addWidget(pixmapCacheLabel, 1, 0, 1, 1);
personalGrid->addWidget(picDownloadHqCheckBox, 2, 0, 1, 2); personalGrid->addWidget(pixmapCacheEdit, 1, 1, 1, 1);
personalGrid->addWidget(clearDownloadedPicsButton, 3, 0, 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 = new QGroupBox;
personalGroupBox->setLayout(personalGrid); personalGroupBox->setLayout(personalGrid);
@ -227,6 +238,7 @@ void GeneralSettingsPage::retranslateUi()
picsPathLabel->setText(tr("Pictures directory:")); picsPathLabel->setText(tr("Pictures directory:"));
cardDatabasePathLabel->setText(tr("Card database:")); cardDatabasePathLabel->setText(tr("Card database:"));
tokenDatabasePathLabel->setText(tr("Token database:")); tokenDatabasePathLabel->setText(tr("Token database:"));
pixmapCacheLabel->setText(tr("Picture cache size:"));
clearDownloadedPicsButton->setText(tr("Reset/Clear Downloaded Pictures")); clearDownloadedPicsButton->setText(tr("Reset/Clear Downloaded Pictures"));
} }

View file

@ -16,6 +16,7 @@ class QLabel;
class QCloseEvent; class QCloseEvent;
class QSpinBox; class QSpinBox;
class QRadioButton; class QRadioButton;
class QSpinBox;
class AbstractSettingsPage : public QWidget { class AbstractSettingsPage : public QWidget {
public: public:
@ -39,11 +40,12 @@ private:
QStringList findQmFiles(); QStringList findQmFiles();
QString languageName(const QString &qmFile); QString languageName(const QString &qmFile);
QLineEdit *deckPathEdit, *replaysPathEdit, *picsPathEdit, *cardDatabasePathEdit, *tokenDatabasePathEdit; QLineEdit *deckPathEdit, *replaysPathEdit, *picsPathEdit, *cardDatabasePathEdit, *tokenDatabasePathEdit;
QSpinBox *pixmapCacheEdit;
QGroupBox *personalGroupBox, *pathsGroupBox; QGroupBox *personalGroupBox, *pathsGroupBox;
QComboBox *languageBox; QComboBox *languageBox;
QCheckBox *picDownloadCheckBox; QCheckBox *picDownloadCheckBox;
QCheckBox *picDownloadHqCheckBox; QCheckBox *picDownloadHqCheckBox;
QLabel *languageLabel, *deckPathLabel, *replaysPathLabel, *picsPathLabel, *cardDatabasePathLabel, *tokenDatabasePathLabel; QLabel *languageLabel, *deckPathLabel, *replaysPathLabel, *picsPathLabel, *cardDatabasePathLabel, *tokenDatabasePathLabel, *pixmapCacheLabel;
QPushButton *clearDownloadedPicsButton; QPushButton *clearDownloadedPicsButton;
}; };

View file

@ -23,6 +23,7 @@ SettingsCache::SettingsCache()
picDownload = settings->value("personal/picturedownload", true).toBool(); picDownload = settings->value("personal/picturedownload", true).toBool();
picDownloadHq = settings->value("personal/picturedownloadhq", false).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(); picUrl = settings->value("personal/picUrl", PIC_URL_DEFAULT).toString();
picUrlHq = settings->value("personal/picUrlHq", PIC_URL_HQ_DEFAULT).toString(); picUrlHq = settings->value("personal/picUrlHq", PIC_URL_HQ_DEFAULT).toString();
picUrlFallback = settings->value("personal/picUrlFallback", PIC_URL_FALLBACK).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); 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) void SettingsCache::copyPath(const QString &src, const QString &dst)
{ {
// test source && return if inexistent // test source && return if inexistent

View file

@ -7,6 +7,8 @@
#define PIC_URL_FALLBACK "http://mtgimage.com/set/!setcode!/!name!.jpg" #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_DEFAULT "http://mtgimage.com/multiverseid/!cardid!.jpg"
#define PIC_URL_HQ_FALLBACK "http://mtgimage.com/set/!setcode!/!name!.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; class QSettings;
@ -32,6 +34,7 @@ signals:
void soundPathChanged(); void soundPathChanged();
void priceTagFeatureChanged(int enabled); void priceTagFeatureChanged(int enabled);
void ignoreUnregisteredUsersChanged(); void ignoreUnregisteredUsersChanged();
void pixmapCacheSizeChanged(int newSizeInMBs);
private: private:
QSettings *settings; QSettings *settings;
@ -62,6 +65,7 @@ private:
QString picUrlFallback; QString picUrlFallback;
QString picUrlHqFallback; QString picUrlHqFallback;
bool attemptAutoConnect; bool attemptAutoConnect;
int pixmapCacheSize;
public: public:
SettingsCache(); SettingsCache();
const QByteArray &getMainWindowGeometry() const { return mainWindowGeometry; } const QByteArray &getMainWindowGeometry() const { return mainWindowGeometry; }
@ -101,6 +105,7 @@ public:
QString getPicUrlHqFallback() const { return picUrlHqFallback; } QString getPicUrlHqFallback() const { return picUrlHqFallback; }
void copyPath(const QString &src, const QString &dst); void copyPath(const QString &src, const QString &dst);
bool getAutoConnect() const { return attemptAutoConnect; } bool getAutoConnect() const { return attemptAutoConnect; }
int getPixmapCacheSize() const { return pixmapCacheSize; }
public slots: public slots:
void setMainWindowGeometry(const QByteArray &_mainWindowGeometry); void setMainWindowGeometry(const QByteArray &_mainWindowGeometry);
void setLang(const QString &_lang); void setLang(const QString &_lang);
@ -138,6 +143,7 @@ public slots:
void setPicUrlFallback(const QString &_picUrlFallback); void setPicUrlFallback(const QString &_picUrlFallback);
void setPicUrlHqFallback(const QString &_picUrlHqFallback); void setPicUrlHqFallback(const QString &_picUrlHqFallback);
void setAutoConnect(const bool &_autoConnect); void setAutoConnect(const bool &_autoConnect);
void setPixmapCacheSize(const int _pixmapCacheSize);
}; };
extern SettingsCache *settingsCache; extern SettingsCache *settingsCache;

View file

@ -362,7 +362,8 @@ void MainWindow::createMenus()
MainWindow::MainWindow(QWidget *parent) MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent), localServer(0), bHasActivated(false) : QMainWindow(parent), localServer(0), bHasActivated(false)
{ {
QPixmapCache::setCacheLimit(200000); connect(settingsCache, SIGNAL(pixmapCacheSizeChanged(int)), this, SLOT(pixmapCacheSizeChanged(int)));
pixmapCacheSizeChanged(settingsCache->getPixmapCacheSize());
client = new RemoteClient; client = new RemoteClient;
connect(client, SIGNAL(connectionClosedEventReceived(const Event_ConnectionClosed &)), this, SLOT(processConnectionClosedEvent(const Event_ConnectionClosed &))); 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); QMainWindow::changeEvent(event);
} }
void MainWindow::pixmapCacheSizeChanged(int newSizeInMBs)
{
//qDebug() << "Setting pixmap cache size to " << value << " MBs";
// translate MBs to KBs
QPixmapCache::setCacheLimit(newSizeInMBs * 1024);
}

View file

@ -44,6 +44,7 @@ private slots:
void protocolVersionMismatch(int localVersion, int remoteVersion); void protocolVersionMismatch(int localVersion, int remoteVersion);
void userInfoReceived(const ServerInfo_User &userInfo); void userInfoReceived(const ServerInfo_User &userInfo);
void localGameEnded(); void localGameEnded();
void pixmapCacheSizeChanged(int newSizeInMBs);
void actConnect(); void actConnect();
void actDisconnect(); void actDisconnect();