[Digikam-devel] extragear/graphics/digikam
Marcel Wiesweg
marcel.wiesweg at gmx.de
Wed Jan 3 16:45:44 GMT 2007
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: digikam-devel at kde.org
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:
More information about the Digikam-devel
mailing list