• Skip to content
  • Skip to link menu
KDE 4.7 API Reference
  • KDE API Reference
  • kdelibs
  • KDE Home
  • Contact Us
 

KIO

previewjob.cpp
Go to the documentation of this file.
00001 // -*- c++ -*-
00002 // vim: ts=4 sw=4 et
00003 /*  This file is part of the KDE libraries
00004     Copyright (C) 2000 David Faure <faure@kde.org>
00005                   2000 Carsten Pfeiffer <pfeiffer@kde.org>
00006                   2001 Malte Starostik <malte.starostik@t-online.de>
00007 
00008     This library is free software; you can redistribute it and/or
00009     modify it under the terms of the GNU Library General Public
00010     License as published by the Free Software Foundation; either
00011     version 2 of the License, or (at your option) any later version.
00012 
00013     This library is distributed in the hope that it will be useful,
00014     but WITHOUT ANY WARRANTY; without even the implied warranty of
00015     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00016     Library General Public License for more details.
00017 
00018     You should have received a copy of the GNU Library General Public License
00019     along with this library; see the file COPYING.LIB.  If not, write to
00020     the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
00021     Boston, MA 02110-1301, USA.
00022 */
00023 
00024 #include "previewjob.h"
00025 #include <kdebug.h>
00026 
00027 #include <sys/stat.h>
00028 #include <sys/types.h>
00029 
00030 #ifdef Q_OS_UNIX
00031 #include <sys/ipc.h>
00032 #include <sys/shm.h>
00033 #endif
00034 
00035 #include <QtCore/QDir>
00036 #include <QtCore/QFile>
00037 #include <QtGui/QImage>
00038 #include <QtCore/QTimer>
00039 #include <QtCore/QRegExp>
00040 
00041 #include <kfileitem.h>
00042 #include <kde_file.h>
00043 #include <ktemporaryfile.h>
00044 #include <kservicetypetrader.h>
00045 #include <kcodecs.h>
00046 #include <kglobal.h>
00047 #include <kstandarddirs.h>
00048 #include <kservice.h>
00049 #include <QtCore/QLinkedList>
00050 #include <kconfiggroup.h>
00051 #include <kprotocolinfo.h>
00052 
00053 #include "jobuidelegate.h"
00054 #include "job_p.h"
00055 
00056 namespace KIO { struct PreviewItem; }
00057 using namespace KIO;
00058 
00059 struct KIO::PreviewItem
00060 {
00061     KFileItem item;
00062     KService::Ptr plugin;
00063 };
00064 
00065 class KIO::PreviewJobPrivate: public KIO::JobPrivate
00066 {
00067 public:
00068     enum { STATE_STATORIG, // if the thumbnail exists
00069            STATE_GETORIG, // if we create it
00070            STATE_CREATETHUMB // thumbnail:/ slave
00071     } state;
00072     PreviewJob *q;
00073 
00074     KFileItemList initialItems;
00075     QStringList enabledPlugins;
00076     // Our todo list :)
00077     // We remove the first item at every step, so use QLinkedList
00078     QLinkedList<PreviewItem> items;
00079     // The current item
00080     PreviewItem currentItem;
00081     // The modification time of that URL
00082     time_t tOrig;
00083     // Path to thumbnail cache for the current size
00084     QString thumbPath;
00085     // Original URL of current item in TMS format
00086     // (file:///path/to/file instead of file:/path/to/file)
00087     QString origName;
00088     // Thumbnail file name for current item
00089     QString thumbName;
00090     // Size of thumbnail
00091     int width;
00092     int height;
00093     // Unscaled size of thumbnail (128 or 256 if cache is enabled)
00094     int cacheWidth;
00095     int cacheHeight;
00096     // Whether the thumbnail should be scaled
00097     bool bScale;
00098     // Whether we should save the thumbnail
00099     bool bSave;
00100     bool ignoreMaximumSize;
00101     int sequenceIndex;
00102     bool succeeded;
00103     // If the file to create a thumb for was a temp file, this is its name
00104     QString tempName;
00105     KIO::filesize_t maximumLocalSize;
00106     KIO::filesize_t maximumRemoteSize;
00107     // the size for the icon overlay
00108     int iconSize;
00109     // the transparency of the blended mimetype icon
00110     int iconAlpha;
00111     // Shared memory segment Id. The segment is allocated to a size
00112     // of extent x extent x 4 (32 bit image) on first need.
00113     int shmid;
00114     // And the data area
00115     uchar *shmaddr;
00116     // Root of thumbnail cache
00117     QString thumbRoot;
00118 
00119     void getOrCreateThumbnail();
00120     bool statResultThumbnail();
00121     void createThumbnail( const QString& );
00122     void determineNextFile();
00123     void emitPreview(const QImage &thumb);
00124 
00125     void startPreview();
00126     void slotThumbData(KIO::Job *, const QByteArray &);
00127 
00128     Q_DECLARE_PUBLIC(PreviewJob)
00129 };
00130 
00131 #ifndef KDE_NO_DEPRECATED
00132 PreviewJob::PreviewJob( const KFileItemList &items, int width, int height,
00133     int iconSize, int iconAlpha, bool scale, bool save,
00134     const QStringList *enabledPlugins )
00135     : KIO::Job(*new PreviewJobPrivate)
00136 {
00137     Q_D(PreviewJob);
00138     d->tOrig = 0;
00139     d->shmid = -1;
00140     d->shmaddr = 0;
00141     d->initialItems = items;
00142     d->enabledPlugins = enabledPlugins ? *enabledPlugins : availablePlugins();
00143     d->width = width;
00144     d->height = height ? height : width;
00145     d->cacheWidth = d->width;
00146     d->cacheHeight = d->height;
00147     d->iconSize = iconSize;
00148     d->iconAlpha = iconAlpha;
00149     d->bScale = scale;
00150     d->bSave = save && scale;
00151     d->succeeded = false;
00152     d->thumbRoot = QDir::homePath() + QLatin1String("/.thumbnails/");
00153     d->ignoreMaximumSize = false;
00154     d->sequenceIndex = 0;
00155     d->maximumLocalSize = 0;
00156     d->maximumRemoteSize = 0;
00157 
00158     // Return to event loop first, determineNextFile() might delete this;
00159     QTimer::singleShot(0, this, SLOT(startPreview()));
00160 }
00161 #endif
00162 
00163 PreviewJob::PreviewJob(const KFileItemList &items,
00164                        const QSize &size,
00165                        const QStringList *enabledPlugins) :
00166     KIO::Job(*new PreviewJobPrivate)
00167 {
00168     Q_D(PreviewJob);
00169     d->tOrig = 0;
00170     d->shmid = -1;
00171     d->shmaddr = 0;
00172     d->initialItems = items;
00173     if (enabledPlugins) {
00174         d->enabledPlugins = *enabledPlugins;
00175     } else {
00176         const KConfigGroup globalConfig(KGlobal::config(), "PreviewSettings");
00177         d->enabledPlugins = globalConfig.readEntry("Plugins", QStringList()
00178                                                               << "directorythumbnail"
00179                                                               << "imagethumbnail"
00180                                                               << "jpegthumbnail");
00181     }
00182     d->width = size.width();
00183     d->height = size.height();
00184     d->cacheWidth = d->width;
00185     d->cacheHeight = d->height;
00186     d->iconSize = 0;
00187     d->iconAlpha = 70;
00188     d->bScale = true;
00189     d->bSave = true;
00190     d->succeeded = false;
00191     d->thumbRoot = QDir::homePath() + QLatin1String("/.thumbnails/");
00192     d->ignoreMaximumSize = false;
00193     d->sequenceIndex = 0;
00194     d->maximumLocalSize = 0;
00195     d->maximumRemoteSize = 0;
00196 
00197     // Return to event loop first, determineNextFile() might delete this;
00198     QTimer::singleShot(0, this, SLOT(startPreview()));
00199 }
00200 
00201 PreviewJob::~PreviewJob()
00202 {
00203 #ifdef Q_OS_UNIX
00204     Q_D(PreviewJob);
00205     if (d->shmaddr) {
00206         shmdt((char*)d->shmaddr);
00207         shmctl(d->shmid, IPC_RMID, 0);
00208     }
00209 #endif
00210 }
00211 
00212 void PreviewJob::setOverlayIconSize(int size)
00213 {
00214     Q_D(PreviewJob);
00215     d->iconSize = size;
00216 }
00217 
00218 int PreviewJob::overlayIconSize() const
00219 {
00220     Q_D(const PreviewJob);
00221     return d->iconSize;
00222 }
00223 
00224 void PreviewJob::setOverlayIconAlpha(int alpha)
00225 {
00226     Q_D(PreviewJob);
00227     d->iconAlpha = qBound(0, alpha, 255);
00228 }
00229 
00230 int PreviewJob::overlayIconAlpha() const
00231 {
00232     Q_D(const PreviewJob);
00233     return d->iconAlpha;
00234 }
00235 
00236 void PreviewJob::setScaleType(ScaleType type)
00237 {
00238     Q_D(PreviewJob);
00239     switch (type) {
00240     case Unscaled:
00241         d->bScale = false;
00242         d->bSave = false;
00243         break;
00244     case Scaled:
00245         d->bScale = true;
00246         d->bSave = false;
00247         break;
00248     case ScaledAndCached:
00249         d->bScale = true;
00250         d->bSave = true;
00251         break;
00252     default:
00253         break;
00254     }
00255 }
00256 
00257 PreviewJob::ScaleType PreviewJob::scaleType() const
00258 {
00259     Q_D(const PreviewJob);
00260     if (d->bScale) {
00261         return d->bSave ? ScaledAndCached : Scaled;
00262     }
00263     return Unscaled;
00264 }
00265 
00266 void PreviewJobPrivate::startPreview()
00267 {
00268     Q_Q(PreviewJob);
00269     // Load the list of plugins to determine which mimetypes are supported
00270     const KService::List plugins = KServiceTypeTrader::self()->query("ThumbCreator");
00271     QMap<QString, KService::Ptr> mimeMap;
00272 
00273     for (KService::List::ConstIterator it = plugins.constBegin(); it != plugins.constEnd(); ++it) {
00274         if (enabledPlugins.contains((*it)->desktopEntryName())) {
00275             const QStringList mimeTypes = (*it)->serviceTypes();
00276             for (QStringList::ConstIterator mt = mimeTypes.constBegin(); mt != mimeTypes.constEnd(); ++mt)
00277                 mimeMap.insert(*mt, *it);
00278         }
00279     }
00280 
00281     // Look for images and store the items in our todo list :)
00282     bool bNeedCache = false;
00283     KFileItemList::const_iterator kit = initialItems.constBegin();
00284     const KFileItemList::const_iterator kend = initialItems.constEnd();
00285     for ( ; kit != kend; ++kit )
00286     {
00287         PreviewItem item;
00288         item.item = *kit;
00289         const QString mimeType = item.item.mimetype();
00290         QMap<QString, KService::Ptr>::ConstIterator plugin = mimeMap.constFind(mimeType);
00291         if (plugin == mimeMap.constEnd())
00292 
00293         {
00294             QString groupMimeType = mimeType;
00295             groupMimeType.replace(QRegExp("/.*"), "/*");
00296             plugin = mimeMap.constFind(groupMimeType);
00297 
00298             if (plugin == mimeMap.constEnd())
00299             {
00300                 // check mime type inheritance, resolve aliases
00301                 const KMimeType::Ptr mimeInfo = KMimeType::mimeType(mimeType, KMimeType::ResolveAliases);
00302                 if (mimeInfo) {
00303                     const QStringList parentMimeTypes = mimeInfo->allParentMimeTypes();
00304                     Q_FOREACH(const QString& parentMimeType, parentMimeTypes) {
00305                         plugin = mimeMap.constFind(parentMimeType);
00306                         if (plugin != mimeMap.constEnd()) break;
00307                     }
00308                 }
00309             }
00310 #if 0 // KDE4: should be covered by inheritance above, all text mimetypes inherit from text/plain
00311             // if that's not enough, we need to invent something else
00312             if (plugin == mimeMap.end())
00313             {
00314                 // check X-KDE-Text property
00315                 KMimeType::Ptr mimeInfo = KMimeType::mimeType(mimeType);
00316                 QVariant textProperty = mimeInfo->property("X-KDE-text");
00317                 if (textProperty.isValid() && textProperty.type() == QVariant::Bool)
00318                 {
00319                     if (textProperty.toBool())
00320                     {
00321                         plugin = mimeMap.find("text/plain");
00322                         if (plugin == mimeMap.end())
00323                         {
00324                             plugin = mimeMap.find( "text/*" );
00325                         }
00326                     }
00327                 }
00328             }
00329 #endif
00330         }
00331 
00332         if (plugin != mimeMap.constEnd())
00333         {
00334             item.plugin = *plugin;
00335             items.append(item);
00336             if (!bNeedCache && bSave &&
00337                 ((*kit).url().protocol() != "file" ||
00338                  !(*kit).url().directory( KUrl::AppendTrailingSlash ).startsWith(thumbRoot)) &&
00339                 (*plugin)->property("CacheThumbnail").toBool())
00340                 bNeedCache = true;
00341         }
00342         else
00343         {
00344             emit q->failed( *kit );
00345         }
00346     }
00347 
00348     KConfigGroup cg( KGlobal::config(), "PreviewSettings" );
00349     maximumLocalSize = cg.readEntry( "MaximumSize", 5*1024*1024LL /* 5MB */ );
00350     maximumRemoteSize = cg.readEntry( "MaximumRemoteSize", 0 );
00351 
00352     if (bNeedCache)
00353     {
00354         if (width <= 128 && height <= 128) cacheWidth = cacheHeight = 128;
00355         else cacheWidth = cacheHeight = 256;
00356         thumbPath = thumbRoot + (cacheWidth == 128 ? "normal/" : "large/");
00357         KStandardDirs::makeDir(thumbPath, 0700);
00358     }
00359     else
00360         bSave = false;
00361 
00362     initialItems.clear();
00363     determineNextFile();
00364 }
00365 
00366 void PreviewJob::removeItem( const KUrl& url )
00367 {
00368     Q_D(PreviewJob);
00369     for (QLinkedList<PreviewItem>::Iterator it = d->items.begin(); it != d->items.end(); ++it)
00370         if ((*it).item.url() == url)
00371         {
00372             d->items.erase(it);
00373             break;
00374         }
00375 
00376     if (d->currentItem.item.url() == url)
00377     {
00378         KJob* job = subjobs().first();
00379         job->kill();
00380         removeSubjob( job );
00381         d->determineNextFile();
00382     }
00383 }
00384 
00385 void KIO::PreviewJob::setSequenceIndex(int index) {
00386     d_func()->sequenceIndex = index;
00387 }
00388 
00389 int KIO::PreviewJob::sequenceIndex() const {
00390     return d_func()->sequenceIndex;
00391 }
00392 
00393 void PreviewJob::setIgnoreMaximumSize(bool ignoreSize)
00394 {
00395     d_func()->ignoreMaximumSize = ignoreSize;
00396 }
00397 
00398 void PreviewJobPrivate::determineNextFile()
00399 {
00400     Q_Q(PreviewJob);
00401     if (!currentItem.item.isNull())
00402     {
00403         if (!succeeded)
00404             emit q->failed( currentItem.item );
00405     }
00406     // No more items ?
00407     if ( items.isEmpty() )
00408     {
00409         q->emitResult();
00410         return;
00411     }
00412     else
00413     {
00414         // First, stat the orig file
00415         state = PreviewJobPrivate::STATE_STATORIG;
00416         currentItem = items.first();
00417         succeeded = false;
00418         items.removeFirst();
00419         KIO::Job *job = KIO::stat( currentItem.item.url(), KIO::HideProgressInfo );
00420         job->addMetaData( "no-auth-prompt", "true" );
00421         q->addSubjob(job);
00422     }
00423 }
00424 
00425 void PreviewJob::slotResult( KJob *job )
00426 {
00427     Q_D(PreviewJob);
00428 
00429     removeSubjob(job);
00430     Q_ASSERT ( !hasSubjobs() ); // We should have only one job at a time ...
00431     switch ( d->state )
00432     {
00433         case PreviewJobPrivate::STATE_STATORIG:
00434         {
00435             if (job->error()) // that's no good news...
00436             {
00437                 // Drop this one and move on to the next one
00438                 d->determineNextFile();
00439                 return;
00440             }
00441             const KIO::UDSEntry entry = static_cast<KIO::StatJob*>(job)->statResult();
00442             d->tOrig = entry.numberValue( KIO::UDSEntry::UDS_MODIFICATION_TIME, 0 );
00443 
00444             bool skipCurrentItem = false;
00445             const KIO::filesize_t size = (KIO::filesize_t)entry.numberValue( KIO::UDSEntry::UDS_SIZE, 0 );
00446             const KUrl itemUrl = d->currentItem.item.mostLocalUrl();
00447             if (itemUrl.isLocalFile() || KProtocolInfo::protocolClass(itemUrl.protocol()) == QLatin1String(":local"))
00448             {
00449                 skipCurrentItem = !d->ignoreMaximumSize && size > d->maximumLocalSize
00450                                   && !d->currentItem.plugin->property("IgnoreMaximumSize").toBool();
00451             }
00452             else
00453             {
00454                 // For remote items the "IgnoreMaximumSize" plugin property is not respected
00455                 skipCurrentItem = !d->ignoreMaximumSize && size > d->maximumRemoteSize;
00456 
00457                 // Remote directories are not supported, don't try to do a file_copy on them
00458                 if (!skipCurrentItem) {
00459                     // TODO update item.mimeType from the UDS entry, in case it wasn't set initially
00460                     KMimeType::Ptr mime = d->currentItem.item.mimeTypePtr();
00461                     if (mime && mime->is("inode/directory")) {
00462                         skipCurrentItem = true;
00463                     }
00464                 }
00465             }
00466             if (skipCurrentItem)
00467             {
00468                 d->determineNextFile();
00469                 return;
00470             }
00471 
00472             bool pluginHandlesSequences = d->currentItem.plugin->property("HandleSequences", QVariant::Bool).toBool();
00473 
00474             if ( !d->currentItem.plugin->property( "CacheThumbnail" ).toBool()  || (d->sequenceIndex && pluginHandlesSequences) )
00475             {
00476                 // This preview will not be cached, no need to look for a saved thumbnail
00477                 // Just create it, and be done
00478                 d->getOrCreateThumbnail();
00479                 return;
00480             }
00481 
00482             if ( d->statResultThumbnail() )
00483                 return;
00484 
00485             d->getOrCreateThumbnail();
00486             return;
00487         }
00488         case PreviewJobPrivate::STATE_GETORIG:
00489         {
00490             if (job->error())
00491             {
00492                 d->determineNextFile();
00493                 return;
00494             }
00495 
00496             d->createThumbnail( static_cast<KIO::FileCopyJob*>(job)->destUrl().toLocalFile() );
00497             return;
00498         }
00499         case PreviewJobPrivate::STATE_CREATETHUMB:
00500         {
00501             if (!d->tempName.isEmpty())
00502             {
00503                 QFile::remove(d->tempName);
00504                 d->tempName.clear();
00505             }
00506             d->determineNextFile();
00507             return;
00508         }
00509     }
00510 }
00511 
00512 bool PreviewJobPrivate::statResultThumbnail()
00513 {
00514     if ( thumbPath.isEmpty() )
00515         return false;
00516 
00517     KUrl url = currentItem.item.mostLocalUrl();
00518     // Don't include the password if any
00519     url.setPass(QString());
00520     origName = url.url();
00521 
00522     KMD5 md5( QFile::encodeName( origName ) );
00523     thumbName = QFile::encodeName( md5.hexDigest() ) + ".png";
00524 
00525     QImage thumb;
00526     if ( !thumb.load( thumbPath + thumbName ) ) return false;
00527 
00528     if ( thumb.text( "Thumb::URI", 0 ) != origName ||
00529          thumb.text( "Thumb::MTime", 0 ).toInt() != tOrig ) return false;
00530 
00531     QString thumbnailerVersion = currentItem.plugin->property("ThumbnailerVersion", QVariant::String).toString();
00532 
00533     if (!thumbnailerVersion.isEmpty() && thumb.text("Software", 0).startsWith("KDE Thumbnail Generator")) {
00534         //Check if the version matches
00535         //The software string should read "KDE Thumbnail Generator pluginName (vX)"
00536         QString softwareString = thumb.text("Software", 0).remove("KDE Thumbnail Generator").trimmed();
00537         if (softwareString.isEmpty()) {
00538             // The thumbnail has been created with an older version, recreating
00539             return false;
00540         }
00541         int versionIndex = softwareString.lastIndexOf("(v");
00542         if (versionIndex < 0) {
00543             return false;
00544         }
00545 
00546         QString cachedVersion = softwareString.remove(0, versionIndex+2);
00547         cachedVersion.chop(1);
00548         uint thumbnailerMajor = thumbnailerVersion.toInt();
00549         uint cachedMajor = cachedVersion.toInt();
00550         if (thumbnailerMajor > cachedMajor) {
00551             return false;
00552         }
00553     }
00554 
00555     // Found it, use it
00556     emitPreview( thumb );
00557     succeeded = true;
00558     determineNextFile();
00559     return true;
00560 }
00561 
00562 
00563 void PreviewJobPrivate::getOrCreateThumbnail()
00564 {
00565     Q_Q(PreviewJob);
00566     // We still need to load the orig file ! (This is getting tedious) :)
00567     const KFileItem& item = currentItem.item;
00568     const QString localPath = item.localPath();
00569     if ( !localPath.isEmpty() )
00570         createThumbnail( localPath );
00571     else
00572     {
00573         state = PreviewJobPrivate::STATE_GETORIG;
00574         KTemporaryFile localFile;
00575         localFile.setAutoRemove(false);
00576         localFile.open();
00577         KUrl localURL;
00578         localURL.setPath( tempName = localFile.fileName() );
00579         const KUrl currentURL = item.mostLocalUrl();
00580         KIO::Job * job = KIO::file_copy( currentURL, localURL, -1, KIO::Overwrite | KIO::HideProgressInfo /* No GUI */ );
00581         job->addMetaData("thumbnail","1");
00582         q->addSubjob(job);
00583     }
00584 }
00585 
00586 void PreviewJobPrivate::createThumbnail( const QString &pixPath )
00587 {
00588     Q_Q(PreviewJob);
00589     state = PreviewJobPrivate::STATE_CREATETHUMB;
00590     KUrl thumbURL;
00591     thumbURL.setProtocol("thumbnail");
00592     thumbURL.setPath(pixPath);
00593     KIO::TransferJob *job = KIO::get(thumbURL, NoReload, HideProgressInfo);
00594     q->addSubjob(job);
00595     q->connect(job, SIGNAL(data(KIO::Job *, const QByteArray &)), SLOT(slotThumbData(KIO::Job *, const QByteArray &)));
00596     bool save = bSave && currentItem.plugin->property("CacheThumbnail").toBool() && !sequenceIndex;
00597     job->addMetaData("mimeType", currentItem.item.mimetype());
00598     job->addMetaData("width", QString().setNum(save ? cacheWidth : width));
00599     job->addMetaData("height", QString().setNum(save ? cacheHeight : height));
00600     job->addMetaData("iconSize", QString().setNum(save ? 64 : iconSize));
00601     job->addMetaData("iconAlpha", QString().setNum(iconAlpha));
00602     job->addMetaData("plugin", currentItem.plugin->library());
00603     if(sequenceIndex)
00604         job->addMetaData("sequence-index", QString().setNum(sequenceIndex));
00605 
00606 #ifdef Q_OS_UNIX
00607     if (shmid == -1)
00608     {
00609         if (shmaddr) {
00610             shmdt((char*)shmaddr);
00611             shmctl(shmid, IPC_RMID, 0);
00612         }
00613         shmid = shmget(IPC_PRIVATE, cacheWidth * cacheHeight * 4, IPC_CREAT|0600);
00614         if (shmid != -1)
00615         {
00616             shmaddr = (uchar *)(shmat(shmid, 0, SHM_RDONLY));
00617             if (shmaddr == (uchar *)-1)
00618             {
00619                 shmctl(shmid, IPC_RMID, 0);
00620                 shmaddr = 0;
00621                 shmid = -1;
00622             }
00623         }
00624         else
00625             shmaddr = 0;
00626     }
00627     if (shmid != -1)
00628         job->addMetaData("shmid", QString().setNum(shmid));
00629 #endif
00630 }
00631 
00632 void PreviewJobPrivate::slotThumbData(KIO::Job *, const QByteArray &data)
00633 {
00634     bool save = bSave &&
00635                 currentItem.plugin->property("CacheThumbnail").toBool() &&
00636                 (currentItem.item.url().protocol() != "file" ||
00637                  !currentItem.item.url().directory( KUrl::AppendTrailingSlash ).startsWith(thumbRoot)) && !sequenceIndex;
00638     QImage thumb;
00639 #ifdef Q_OS_UNIX
00640     if (shmaddr)
00641     {
00642         // Keep this in sync with kdebase/kioslave/thumbnail.cpp
00643         QDataStream str(data);
00644         int width, height;
00645         quint8 iFormat;
00646         str >> width >> height >> iFormat;
00647         QImage::Format format = static_cast<QImage::Format>( iFormat );
00648         thumb = QImage(shmaddr, width, height, format ).copy();
00649     }
00650     else
00651 #endif
00652         thumb.loadFromData(data);
00653 
00654     if (thumb.isNull()) {
00655         QDataStream s(data);
00656         s >> thumb;
00657     }
00658 
00659     QString tempFileName;
00660     bool savedCorrectly = false;
00661     if (save)
00662     {
00663         thumb.setText("Thumb::URI", origName);
00664         thumb.setText("Thumb::MTime", QString::number(tOrig));
00665         thumb.setText("Thumb::Size", number(currentItem.item.size()));
00666         thumb.setText("Thumb::Mimetype", currentItem.item.mimetype());
00667         QString thumbnailerVersion = currentItem.plugin->property("ThumbnailerVersion", QVariant::String).toString();
00668         QString signature = QString("KDE Thumbnail Generator "+currentItem.plugin->name());
00669         if (!thumbnailerVersion.isEmpty()) {
00670             signature.append(" (v"+thumbnailerVersion+')');
00671         }
00672         thumb.setText("Software", signature);
00673         KTemporaryFile temp;
00674         temp.setPrefix(thumbPath + "kde-tmp-");
00675         temp.setSuffix(".png");
00676         temp.setAutoRemove(false);
00677         if (temp.open()) //Only try to write out the thumbnail if we
00678         {                //actually created the temp file.
00679             tempFileName = temp.fileName();
00680             savedCorrectly = thumb.save(tempFileName, "PNG");
00681         }
00682     }
00683     if(savedCorrectly)
00684     {
00685         Q_ASSERT(!tempFileName.isEmpty());
00686         KDE::rename(tempFileName, thumbPath + thumbName);
00687     }
00688     emitPreview( thumb );
00689     succeeded = true;
00690 }
00691 
00692 void PreviewJobPrivate::emitPreview(const QImage &thumb)
00693 {
00694     Q_Q(PreviewJob);
00695     QPixmap pix;
00696     if (thumb.width() > width || thumb.height() > height)
00697         pix = QPixmap::fromImage( thumb.scaled(QSize(width, height), Qt::KeepAspectRatio, Qt::SmoothTransformation) );
00698     else
00699         pix = QPixmap::fromImage( thumb );
00700     emit q->gotPreview(currentItem.item, pix);
00701 }
00702 
00703 QStringList PreviewJob::availablePlugins()
00704 {
00705     QStringList result;
00706     const KService::List plugins = KServiceTypeTrader::self()->query("ThumbCreator");
00707     for (KService::List::ConstIterator it = plugins.begin(); it != plugins.end(); ++it)
00708         if (!result.contains((*it)->desktopEntryName()))
00709             result.append((*it)->desktopEntryName());
00710     return result;
00711 }
00712 
00713 QStringList PreviewJob::supportedMimeTypes()
00714 {
00715     QStringList result;
00716     const KService::List plugins = KServiceTypeTrader::self()->query("ThumbCreator");
00717     for (KService::List::ConstIterator it = plugins.begin(); it != plugins.end(); ++it)
00718         result += (*it)->serviceTypes();
00719     return result;
00720 }
00721 
00722 #ifndef KDE_NO_DEPRECATED
00723 PreviewJob *KIO::filePreview( const KFileItemList &items, int width, int height,
00724     int iconSize, int iconAlpha, bool scale, bool save,
00725     const QStringList *enabledPlugins )
00726 {
00727     return new PreviewJob(items, width, height, iconSize, iconAlpha,
00728                           scale, save, enabledPlugins);
00729 }
00730 
00731 PreviewJob *KIO::filePreview( const KUrl::List &items, int width, int height,
00732     int iconSize, int iconAlpha, bool scale, bool save,
00733     const QStringList *enabledPlugins )
00734 {
00735     KFileItemList fileItems;
00736     for (KUrl::List::ConstIterator it = items.begin(); it != items.end(); ++it) {
00737         Q_ASSERT( (*it).isValid() ); // please call us with valid urls only
00738         fileItems.append(KFileItem(KFileItem::Unknown, KFileItem::Unknown, *it, true));
00739     }
00740     return new PreviewJob(fileItems, width, height, iconSize, iconAlpha,
00741                           scale, save, enabledPlugins);
00742 }
00743 #endif
00744 
00745 PreviewJob *KIO::filePreview(const KFileItemList &items, const QSize &size, const QStringList *enabledPlugins)
00746 {
00747     return new PreviewJob(items, size, enabledPlugins);
00748 }
00749 
00750 #ifndef KDE_NO_DEPRECATED
00751 KIO::filesize_t PreviewJob::maximumFileSize()
00752 {
00753     KConfigGroup cg( KGlobal::config(), "PreviewSettings" );
00754     return cg.readEntry( "MaximumSize", 5*1024*1024LL /* 5MB */ );
00755 }
00756 #endif
00757 
00758 #include "previewjob.moc"

KIO

Skip menu "KIO"
  • Main Page
  • Namespace List
  • Namespace Members
  • Alphabetical List
  • Class List
  • Class Hierarchy
  • Class Members
  • File List
  • File Members
  • Related Pages

kdelibs

Skip menu "kdelibs"
  • DNSSD
  • Interfaces
  •   KHexEdit
  •   KMediaPlayer
  •   KSpeech
  •   KTextEditor
  • kconf_update
  • KDE3Support
  •   KUnitTest
  • KDECore
  • KDED
  • KDEsu
  • KDEUI
  • KDEWebKit
  • KDocTools
  • KFile
  • KHTML
  • KImgIO
  • KInit
  • kio
  • KIOSlave
  • KJS
  •   KJS-API
  •   WTF
  • kjsembed
  • KNewStuff
  • KParts
  • KPty
  • Kross
  • KUnitConversion
  • KUtils
  • Nepomuk
  • Plasma
  • Solid
  • Sonnet
  • ThreadWeaver
Generated for kdelibs by doxygen 1.7.5
This website is maintained by Adriaan de Groot and Allen Winter.
KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal