mirror of
https://bitbucket.org/smil3y/kdelibs.git
synced 2025-02-24 10:52:49 +00:00
200 lines
5.1 KiB
C++
200 lines
5.1 KiB
C++
/*
|
|
* This file is part of the KDE project.
|
|
* Copyright © 2010 Michael Pyne <mpyne@kde.org>
|
|
*
|
|
* This library is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU Library General Public
|
|
* License version 2 as published by the Free Software Foundation.
|
|
*
|
|
* This library is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
* Library General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU Library General Public License
|
|
* along with this library; see the file COPYING.LIB. If not, write to
|
|
* the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
|
* Boston, MA 02110-1301, USA.
|
|
*/
|
|
|
|
#include "kimagecache.h"
|
|
|
|
#include <QtGui/QPixmap>
|
|
#include <QtGui/QImage>
|
|
#include <QtCore/QBuffer>
|
|
#include <QtCore/QCache>
|
|
#include <QtCore/QCoreApplication>
|
|
|
|
#include <time.h>
|
|
|
|
/**
|
|
* This is a QObject subclass so we can catch the signal that the application is about
|
|
* to close and properly release any QPixmaps we have cached.
|
|
*/
|
|
class KImageCache::Private : public QObject
|
|
{
|
|
Q_OBJECT
|
|
|
|
public:
|
|
Private(QObject *parent = 0)
|
|
: QObject(parent)
|
|
, timestamp(::time(0))
|
|
, enablePixmapCaching(true)
|
|
{
|
|
QObject::connect(QCoreApplication::instance(), SIGNAL(aboutToQuit()),
|
|
this, SLOT(clearPixmaps()));
|
|
}
|
|
|
|
/**
|
|
* Inserts a pixmap into the pixmap cache if the pixmap cache is enabled, with
|
|
* weighting based on image size and bit depth.
|
|
*/
|
|
bool insertPixmap(const QString &key, QPixmap *pixmap)
|
|
{
|
|
if (enablePixmapCaching && pixmap && !pixmap->isNull()) {
|
|
// "cost" parameter is based on both image size and depth to make cost
|
|
// based on size in bytes instead of area on-screen.
|
|
return pixmapCache.insert(key, pixmap,
|
|
pixmap->width() * pixmap->height() * pixmap->depth() / 8);
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
public slots:
|
|
void clearPixmaps()
|
|
{
|
|
pixmapCache.clear();
|
|
}
|
|
|
|
public:
|
|
time_t timestamp;
|
|
|
|
/**
|
|
* This is used to cache pixmaps as they are inserted, instead of always
|
|
* converting to image data and storing that in shared memory.
|
|
*/
|
|
QCache<QString, QPixmap> pixmapCache;
|
|
|
|
bool enablePixmapCaching;
|
|
};
|
|
|
|
KImageCache::KImageCache(const QString &cacheName,
|
|
unsigned defaultCacheSize,
|
|
unsigned expectedItemSize)
|
|
: KSharedDataCache(cacheName, defaultCacheSize, expectedItemSize)
|
|
, d(new Private)
|
|
{
|
|
// Use at least 16 KiB for the pixmap cache
|
|
d->pixmapCache.setMaxCost(qMax(defaultCacheSize / 8, (unsigned int) 16384));
|
|
}
|
|
|
|
KImageCache::~KImageCache()
|
|
{
|
|
delete d;
|
|
}
|
|
|
|
bool KImageCache::insertImage(const QString &key, const QImage &image)
|
|
{
|
|
QBuffer buffer;
|
|
buffer.open(QBuffer::WriteOnly);
|
|
image.save(&buffer, "PNG");
|
|
|
|
if (this->insert(key, buffer.buffer())) {
|
|
d->timestamp = ::time(0);
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
bool KImageCache::insertPixmap(const QString &key, const QPixmap &pixmap)
|
|
{
|
|
d->insertPixmap(key, new QPixmap(pixmap));
|
|
|
|
// One thing to think about is only inserting things to the shared cache
|
|
// that are frequently used. But that would require tracking the use count
|
|
// in our local cache too, which I think is probably too much work.
|
|
|
|
return insertImage(key, pixmap.toImage());
|
|
}
|
|
|
|
bool KImageCache::findImage(const QString &key, QImage *destination) const
|
|
{
|
|
QByteArray cachedData;
|
|
if (!this->find(key, &cachedData) || cachedData.isNull()) {
|
|
return false;
|
|
}
|
|
|
|
if (destination) {
|
|
destination->loadFromData(cachedData, "PNG");
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
bool KImageCache::findPixmap(const QString &key, QPixmap *destination) const
|
|
{
|
|
if (d->enablePixmapCaching) {
|
|
QPixmap *cachedPixmap = d->pixmapCache.object(key);
|
|
if (cachedPixmap) {
|
|
if (destination) {
|
|
*destination = *cachedPixmap;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
}
|
|
|
|
QByteArray cachedData;
|
|
if (!this->find(key, &cachedData) || cachedData.isNull()) {
|
|
return false;
|
|
}
|
|
|
|
if (destination) {
|
|
destination->loadFromData(cachedData, "PNG");
|
|
|
|
// Manually re-insert to pixmap cache if we'll be using this one.
|
|
d->insertPixmap(key, new QPixmap(*destination));
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
void KImageCache::clear()
|
|
{
|
|
d->pixmapCache.clear();
|
|
KSharedDataCache::clear();
|
|
}
|
|
|
|
time_t KImageCache::lastModifiedTime() const
|
|
{
|
|
return d->timestamp;
|
|
}
|
|
|
|
bool KImageCache::pixmapCaching() const
|
|
{
|
|
return d->enablePixmapCaching;
|
|
}
|
|
|
|
void KImageCache::setPixmapCaching(bool enable)
|
|
{
|
|
if (enable != d->enablePixmapCaching) {
|
|
d->enablePixmapCaching = enable;
|
|
if (!enable) {
|
|
d->pixmapCache.clear();
|
|
}
|
|
}
|
|
}
|
|
|
|
int KImageCache::pixmapCacheLimit() const
|
|
{
|
|
return d->pixmapCache.maxCost();
|
|
}
|
|
|
|
void KImageCache::setPixmapCacheLimit(int size)
|
|
{
|
|
d->pixmapCache.setMaxCost(size);
|
|
}
|
|
|
|
#include "kimagecache.moc"
|