thumbnailcache.cpp Example File
mediabrowser/thumbnailcache.cpp
 
 #include "thumbnailcache.h"
 #include "thumbnailmodel.h"
 #include <QtCore/qcryptographichash.h>
 #include <QtCore/qcoreapplication.h>
 #include <QtCore/qcoreevent.h>
 #include <QtCore/qdir.h>
 #include <QtCore/qurl.h>
 #include <QtGui/qimagereader.h>
 #include <QtGui/qpixmap.h>
 #if (QT_VERSION < QT_VERSION_CHECK(4, 7, 0))
 uint qHash(const QUrl &url) { return qHash(url.toString()); }
 #endif
 class Thumbnail
 {
 public:
     Thumbnail(const QUrl &url)
         : url(url)
     {
     }
     const QUrl url;
     QPixmap pixmap;
 private:
     ThumbnailCache *cache;
 };
 class ThumbnailEvent : public QEvent
 {
 public:
     ThumbnailEvent(const QUrl &url, const QImage &image)
         : QEvent(QEvent::User)
         , url(url)
         , image(image)
     {
     }
     const QUrl url;
     const QImage image;
 };
 ThumbnailCache::ThumbnailCache(QObject *parent)
     : QThread(parent)
 #if defined(Q_OS_SYMBIAN) || defined(Q_WS_MAEMO_5) || defined(Q_WS_MAEMO_6)
     , cache(25)
 #else
     , cache(150)
 #endif
     , cancelled(false)
 {
     start(QThread::LowestPriority);
 }
 ThumbnailCache::~ThumbnailCache()
 {
     {
         QMutexLocker locker(&mutex);
         cancelled = true;
         waitCondition.wakeOne();
     }
     wait();
 }
 QPixmap ThumbnailCache::thumbnail(const QUrl &url)
 {
     QMutexLocker locker(&mutex);
     if (Thumbnail *thumbnail = cache.object(url)) {
         return thumbnail->pixmap;
     } else {
         pendingUrls.enqueue(url);
         cache.insert(url, new Thumbnail(url));
         waitCondition.wakeOne();
         return QPixmap();
     }
 }
 bool ThumbnailCache::event(QEvent *event)
 {
     if (event->type() == QEvent::User) {
         ThumbnailEvent *thumbnailEvent = static_cast<ThumbnailEvent *>(event);
         QMutexLocker locker(&mutex);
         if (Thumbnail *thumbnail = cache.object(thumbnailEvent->url)) {
             thumbnail->pixmap = QPixmap::fromImage(thumbnailEvent->image);
             locker.unlock();
             emit thumbnailReady();
         }
         return true;
     } else {
         return QThread::event(event);
     }
 }
 void ThumbnailCache::run()
 {
     QMutexLocker locker(&mutex);
     while(!cancelled) {
         if (!pendingUrls.isEmpty()) {
             const QUrl url = pendingUrls.dequeue();
             if (cache.contains(url)) {
                 locker.unlock();
                 QImage image = loadImage(url);
                 locker.relock();
                 if (!image.isNull())
                     QCoreApplication::postEvent(this, new ThumbnailEvent(url, image));
             }
         } else {
             waitCondition.wait(&mutex);
         }
     }
 }
 QImage ThumbnailCache::loadImage(const QUrl &url) const
 {
     const QString fileName = thumbnailPath(url);
     QImageReader reader(fileName);
     reader.setQuality(25);
     if (reader.supportsOption(QImageIOHandler::Size)) {
         QSize size = reader.size();
         if (!reader.supportsOption(QImageIOHandler::ScaledSize)
                 && (size.width() > 1280 || size.height() > 1280)) {
             return QImage();
         }
         if (size.width() > ThumbnailModel::thumbnailSize.width()
                 || size.height() > ThumbnailModel::thumbnailSize.height()) {
             size.scale(ThumbnailModel::thumbnailSize, Qt::KeepAspectRatio);
         }
         reader.setScaledSize(size);
     } else {
         reader.setScaledSize(ThumbnailModel::thumbnailSize);
     }
     return reader.read();
 }
 QString ThumbnailCache::thumbnailPath(const QUrl &url) const
 {
 #if defined(Q_OS_UNIX) && !(defined(Q_OS_SYMBIAN) || defined(Q_OS_MAC))
 #if defined(Q_WS_MAEMO_5)
     QString thumbnailPath = QDir::homePath()
             + QLatin1String("/.thumbnails/cropped/")
             + QCryptographicHash::hash(url.toString().toUtf8(), QCryptographicHash::Md5).toHex()
             + QLatin1String(".jpeg");
 #elif defined(Q_WS_MAEMO_6)
     QString thumbnailPath = QDir::homePath()
             + QLatin1String("/.thumbnails/grid/")
             + QCryptographicHash::hash(url.toString().toUtf8(), QCryptographicHash::Md5).toHex()
             + QLatin1String(".jpeg");
 #else
     QString thumbnailPath = QDir::homePath()
             + QLatin1String("/.thumbnails/normal/")
             + QCryptographicHash::hash(url.toEncoded(), QCryptographicHash::Md5).toHex()
             + QLatin1String(".png");
 #endif
     if (QFile::exists(thumbnailPath))
         return thumbnailPath;
 #endif
     return url.toLocalFile();
 }