1/* This file is part of the KDE project.
2 SPDX-FileCopyrightText: 2010 Michael Pyne <mpyne@kde.org>
3
4 SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
5*/
6
7#include "klocalimagecacheimpl.h"
8
9#include <QBuffer>
10#include <QCache>
11#include <QCoreApplication>
12#include <QDateTime>
13
14#include <QImage>
15#include <QPixmap>
16
17/**
18 * This is a QObject subclass so we can catch the signal that the application is about
19 * to close and properly release any QPixmaps we have cached.
20 */
21class KLocalImageCacheImplementationPrivate : public QObject
22{
23 Q_OBJECT
24
25public:
26 KLocalImageCacheImplementationPrivate(QObject *parent = nullptr)
27 : QObject(parent)
28 , timestamp(QDateTime::currentDateTime())
29 {
30 QObject::connect(sender: QCoreApplication::instance(), signal: &QCoreApplication::aboutToQuit, context: this, slot: &KLocalImageCacheImplementationPrivate::clearPixmaps);
31 }
32
33 /**
34 * Inserts a pixmap into the pixmap cache if the pixmap cache is enabled, with
35 * weighting based on image size and bit depth.
36 */
37 bool insertPixmap(const QString &key, QPixmap *pixmap)
38 {
39 if (enablePixmapCaching && pixmap && !pixmap->isNull()) {
40 // "cost" parameter is based on both image size and depth to make cost
41 // based on size in bytes instead of area on-screen.
42 return pixmapCache.insert(key, object: pixmap, cost: pixmap->width() * pixmap->height() * pixmap->depth() / 8);
43 }
44
45 return false;
46 }
47
48public Q_SLOTS:
49 void clearPixmaps()
50 {
51 pixmapCache.clear();
52 }
53
54public:
55 QDateTime timestamp;
56
57 /**
58 * This is used to cache pixmaps as they are inserted, instead of always
59 * converting to image data and storing that in shared memory.
60 */
61 QCache<QString, QPixmap> pixmapCache;
62
63 bool enablePixmapCaching = true;
64};
65
66KLocalImageCacheImplementation::KLocalImageCacheImplementation(unsigned defaultCacheSize)
67 : d(new KLocalImageCacheImplementationPrivate)
68{
69 // Use at least 16 KiB for the pixmap cache
70 d->pixmapCache.setMaxCost(qMax(a: defaultCacheSize / 8, b: (unsigned int)16384));
71}
72
73KLocalImageCacheImplementation::~KLocalImageCacheImplementation() = default;
74
75void KLocalImageCacheImplementation::updateModifiedTime()
76{
77 d->timestamp = QDateTime::currentDateTime();
78}
79
80QByteArray KLocalImageCacheImplementation::serializeImage(const QImage &image) const
81{
82 QBuffer buffer;
83 buffer.open(openMode: QBuffer::WriteOnly);
84 image.save(device: &buffer, format: "PNG");
85 return buffer.buffer();
86}
87
88bool KLocalImageCacheImplementation::insertLocalPixmap(const QString &key, const QPixmap &pixmap) const
89{
90 return d->insertPixmap(key, pixmap: new QPixmap(pixmap));
91}
92
93bool KLocalImageCacheImplementation::findLocalPixmap(const QString &key, QPixmap *destination) const
94{
95 if (d->enablePixmapCaching) {
96 QPixmap *cachedPixmap = d->pixmapCache.object(key);
97 if (cachedPixmap) {
98 if (destination) {
99 *destination = *cachedPixmap;
100 }
101
102 return true;
103 }
104 }
105
106 return false;
107}
108
109void KLocalImageCacheImplementation::clearLocalCache()
110{
111 d->pixmapCache.clear();
112}
113
114QDateTime KLocalImageCacheImplementation::lastModifiedTime() const
115{
116 return d->timestamp;
117}
118
119bool KLocalImageCacheImplementation::pixmapCaching() const
120{
121 return d->enablePixmapCaching;
122}
123
124void KLocalImageCacheImplementation::setPixmapCaching(bool enable)
125{
126 if (enable != d->enablePixmapCaching) {
127 d->enablePixmapCaching = enable;
128 if (!enable) {
129 d->pixmapCache.clear();
130 }
131 }
132}
133
134int KLocalImageCacheImplementation::pixmapCacheLimit() const
135{
136 return d->pixmapCache.maxCost();
137}
138
139void KLocalImageCacheImplementation::setPixmapCacheLimit(int size)
140{
141 d->pixmapCache.setMaxCost(size);
142}
143
144#include "klocalimagecacheimpl.moc"
145

source code of kguiaddons/src/util/klocalimagecacheimpl.cpp