SVN commit 619531 by mwiesweg:
Loading of previews is now multithreaded: - integrate preview loading into the load-save framework - the PreviewLoadTask is a cut-down version of the normal SharedLoadingTask - use the same cache CCMAIL: [hidden email] M +0 -1 digikam/Makefile.am M +31 -43 digikam/imagepreviewwidget.cpp M +4 -4 digikam/imagepreviewwidget.h M +4 -0 libs/threadimageio/Makefile.am M +11 -3 libs/threadimageio/loadingcache.cpp M +24 -0 libs/threadimageio/loadingdescription.h M +1 -1 libs/threadimageio/loadsavetask.cpp M +1 -1 libs/threadimageio/loadsavetask.h M +13 -3 libs/threadimageio/loadsavethread.cpp M +40 -0 libs/threadimageio/managedloadsavethread.cpp M +1 -0 libs/threadimageio/managedloadsavethread.h A libs/threadimageio/previewloadthread.cpp [License: GPL] A libs/threadimageio/previewloadthread.h [License: GPL] A libs/threadimageio/previewtask.cpp [License: GPL] A libs/threadimageio/previewtask.h [License: GPL] --- trunk/extragear/graphics/digikam/digikam/Makefile.am #619530:619531 @@ -67,7 +67,6 @@ iconitem.cpp \ imageattributeswatch.cpp \ imageinfo.cpp \ - imagepreviewjob.cpp \ imagepreviewwidget.cpp \ imagepreviewview.cpp \ kdatetimeedit.cpp \ --- trunk/extragear/graphics/digikam/digikam/imagepreviewwidget.cpp #619530:619531 @@ -37,9 +37,9 @@ // Local includes. #include "ddebug.h" +#include "previewloadthread.h" #include "themeengine.h" #include "albumsettings.h" -#include "imagepreviewjob.h" #include "imagepreviewwidget.h" #include "imagepreviewwidget.moc" @@ -52,7 +52,7 @@ ImagePreviewWidgetPriv() { - previewJob = 0; + previewThread = 0; } QString path; @@ -60,8 +60,8 @@ QPixmap pixmap; QImage preview; - - QGuardedPtr<ImagePreviewJob> previewJob; + + PreviewLoadThread *previewThread; }; ImagePreviewWidget::ImagePreviewWidget(QWidget *parent) @@ -83,11 +83,7 @@ ImagePreviewWidget::~ImagePreviewWidget() { - if (!d->previewJob.isNull()) - { - d->previewJob->kill(); - d->previewJob = 0; - } + delete d->previewThread; delete d; } @@ -100,53 +96,43 @@ d->path = path; if (d->path.isEmpty()) - slotFailedImagePreview(KURL()); + { + d->pixmap = QPixmap(contentsRect().size()); - if (!d->previewJob.isNull()) + updatePixmap(); + update(); + unsetCursor(); + emit previewFailed(); + } + + if (!d->previewThread) { - d->previewJob->kill(); - d->previewJob = 0; + d->previewThread = new PreviewLoadThread(); + connect(d->previewThread, SIGNAL(signalPreviewLoaded(const LoadingDescription &, const QImage &)), + this, SLOT(slotGotImagePreview(const LoadingDescription &, const QImage&))); } - d->previewJob = new ImagePreviewJob(KURL(path), 1024, AlbumSettings::instance()->getExifRotate()); + d->previewThread->load(LoadingDescription(path, 1024, AlbumSettings::instance()->getExifRotate())); - connect(d->previewJob, SIGNAL(signalImagePreview(const KURL&, const QImage&)), - this, SLOT(slotGotImagePreview(const KURL&, const QImage&))); - - connect(d->previewJob, SIGNAL(signalFailed(const KURL&)), - this, SLOT(slotFailedImagePreview(const KURL&))); - emit previewStarted(); } -void ImagePreviewWidget::slotGotImagePreview(const KURL&, const QImage& preview) +void ImagePreviewWidget::slotGotImagePreview(const LoadingDescription &description, const QImage& preview) { + if (description.filePath != d->path) + return; + d->preview = preview; d->pixmap = QPixmap(contentsRect().size()); - // It is very important to kill the thumbnail job properly - // so that is frees its shared memory. Otherwise the memory - // will _never_ be freed, see b.k.o. #131277 - if (!d->previewJob.isNull()) - { - d->previewJob->kill(); - d->previewJob = 0; - } - updatePixmap(); - repaint(false); + update(); unsetCursor(); - emit previewComplete(); -} -void ImagePreviewWidget::slotFailedImagePreview(const KURL&) -{ - d->preview = QImage(); - d->pixmap = QPixmap(contentsRect().size()); - updatePixmap(); - repaint(false); - unsetCursor(); - emit previewFailed(); + if (preview.isNull()) + emit previewFailed(); + else + emit previewComplete(); } void ImagePreviewWidget::updatePixmap( void ) @@ -178,12 +164,14 @@ } else { - // There is nothing to see. - + // There is nothing to see: Empty album, or initially waiting to load preview + + /* p.setPen(QPen(ThemeEngine::instance()->textRegColor())); p.drawText(0, 0, d->pixmap.width(), d->pixmap.height(), Qt::AlignCenter|Qt::WordBreak, i18n("No item to preview in this album.")); + */ } p.end(); --- trunk/extragear/graphics/digikam/digikam/imagepreviewwidget.h #619530:619531 @@ -29,6 +29,7 @@ // Local includes #include "digikam_export.h" +#include "loadingdescription.h" class QPixmap; @@ -70,10 +71,9 @@ void wheelEvent(QWheelEvent * e); private slots: - - void slotGotImagePreview(const KURL&, const QImage& preview); - void slotFailedImagePreview(const KURL&); - + + void slotGotImagePreview(const LoadingDescription &loadingDescription, const QImage &image); + private: void updatePixmap(void); --- trunk/extragear/graphics/digikam/libs/threadimageio/Makefile.am #619530:619531 @@ -5,7 +5,9 @@ libthreadimageio_la_SOURCES = loadsavethread.cpp \ managedloadsavethread.cpp \ sharedloadsavethread.cpp \ + previewloadthread.cpp \ loadsavetask.cpp \ + previewtask.cpp \ loadingcache.cpp \ loadingcacheinterface.cpp @@ -13,5 +15,7 @@ INCLUDES = -I$(top_srcdir)/digikam/libs/dimg \ -I$(top_srcdir)/digikam/libs/dimg/loaders \ + -I$(top_srcdir)/digikam/libs/dmetadata \ + -I$(top_srcdir)/digikam/libs/dcraw \ -I$(top_srcdir)/digikam/digikam \ $(all_includes) --- trunk/extragear/graphics/digikam/libs/threadimageio/loadingcache.cpp #619530:619531 @@ -88,9 +88,17 @@ bool LoadingCache::putImage(const QString &cacheKey, DImg *img, const QString &filePath) { bool successfullyInserted; - // use size of image as cache cost - if ( d->imageCache.insert(cacheKey, img, img->numBytes()) ) + + // use size of image as cache cost, take care for wrapped preview QImages + int cost = img->numBytes(); + QVariant attribute(img->attribute("previewQImage")); + if (attribute.isValid()) { + cost = attribute.toImage().numBytes(); + } + + if ( d->imageCache.insert(cacheKey, img, cost) ) + { if (!filePath.isEmpty()) { // store file path as attribute for our own use @@ -141,7 +149,7 @@ } } -void LoadingCache::customEvent(QCustomEvent *event) +void LoadingCache::customEvent(QCustomEvent *) { // Event comes from main thread, we need to lock ourselves. CacheLock lock(this); --- trunk/extragear/graphics/digikam/libs/threadimageio/loadingdescription.h #619530:619531 @@ -34,6 +34,18 @@ { public: + class PreviewParameters + { + public: + PreviewParameters() + { + size = 0; + exifRotate = false; + } + int size; + bool exifRotate; + }; + /* An invalid LoadingDescription */ @@ -59,8 +71,20 @@ : filePath(filePath), rawDecodingSettings(settings) {}; + /* + For preview jobs: + Stores preview max size and exif rotation + */ + LoadingDescription(const QString &filePath, int size, bool exifRotate) + : filePath(filePath) + { + previewParameters.size = size; + previewParameters.exifRotate = exifRotate; + }; + QString filePath; RawDecodingSettings rawDecodingSettings; + PreviewParameters previewParameters; /* Return the cache key this description shall be stored as --- trunk/extragear/graphics/digikam/libs/threadimageio/loadsavetask.cpp #619530:619531 @@ -284,7 +284,7 @@ // set to 0, as checked in setStatus m_usedProcess = 0; } -}; +} void SharedLoadingTask::progressInfo(const DImg *, float progress) { --- trunk/extragear/graphics/digikam/libs/threadimageio/loadsavetask.h #619530:619531 @@ -284,7 +284,7 @@ virtual QObject *eventReceiver(); virtual LoadSaveThread::AccessMode accessMode(); -private: +protected: LoadSaveThread::AccessMode m_accessMode; bool m_completed; --- trunk/extragear/graphics/digikam/libs/threadimageio/loadsavethread.cpp #619530:619531 @@ -38,6 +38,8 @@ // so we do not need to store check for every option here. if (rawDecodingSettings.halfSizeColorImage) return filePath + "-halfSizeColorImage"; + else if (previewParameters.size) + return filePath + "-previewImage"; else return filePath; } @@ -51,13 +53,16 @@ keys.append(filePath); if (rawDecodingSettings.halfSizeColorImage) keys.append(filePath + "-halfSizeColorImage"); + if (previewParameters.size) + keys.append(filePath + "-previewImage"); return keys; } bool LoadingDescription::isReducedVersion() const { - // currently the only way to get a reduced, speed optimized loading - return rawDecodingSettings.halfSizeColorImage; + // return true if this loads anything but the full version + return rawDecodingSettings.halfSizeColorImage + || previewParameters.size; } bool LoadingDescription::operator==(const LoadingDescription &other) const @@ -65,7 +70,8 @@ // NOTE: If we start loading RAW files with different loading settings in parallel, // this and the next methods must be better implemented! return filePath == other.filePath && - rawDecodingSettings.halfSizeColorImage == other.rawDecodingSettings.halfSizeColorImage; + rawDecodingSettings.halfSizeColorImage == other.rawDecodingSettings.halfSizeColorImage && + previewParameters.size == other.previewParameters.size; } bool LoadingDescription::equalsIgnoreReducedVersion(const LoadingDescription &other) const @@ -79,6 +85,10 @@ ( (rawDecodingSettings.halfSizeColorImage == other.rawDecodingSettings.halfSizeColorImage) || other.rawDecodingSettings.halfSizeColorImage + ) && + ( + (previewParameters.size == other.previewParameters.size) || + other.previewParameters.size ); } --- trunk/extragear/graphics/digikam/libs/threadimageio/managedloadsavethread.cpp #619530:619531 @@ -24,6 +24,7 @@ #include "ddebug.h" #include "managedloadsavethread.h" #include "loadsavetask.h" +#include "previewtask.h" namespace Digikam { @@ -205,6 +206,45 @@ m_condVar.wakeAll(); } +void ManagedLoadSaveThread::loadPreview(LoadingDescription description) +{ + // This is similar to the LoadingPolicyFirstRemovePrevious policy with normal loading tasks. + // Preview threads typically only support preview tasks, + // so no need to differentiate with normal loading tasks. + + QMutexLocker lock(&m_mutex); + LoadingTask *loadingTask = 0; + LoadingTask *existingTask = findExistingTask(description); + + // reuse task if it exists + if (existingTask) + { + existingTask->setStatus(LoadingTask::LoadingTaskStatusLoading); + } + // stop current task + if (m_currentTask && m_currentTask != existingTask) + { + if ( (loadingTask = checkLoadingTask(m_currentTask, LoadingTaskFilterAll)) ) + loadingTask->setStatus(LoadingTask::LoadingTaskStatusStopping); + } + // remove all loading tasks + for (LoadSaveTask *task = m_todo.first(); task; task = m_todo.next()) + { + if (task != existingTask && checkLoadingTask(task, LoadingTaskFilterAll)) + { + m_todo.remove(); + m_todo.prev(); + } + } + //DDebug()<<"loadPreview for " << description.filePath << " existingTask " << existingTask << " currentTask " << m_currentTask << endl; + // append new loading task + if (existingTask) + return; + m_todo.append(new PreviewLoadingTask(this, description)); + m_condVar.wakeAll(); +} + + LoadingTask *ManagedLoadSaveThread::createLoadingTask(const LoadingDescription &description, bool preloading, LoadingMode loadingMode, AccessMode accessMode) { --- trunk/extragear/graphics/digikam/libs/threadimageio/managedloadsavethread.h #619530:619531 @@ -108,6 +108,7 @@ void load(LoadingDescription description, LoadingMode loadingMode, LoadingPolicy policy = LoadingPolicyAppend, AccessMode mode = AccessModeReadWrite); + void loadPreview(LoadingDescription description); private: _______________________________________________ Digikam-devel mailing list [hidden email] https://mail.kde.org/mailman/listinfo/digikam-devel |
Free forum by Nabble | Edit this page |