File indexing completed on 2024-12-08 03:39:27

0001 /*  This file is part of the KDE project.
0002     SPDX-FileCopyrightText: 2010 Michael Pyne <mpyne@kde.org>
0003 
0004     SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
0005 */
0006 
0007 #include "klocalimagecacheimpl.h"
0008 
0009 #include <QBuffer>
0010 #include <QCache>
0011 #include <QCoreApplication>
0012 #include <QDateTime>
0013 
0014 #include <QImage>
0015 #include <QPixmap>
0016 
0017 /**
0018  * This is a QObject subclass so we can catch the signal that the application is about
0019  * to close and properly release any QPixmaps we have cached.
0020  */
0021 class KLocalImageCacheImplementationPrivate : public QObject
0022 {
0023     Q_OBJECT
0024 
0025 public:
0026     KLocalImageCacheImplementationPrivate(QObject *parent = nullptr)
0027         : QObject(parent)
0028         , timestamp(QDateTime::currentDateTime())
0029     {
0030         QObject::connect(QCoreApplication::instance(), &QCoreApplication::aboutToQuit, this, &KLocalImageCacheImplementationPrivate::clearPixmaps);
0031     }
0032 
0033     /**
0034      * Inserts a pixmap into the pixmap cache if the pixmap cache is enabled, with
0035      * weighting based on image size and bit depth.
0036      */
0037     bool insertPixmap(const QString &key, QPixmap *pixmap)
0038     {
0039         if (enablePixmapCaching && pixmap && !pixmap->isNull()) {
0040             // "cost" parameter is based on both image size and depth to make cost
0041             // based on size in bytes instead of area on-screen.
0042             return pixmapCache.insert(key, pixmap, pixmap->width() * pixmap->height() * pixmap->depth() / 8);
0043         }
0044 
0045         return false;
0046     }
0047 
0048 public Q_SLOTS:
0049     void clearPixmaps()
0050     {
0051         pixmapCache.clear();
0052     }
0053 
0054 public:
0055     QDateTime timestamp;
0056 
0057     /**
0058      * This is used to cache pixmaps as they are inserted, instead of always
0059      * converting to image data and storing that in shared memory.
0060      */
0061     QCache<QString, QPixmap> pixmapCache;
0062 
0063     bool enablePixmapCaching = true;
0064 };
0065 
0066 KLocalImageCacheImplementation::KLocalImageCacheImplementation(unsigned defaultCacheSize)
0067     : d(new KLocalImageCacheImplementationPrivate)
0068 {
0069     // Use at least 16 KiB for the pixmap cache
0070     d->pixmapCache.setMaxCost(qMax(defaultCacheSize / 8, (unsigned int)16384));
0071 }
0072 
0073 KLocalImageCacheImplementation::~KLocalImageCacheImplementation() = default;
0074 
0075 void KLocalImageCacheImplementation::updateModifiedTime()
0076 {
0077     d->timestamp = QDateTime::currentDateTime();
0078 }
0079 
0080 QByteArray KLocalImageCacheImplementation::serializeImage(const QImage &image) const
0081 {
0082     QBuffer buffer;
0083     buffer.open(QBuffer::WriteOnly);
0084     image.save(&buffer, "PNG");
0085     return buffer.buffer();
0086 }
0087 
0088 bool KLocalImageCacheImplementation::insertLocalPixmap(const QString &key, const QPixmap &pixmap) const
0089 {
0090     return d->insertPixmap(key, new QPixmap(pixmap));
0091 }
0092 
0093 bool KLocalImageCacheImplementation::findLocalPixmap(const QString &key, QPixmap *destination) const
0094 {
0095     if (d->enablePixmapCaching) {
0096         QPixmap *cachedPixmap = d->pixmapCache.object(key);
0097         if (cachedPixmap) {
0098             if (destination) {
0099                 *destination = *cachedPixmap;
0100             }
0101 
0102             return true;
0103         }
0104     }
0105 
0106     return false;
0107 }
0108 
0109 void KLocalImageCacheImplementation::clearLocalCache()
0110 {
0111     d->pixmapCache.clear();
0112 }
0113 
0114 QDateTime KLocalImageCacheImplementation::lastModifiedTime() const
0115 {
0116     return d->timestamp;
0117 }
0118 
0119 bool KLocalImageCacheImplementation::pixmapCaching() const
0120 {
0121     return d->enablePixmapCaching;
0122 }
0123 
0124 void KLocalImageCacheImplementation::setPixmapCaching(bool enable)
0125 {
0126     if (enable != d->enablePixmapCaching) {
0127         d->enablePixmapCaching = enable;
0128         if (!enable) {
0129             d->pixmapCache.clear();
0130         }
0131     }
0132 }
0133 
0134 int KLocalImageCacheImplementation::pixmapCacheLimit() const
0135 {
0136     return d->pixmapCache.maxCost();
0137 }
0138 
0139 void KLocalImageCacheImplementation::setPixmapCacheLimit(int size)
0140 {
0141     d->pixmapCache.setMaxCost(size);
0142 }
0143 
0144 #include "klocalimagecacheimpl.moc"