~ubuntu-branches/ubuntu/intrepid/gwenview/intrepid

« back to all changes in this revision

Viewing changes to gwenview/thumbnailloadjob.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Christopher Martin
  • Date: 2005-04-06 11:33:06 UTC
  • mfrom: (1.2.1 upstream) (2.1.1 warty)
  • Revision ID: james.westby@ubuntu.com-20050406113306-7zovl7z0io5bacpd
Tags: 1.2.0-1
* New upstream release.
  + Fixes crashes when using "Back" to navigate. (Closes: #301811)
* Enable KIPI support.
* Add a doc-base file for the handbook.

Show diffs side-by-side

added added

removed removed

Lines of Context:
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.
5
 
*/
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>
9
 
 
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.
14
 
 
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.
19
 
 
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.
23
 
*/
24
 
 
25
 
// Qt includes
26
 
#include <qdir.h>
27
 
#include <qfile.h>
28
 
 
29
 
// KDE includes
30
 
#include <kdebug.h>
31
 
#include <kfileviewitem.h>
32
 
#include <kmdcodec.h>
33
 
#include <kstddirs.h>
34
 
 
35
 
// Our includes
36
 
#include "thumbnailloadjob.moc"
37
 
 
38
 
//#define ENABLE_LOG
39
 
#ifdef ENABLE_LOG
40
 
#define LOG(x) kdDebug() << k_funcinfo << x << endl
41
 
#else
42
 
#define LOG(x) ;
43
 
#endif
44
 
 
45
 
 
46
 
 
47
 
const QString& ThumbnailLoadJob::thumbnailDir() {
48
 
        static QString dir;
49
 
        if (!dir.isEmpty()) return dir;
50
 
 
51
 
        KGlobal::dirs()->addResourceType("thumbnails","share/thumbnails/");
52
 
        dir = QDir::cleanDirPath( KGlobal::dirs()->resourceDirs("thumbnails")[0] );
53
 
        return dir;
54
 
}
55
 
 
56
 
 
57
 
ThumbnailLoadJob::ThumbnailLoadJob(const KFileViewItemList* itemList,ThumbnailSize size)
58
 
: KIO::Job(false), mThumbnailSize(size)
59
 
{
60
 
        LOG("");
61
 
 
62
 
// Look for images and store the items in our todo list
63
 
        for (KFileViewItem* item=itemList->getFirst(); item; item=item->next()) {
64
 
                mItems.append(item);
65
 
        }
66
 
 
67
 
        if (mItems.isEmpty()) return;
68
 
 
69
 
        QString originalDir=QDir::cleanDirPath( mItems.first()->url().directory() );
70
 
 
71
 
// Check if we're already in a cache dir
72
 
// In that case the cache dir will be the original dir
73
 
/*
74
 
        KGlobal::dirs()->addResourceType("thumbnails","share/thumbnails/");
75
 
        QString cacheBaseDir = QDir::cleanDirPath( KGlobal::dirs()->resourceDirs("thumbnails")[0] );
76
 
*/
77
 
        QString cacheBaseDir = thumbnailDir();
78
 
        if ( originalDir.startsWith(cacheBaseDir) ) {
79
 
                mCacheDir=originalDir;
80
 
                return;
81
 
        }
82
 
 
83
 
// Generate the thumbnail dir name
84
 
        HASHHEX hash;
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] ) + "/";
90
 
 
91
 
// Create the thumbnail cache dir
92
 
        mCacheDir = locateLocal( "thumbnails", thumbPath + "/" + QString(mThumbnailSize) + "/" );
93
 
        LOG("mCacheDir=" << mCacheDir);
94
 
}
95
 
 
96
 
 
97
 
ThumbnailLoadJob::~ThumbnailLoadJob() {
98
 
        LOG("");
99
 
}
100
 
 
101
 
 
102
 
void ThumbnailLoadJob::start() {
103
 
        if (mItems.isEmpty()) {
104
 
                LOG("Nothing to do");
105
 
                emit result(this);
106
 
                delete this;
107
 
                return;
108
 
        }
109
 
 
110
 
        determineNextIcon();
111
 
}
112
 
 
113
 
 
114
 
//-Internal--------------------------------------------------------------
115
 
void ThumbnailLoadJob::itemRemoved(const KFileViewItem* item) {
116
 
        mItems.removeRef(item);
117
 
 
118
 
        if (item == mCurrentItem) {
119
 
                // Abort
120
 
                subjobs.first()->kill();
121
 
                subjobs.removeFirst();
122
 
                determineNextIcon();
123
 
        }
124
 
}
125
 
 
126
 
 
127
 
void ThumbnailLoadJob::determineNextIcon() {
128
 
        // No more items ?
129
 
        if (mItems.isEmpty()) {
130
 
        // Done
131
 
                LOG("emitting result");
132
 
                emit result(this);
133
 
                delete this;
134
 
        } else {
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() );
141
 
                addSubjob(job);
142
 
                mItems.removeFirst();
143
 
        }
144
 
}
145
 
 
146
 
 
147
 
void ThumbnailLoadJob::slotResult(KIO::Job * job) {
148
 
        subjobs.remove(job);
149
 
        ASSERT(subjobs.isEmpty());      // We should have only one job at a time ...
150
 
 
151
 
        switch (mState) {
152
 
        case STATE_STATORIG: {
153
 
        // Could not stat original, drop this one and move on to the next one
154
 
                if (job->error()) {
155
 
                        determineNextIcon();
156
 
                        return;
157
 
                }
158
 
 
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();
162
 
                mOriginalTime = 0;
163
 
                for (; it!=entry.end(); it++) {
164
 
                        if ((*it).m_uds == KIO::UDS_MODIFICATION_TIME) {
165
 
                                mOriginalTime = (time_t)((*it).m_long);
166
 
                                break;
167
 
                        }
168
 
                }
169
 
 
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());
175
 
                addSubjob(job);
176
 
 
177
 
                return;
178
 
        }
179
 
 
180
 
 
181
 
        case STATE_STATTHUMB:
182
 
        // Try to load this thumbnail - takes care of determineNextIcon
183
 
                if (statResultThumbnail(static_cast < KIO::StatJob * >(job)))
184
 
                        return;
185
 
 
186
 
        // Not found or not valid, let's create a thumbnail
187
 
                createThumbnail(mCurrentURL.path());
188
 
                return;
189
 
 
190
 
 
191
 
        case STATE_CREATETHUMB:
192
 
        // Thumbnail saved, go on
193
 
                determineNextIcon();
194
 
                return;
195
 
        }
196
 
}
197
 
 
198
 
 
199
 
bool ThumbnailLoadJob::statResultThumbnail(KIO::StatJob * job) {
200
 
// Quit if thumbnail not found
201
 
        if (job->error()) return false;
202
 
 
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);
210
 
                        break;
211
 
                }
212
 
        }
213
 
 
214
 
// Quit if thumbnail is older than file
215
 
        if (thumbnailTime<mOriginalTime) {
216
 
                return false;
217
 
        }
218
 
 
219
 
// Load thumbnail
220
 
        QPixmap pix;
221
 
        if (!pix.load(mThumbURL.path())) {
222
 
                return false;
223
 
        }
224
 
 
225
 
        emit thumbnailLoaded(mCurrentItem,pix);
226
 
        determineNextIcon();
227
 
        return true;
228
 
}
229
 
 
230
 
 
231
 
void ThumbnailLoadJob::createThumbnail(QString pixPath) {
232
 
        mState = STATE_CREATETHUMB;
233
 
        KURL thumbURL;
234
 
        thumbURL.setProtocol("thumbnail");
235
 
        thumbURL.setPath(pixPath);
236
 
        QString sizeStr=QString::number(mThumbnailSize.pixelSize());
237
 
 
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 &)));
241
 
 
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");
248
 
        addSubjob(job);
249
 
}
250
 
 
251
 
 
252
 
void ThumbnailLoadJob::slotThumbData(KIO::Job *, const QByteArray& imgData) {
253
 
        LOG("");
254
 
        QPixmap pix(imgData);
255
 
        emit thumbnailLoaded(mCurrentItem,pix);
256
 
 
257
 
        QFile file;
258
 
        file.setName(mThumbURL.path());
259
 
        if (!file.open(IO_WriteOnly)) return;
260
 
 
261
 
        file.writeBlock(imgData.data(), imgData.size());
262
 
        file.close();
263
 
}