1 /* Copyright (C) 2008 Jesper K. Pedersen <blackie@kde.org>
2 Henner Zeller <h.zeller@acm.org>
4 This program is free software; you can redistribute it and/or
5 modify it under the terms of the GNU General Public
6 License as published by the Free Software Foundation; either
7 version 2 of the License, or (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 General Public License for more details.
14 You should have received a copy of the GNU General Public License
15 along with this program; see the file COPYING. If not, write to
16 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
17 Boston, MA 02110-1301, USA.
20 #include "ThumbnailStorage.h"
28 * The default format for images. The 'ppm' format seems to be fastest to work
29 * with, so this is what we use as default.
30 * Note, that <http://jens.triq.net/thumbnail-spec/> would require to use 'png'.
32 static const char *kDefaultImageFormat
= "ppm";
34 ImageManager::FileThumbnailStorage::FileThumbnailStorage(const QString
& imageFormat
)
35 : _imageFormat(!imageFormat
.isEmpty() ? imageFormat
: QString::fromLatin1(kDefaultImageFormat
))
37 QDir
dir(QDir::homePath());
38 dir
.mkdir( QString::fromLatin1( ".thumbnails" ) );
39 dir
.cd( QString::fromLatin1( ".thumbnails" ) );
40 dir
.mkdir( QString::fromLatin1( "normal" ) );
41 dir
.mkdir( QString::fromLatin1( "large" ) );
44 QString
ImageManager::FileThumbnailStorage::keyToPath(const QString
& key
)
46 return QString::fromLatin1( "%1/.thumbnails/%2.%3" )
47 .arg(QDir::homePath()).arg(key
).arg(_imageFormat
);
50 bool ImageManager::FileThumbnailStorage::store(const QString
& key
, const QImage
& image
)
52 QString path
= keyToPath(key
);
54 /* To prevent a race condition where another thread reads data from
55 * a file that is not fully written to yet, we save the thumbnail into a
56 * temporary file. Without this fix, you'd get plenty of
57 * "libpng error: Read Error" messages when running more ImageLoader
59 QString temporary
= path
+ QString::fromLatin1(".tmp");
60 bool ok
= image
.save( temporary
, _imageFormat
.toLatin1() );
62 if (!ok
) return false;
64 /* We can't use QFile::rename() here as we really want to overwrite
65 * target file (perhaps we have a hash collision, or maybe it's
67 rename( temporary
.toLocal8Bit().constData(),
68 path
.toLocal8Bit().constData() );
71 QMutexLocker
l(&_cacheLock
);
72 _existenceCache
.insert(key
);
77 void ImageManager::FileThumbnailStorage::remove(const QString
& key
)
79 QFile::remove( keyToPath(key
) );
82 bool ImageManager::FileThumbnailStorage::retrieve(const QString
& key
, QImage
* image
)
84 QString path
= keyToPath(key
);
85 if ( QFile::exists( path
) ) {
86 return image
->load( path
, _imageFormat
.toLatin1() );
91 bool ImageManager::FileThumbnailStorage::exists(const QString
& key
)
94 QMutexLocker
l(&_cacheLock
);
95 if (_existenceCache
.contains(key
))
98 QString path
= keyToPath(key
);
99 bool exists
= QFile::exists( path
);
101 QMutexLocker
l(&_cacheLock
);
102 _existenceCache
.insert(key
);
108 #ifdef TESTING_MEMORY_THUMBNAIL_CACHING
109 ImageManager::MemoryThumbnailStorage::MemoryThumbnailStorage(const char *imageFormat
)
110 : _imageFormat(imageFormat
!= NULL
? imageFormat
: kDefaultImageFormat
)
115 bool ImageManager::MemoryThumbnailStorage::store(const QString
& key
, const QImage
& image
)
119 buffer
.open(QIODevice::WriteOnly
);
120 const char *qual
= getenv("KPA_THUMB_QUALITY"); // for testing.
121 int quality
= qual
== NULL
? -1 : atoi(qual
);
122 image
.save(&buffer
, _imageFormat
, quality
);
123 _cache
.insert(key
, ba
);
124 kDebug() << "Store '" << key
<< "'; size=" << ba
.size()/1024 << "k";
128 bool ImageManager::MemoryThumbnailStorage::retrieve(const QString
& key
, QImage
* image
)
130 ImageCache::const_iterator found
= _cache
.find(key
);
131 if (found
== _cache
.end())
133 bool ok
= image
->loadFromData(found
.value(), _imageFormat
);
134 kDebug() << "Load '" << key
<< "'; size=" << found
.value().size()/1024 << "k; ok=" << ok
;
138 bool ImageManager::MemoryThumbnailStorage::exists(const QString
& key
)
140 ImageCache::const_iterator found
= _cache
.find(key
);
141 return (found
!= _cache
.end());
144 #endif /* TESTING_MEMORY_THUMBNAIL_CACHING */