1
/* Gwenview - A simple image viewer for KDE
2
Copyright (C) 2000-2002 Aur�lien G�teau
3
This class is based on the ImagePreviewJob class from Konqueror.
4
Original copyright follows.
6
/* This file is part of the KDE project
7
Copyright (C) 2000 David Faure <faure@kde.org>
8
2000 Carsten Pfeiffer <pfeiffer@kde.org>
10
This program is free software; you can redistribute it and/or modify
11
it under the terms of the GNU General Public License as published by
12
the Free Software Foundation; either version 2 of the License, or
13
(at your option) any later version.
15
This program is distributed in the hope that it will be useful,
16
but WITHOUT ANY WARRANTY; without even the implied warranty of
17
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18
GNU General Public License for more details.
20
You should have received a copy of the GNU General Public License
21
along with this program; if not, write to the Free Software
22
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
31
#include <kfileviewitem.h>
36
#include "thumbnailloadjob.moc"
40
#define LOG(x) kdDebug() << k_funcinfo << x << endl
47
const QString& ThumbnailLoadJob::thumbnailDir() {
49
if (!dir.isEmpty()) return dir;
51
KGlobal::dirs()->addResourceType("thumbnails","share/thumbnails/");
52
dir = QDir::cleanDirPath( KGlobal::dirs()->resourceDirs("thumbnails")[0] );
57
ThumbnailLoadJob::ThumbnailLoadJob(const KFileViewItemList* itemList,ThumbnailSize size)
58
: KIO::Job(false), mThumbnailSize(size)
62
// Look for images and store the items in our todo list
63
for (KFileViewItem* item=itemList->getFirst(); item; item=item->next()) {
67
if (mItems.isEmpty()) return;
69
QString originalDir=QDir::cleanDirPath( mItems.first()->url().directory() );
71
// Check if we're already in a cache dir
72
// In that case the cache dir will be the original dir
74
KGlobal::dirs()->addResourceType("thumbnails","share/thumbnails/");
75
QString cacheBaseDir = QDir::cleanDirPath( KGlobal::dirs()->resourceDirs("thumbnails")[0] );
77
QString cacheBaseDir = thumbnailDir();
78
if ( originalDir.startsWith(cacheBaseDir) ) {
79
mCacheDir=originalDir;
83
// Generate the thumbnail dir name
85
KMD5 md5( QFile::encodeName(originalDir) );
86
md5.hexDigest( hash );
87
QString thumbPath = QString::fromLatin1( hash, 4 ) + "/" +
88
QString::fromLatin1( &hash[4], 4 ) + "/" +
89
QString::fromLatin1( &hash[8] ) + "/";
91
// Create the thumbnail cache dir
92
mCacheDir = locateLocal( "thumbnails", thumbPath + "/" + QString(mThumbnailSize) + "/" );
93
LOG("mCacheDir=" << mCacheDir);
97
ThumbnailLoadJob::~ThumbnailLoadJob() {
102
void ThumbnailLoadJob::start() {
103
if (mItems.isEmpty()) {
104
LOG("Nothing to do");
114
//-Internal--------------------------------------------------------------
115
void ThumbnailLoadJob::itemRemoved(const KFileViewItem* item) {
116
mItems.removeRef(item);
118
if (item == mCurrentItem) {
120
subjobs.first()->kill();
121
subjobs.removeFirst();
127
void ThumbnailLoadJob::determineNextIcon() {
129
if (mItems.isEmpty()) {
131
LOG("emitting result");
135
// First, stat the orig file
136
mState = STATE_STATORIG;
137
mCurrentItem = mItems.first();
138
mCurrentURL = mCurrentItem->url();
139
KIO::Job* job = KIO::stat(mCurrentURL,false);
140
LOG( "KIO::stat orig " << mCurrentURL.url() );
142
mItems.removeFirst();
147
void ThumbnailLoadJob::slotResult(KIO::Job * job) {
149
ASSERT(subjobs.isEmpty()); // We should have only one job at a time ...
152
case STATE_STATORIG: {
153
// Could not stat original, drop this one and move on to the next one
159
// Get modification time of the original file
160
KIO::UDSEntry entry = static_cast<KIO::StatJob*>(job)->statResult();
161
KIO::UDSEntry::ConstIterator it= entry.begin();
163
for (; it!=entry.end(); it++) {
164
if ((*it).m_uds == KIO::UDS_MODIFICATION_TIME) {
165
mOriginalTime = (time_t)((*it).m_long);
170
// Now stat the thumbnail
171
mThumbURL.setPath(mCacheDir + "/" + mCurrentURL.fileName());
172
mState = STATE_STATTHUMB;
173
KIO::Job * job = KIO::stat(mThumbURL, false);
174
LOG("Stat thumb " << mThumbURL.url());
181
case STATE_STATTHUMB:
182
// Try to load this thumbnail - takes care of determineNextIcon
183
if (statResultThumbnail(static_cast < KIO::StatJob * >(job)))
186
// Not found or not valid, let's create a thumbnail
187
createThumbnail(mCurrentURL.path());
191
case STATE_CREATETHUMB:
192
// Thumbnail saved, go on
199
bool ThumbnailLoadJob::statResultThumbnail(KIO::StatJob * job) {
200
// Quit if thumbnail not found
201
if (job->error()) return false;
203
// Get thumbnail modification time
204
KIO::UDSEntry entry = job->statResult();
205
KIO::UDSEntry::ConstIterator it = entry.begin();
206
time_t thumbnailTime = 0;
207
for (; it != entry.end(); it++) {
208
if ((*it).m_uds == KIO::UDS_MODIFICATION_TIME) {
209
thumbnailTime = (time_t) ((*it).m_long);
214
// Quit if thumbnail is older than file
215
if (thumbnailTime<mOriginalTime) {
221
if (!pix.load(mThumbURL.path())) {
225
emit thumbnailLoaded(mCurrentItem,pix);
231
void ThumbnailLoadJob::createThumbnail(QString pixPath) {
232
mState = STATE_CREATETHUMB;
234
thumbURL.setProtocol("thumbnail");
235
thumbURL.setPath(pixPath);
236
QString sizeStr=QString::number(mThumbnailSize.pixelSize());
238
KIO::TransferJob * job = KIO::get(thumbURL, false, false);
239
connect(job, SIGNAL(data(KIO::Job *, const QByteArray &)),
240
SLOT(slotThumbData(KIO::Job *, const QByteArray &)));
242
job->addMetaData("mimeType", mCurrentItem->mimetype());
243
job->addMetaData("iconSize", sizeStr);
244
job->addMetaData("width",sizeStr);
245
job->addMetaData("height",sizeStr);
246
job->addMetaData("extent",sizeStr);
247
job->addMetaData("plugin","imagethumbnail");
252
void ThumbnailLoadJob::slotThumbData(KIO::Job *, const QByteArray& imgData) {
254
QPixmap pix(imgData);
255
emit thumbnailLoaded(mCurrentItem,pix);
258
file.setName(mThumbURL.path());
259
if (!file.open(IO_WriteOnly)) return;
261
file.writeBlock(imgData.data(), imgData.size());