diff --git a/core/libs/database/models/imagethumbnailmodel.cpp b/core/libs/database/models/imagethumbnailmodel.cpp index cf630e81a8..e602f4a300 100644 --- a/core/libs/database/models/imagethumbnailmodel.cpp +++ b/core/libs/database/models/imagethumbnailmodel.cpp @@ -1,323 +1,333 @@ /* ============================================================ * * This file is a part of digiKam project * http://www.digikam.org * * Date : 2009-03-05 * Description : Qt item model for database entries with support for thumbnail loading * * Copyright (C) 2009-2011 by Marcel Wiesweg * Copyright (C) 2011-2018 by Gilles Caulier * * This program is free software; you can redistribute it * and/or modify it under the terms of the GNU General * Public License as published by the Free Software Foundation; * either version 2, or (at your option) * any later version. * * This program 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 General Public License for more details. * * ============================================================ */ #include "imagethumbnailmodel.h" // Qt includes #include // Local includes #include "digikam_debug.h" #include "thumbnailloadthread.h" #include "digikam_export.h" #include "digikam_globals.h" namespace Digikam { -class ImageThumbnailModel::ImageThumbnailModelPriv +class ImageThumbnailModel::Private { public: - ImageThumbnailModelPriv() : - thread(0), + explicit Private() + : thread(0), preloadThread(0), thumbSize(0), lastGlobalThumbSize(0), preloadThumbSize(0), emitDataChanged(true) { staticListContainingThumbnailRole << ImageModel::ThumbnailRole; } ThumbnailLoadThread* thread; ThumbnailLoadThread* preloadThread; ThumbnailSize thumbSize; ThumbnailSize lastGlobalThumbSize; ThumbnailSize preloadThumbSize; QRect detailRect; QVector staticListContainingThumbnailRole; bool emitDataChanged; int preloadThumbnailSize() const { if (preloadThumbSize.size()) { return preloadThumbSize.size(); } return thumbSize.size(); } }; -ImageThumbnailModel::ImageThumbnailModel(QObject* parent) - : ImageModel(parent), d(new ImageThumbnailModelPriv) +ImageThumbnailModel::ImageThumbnailModel(QObject* const parent) + : ImageModel(parent), + d(new Private) { setKeepsFilePathCache(true); } ImageThumbnailModel::~ImageThumbnailModel() { delete d->preloadThread; delete d; } -void ImageThumbnailModel::setThumbnailLoadThread(ThumbnailLoadThread* thread) +void ImageThumbnailModel::setThumbnailLoadThread(ThumbnailLoadThread* const thread) { d->thread = thread; connect(d->thread, SIGNAL(signalThumbnailLoaded(LoadingDescription,QPixmap)), this, SLOT(slotThumbnailLoaded(LoadingDescription,QPixmap))); } ThumbnailLoadThread* ImageThumbnailModel::thumbnailLoadThread() const { return d->thread; } ThumbnailSize ImageThumbnailModel::thumbnailSize() const { return d->thumbSize; } void ImageThumbnailModel::setThumbnailSize(const ThumbnailSize& size) { d->lastGlobalThumbSize = size; d->thumbSize = size; } void ImageThumbnailModel::setPreloadThumbnailSize(const ThumbnailSize& size) { d->preloadThumbSize = size; } void ImageThumbnailModel::setEmitDataChanged(bool emitSignal) { d->emitDataChanged = emitSignal; } void ImageThumbnailModel::setPreloadThumbnails(bool preload) { if (preload) { if (!d->preloadThread) { d->preloadThread = new ThumbnailLoadThread; d->preloadThread->setPixmapRequested(false); d->preloadThread->setPriority(QThread::LowestPriority); } connect(this, SIGNAL(allRefreshingFinished()), this, SLOT(preloadAllThumbnails())); } else { delete d->preloadThread; d->preloadThread = 0; + disconnect(this, SIGNAL(allRefreshingFinished()), this, SLOT(preloadAllThumbnails())); } } void ImageThumbnailModel::prepareThumbnails(const QList& indexesToPrepare) { prepareThumbnails(indexesToPrepare, d->thumbSize); } void ImageThumbnailModel::prepareThumbnails(const QList& indexesToPrepare, const ThumbnailSize& thumbSize) { if (!d->thread) { return; } QList ids; + foreach(const QModelIndex& index, indexesToPrepare) { ids << imageInfoRef(index).thumbnailIdentifier(); } + d->thread->findGroup(ids, thumbSize.size()); } void ImageThumbnailModel::preloadThumbnails(const QList& infos) { if (!d->preloadThread) { return; } QList ids; + foreach(const ImageInfo& info, infos) { ids << info.thumbnailIdentifier(); } + d->preloadThread->pregenerateGroup(ids, d->preloadThumbnailSize()); } void ImageThumbnailModel::preloadThumbnails(const QList& indexesToPreload) { if (!d->preloadThread) { return; } QList ids; + foreach(const QModelIndex& index, indexesToPreload) { ids << imageInfoRef(index).thumbnailIdentifier(); } + d->preloadThread->stopAllTasks(); d->preloadThread->pregenerateGroup(ids, d->preloadThumbnailSize()); } void ImageThumbnailModel::preloadAllThumbnails() { preloadThumbnails(imageInfos()); } void ImageThumbnailModel::imageInfosCleared() { if (d->preloadThread) { d->preloadThread->stopAllTasks(); } } QVariant ImageThumbnailModel::data(const QModelIndex& index, int role) const { if (role == ThumbnailRole && d->thread && index.isValid()) { QPixmap thumbnail; ImageInfo info = imageInfo(index); QString path = info.filePath(); if (info.isNull()) { return QVariant(QVariant::Pixmap); } if (!d->detailRect.isNull()) { if (d->thread->find(info.thumbnailIdentifier(), d->detailRect, thumbnail, d->thumbSize.size())) { return thumbnail; } } else { if (d->thread->find(info.thumbnailIdentifier(), thumbnail, d->thumbSize.size())) { return thumbnail; } } return QVariant(QVariant::Pixmap); } return ImageModel::data(index, role); } bool ImageThumbnailModel::setData(const QModelIndex& index, const QVariant& value, int role) { if (role == ThumbnailRole) { switch (value.type()) { case QVariant::Invalid: d->thumbSize = d->lastGlobalThumbSize; d->detailRect = QRect(); break; case QVariant::Int: if (value.isNull()) { d->thumbSize = d->lastGlobalThumbSize; } else { d->thumbSize = ThumbnailSize(value.toInt()); } break; case QVariant::Rect: if (value.isNull()) { d->detailRect = QRect(); } else { d->detailRect = value.toRect(); } break; default: break; } } return ImageModel::setData(index, value, role); } void ImageThumbnailModel::slotThumbnailLoaded(const LoadingDescription& loadingDescription, const QPixmap& thumb) { if (thumb.isNull()) { return; } // In case of multiple occurrence, we currently do not know which thumbnail is this. Signal change on all. QModelIndexList indexes; ThumbnailIdentifier thumbId = loadingDescription.thumbnailIdentifier(); + if (thumbId.filePath.isEmpty()) { indexes = indexesForImageId(thumbId.id); } else { indexes = indexesForPath(thumbId.filePath); } + foreach(const QModelIndex& index, indexes) { if (thumb.isNull()) { emit thumbnailFailed(index, loadingDescription.previewParameters.size); } else { emit thumbnailAvailable(index, loadingDescription.previewParameters.size); if (d->emitDataChanged) { emit dataChanged(index, index, d->staticListContainingThumbnailRole); } } } } } // namespace Digikam diff --git a/core/libs/database/models/imagethumbnailmodel.h b/core/libs/database/models/imagethumbnailmodel.h index 9b130b363f..5b7bff320a 100644 --- a/core/libs/database/models/imagethumbnailmodel.h +++ b/core/libs/database/models/imagethumbnailmodel.h @@ -1,140 +1,140 @@ /* ============================================================ * * This file is a part of digiKam project * http://www.digikam.org * * Date : 2009-03-05 * Description : Qt item model for database entries with support for thumbnail loading * * Copyright (C) 2009-2011 by Marcel Wiesweg * Copyright (C) 2011 by Gilles Caulier * * This program is free software; you can redistribute it * and/or modify it under the terms of the GNU General * Public License as published by the Free Software Foundation; * either version 2, or (at your option) * any later version. * * This program 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 General Public License for more details. * * ============================================================ */ #ifndef DIGIKAM_IMAGE_THUMBNAIL_MODEL_H #define DIGIKAM_IMAGE_THUMBNAIL_MODEL_H // Local includes #include "imagemodel.h" #include "thumbnailsize.h" #include "digikam_export.h" namespace Digikam { class LoadingDescription; class ThumbnailLoadThread; class DIGIKAM_DATABASE_EXPORT ImageThumbnailModel : public ImageModel { Q_OBJECT public: /** * An ImageModel that supports thumbnail loading. * You need to set a ThumbnailLoadThread to enable thumbnail loading. * Adjust the thumbnail size to your needs. * Note that setKeepsFilePathCache is enabled per default. */ - explicit ImageThumbnailModel(QObject* parent); + explicit ImageThumbnailModel(QObject* const parent); ~ImageThumbnailModel(); /** Enable thumbnail loading and set the thread that shall be used. * The thumbnail size of this thread will be adjusted. */ - void setThumbnailLoadThread(ThumbnailLoadThread* thread); + void setThumbnailLoadThread(ThumbnailLoadThread* const thread); ThumbnailLoadThread* thumbnailLoadThread() const; /// Set the thumbnail size to use void setThumbnailSize(const ThumbnailSize& thumbSize); /// If you want to fix a size for preloading, do it here. void setPreloadThumbnailSize(const ThumbnailSize& thumbSize); void setExifRotate(bool rotate); /** * Enable emitting dataChanged() when a thumbnail becomes available. * The thumbnailAvailable() signal will be emitted in any case. * Default is true. */ void setEmitDataChanged(bool emitSignal); /** * Enable preloading of thumbnails: * If preloading is enabled, for every entry in the model a thumbnail generation is started. * Default: false. */ void setPreloadThumbnails(bool preload); ThumbnailSize thumbnailSize() const; /** * Handles the ThumbnailRole. * If the pixmap is available, returns it in the QVariant. * If it still needs to be loaded, returns a null QVariant and emits * thumbnailAvailable() as soon as it is available. */ virtual QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const; /** * You can override the current thumbnail size by giving an integer value for ThumbnailRole. * Set a null QVariant to use the thumbnail size set by setThumbnailSize() again. * The index given here is ignored for this purpose. */ virtual bool setData(const QModelIndex& index, const QVariant& value, int role = Qt::DisplayRole); public Q_SLOTS: /** Prepare the thumbnail loading for the given indexes */ void prepareThumbnails(const QList& indexesToPrepare); void prepareThumbnails(const QList& indexesToPrepare, const ThumbnailSize& thumbSize); /** * Preload thumbnail for the given infos resp. indexes. * Note: Use setPreloadThumbnails to automatically preload all entries in the model. * Note: This only ensures thumbnail generation. It is not guaranteed that pixmaps * are stored in the cache. For thumbnails that are expect to be drawn immediately, * include them in prepareThumbnails(). * Note: Stops preloading of previously added thumbnails. */ void preloadThumbnails(const QList&); void preloadThumbnails(const QList&); void preloadAllThumbnails(); Q_SIGNALS: void thumbnailAvailable(const QModelIndex& index, int requestedSize); void thumbnailFailed(const QModelIndex& index, int requestedSize); protected: virtual void imageInfosCleared(); protected Q_SLOTS: void slotThumbnailLoaded(const LoadingDescription& loadingDescription, const QPixmap& thumb); private: - class ImageThumbnailModelPriv; - ImageThumbnailModelPriv* const d; + class Private; + Private* const d; }; } // namespace Digikam #endif // DIGIKAM_IMAGE_THUMBNAIL_MODEL_H