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

KIO

  • kio
  • kio
previewjob.cpp
Go to the documentation of this file.
1// -*- c++ -*-
2// vim: ts=4 sw=4 et
3/* This file is part of the KDE libraries
4 Copyright (C) 2000 David Faure <faure@kde.org>
5 2000 Carsten Pfeiffer <pfeiffer@kde.org>
6 2001 Malte Starostik <malte.starostik@t-online.de>
7
8 This library is free software; you can redistribute it and/or
9 modify it under the terms of the GNU Library General Public
10 License as published by the Free Software Foundation; either
11 version 2 of the License, or (at your option) any later version.
12
13 This library is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 Library General Public License for more details.
17
18 You should have received a copy of the GNU Library General Public License
19 along with this library; see the file COPYING.LIB. If not, write to
20 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
21 Boston, MA 02110-1301, USA.
22*/
23
24#include "previewjob.h"
25#include <kdebug.h>
26
27#include <sys/stat.h>
28#include <sys/types.h>
29
30#ifdef Q_OS_UNIX
31#include <sys/ipc.h>
32#include <sys/shm.h>
33#endif
34
35#include <QtCore/QDir>
36#include <QtCore/QFile>
37#include <QtGui/QImage>
38#include <QtCore/QTimer>
39#include <QtCore/QRegExp>
40
41#include <kfileitem.h>
42#include <kde_file.h>
43#include <ktemporaryfile.h>
44#include <kservicetypetrader.h>
45#include <kcodecs.h>
46#include <kglobal.h>
47#include <kstandarddirs.h>
48#include <kservice.h>
49#include <QtCore/QLinkedList>
50#include <kconfiggroup.h>
51#include <kprotocolinfo.h>
52
53#include "jobuidelegate.h"
54#include "job_p.h"
55
56namespace KIO { struct PreviewItem; }
57using namespace KIO;
58
59struct KIO::PreviewItem
60{
61 KFileItem item;
62 KService::Ptr plugin;
63};
64
65class KIO::PreviewJobPrivate: public KIO::JobPrivate
66{
67public:
68 enum { STATE_STATORIG, // if the thumbnail exists
69 STATE_GETORIG, // if we create it
70 STATE_CREATETHUMB // thumbnail:/ slave
71 } state;
72 PreviewJob *q;
73
74 KFileItemList initialItems;
75 QStringList enabledPlugins;
76 // Some plugins support remote URLs, <protocol, mimetypes>
77 QHash<QString, QStringList> m_remoteProtocolPlugins;
78 // Our todo list :)
79 // We remove the first item at every step, so use QLinkedList
80 QLinkedList<PreviewItem> items;
81 // The current item
82 PreviewItem currentItem;
83 // The modification time of that URL
84 time_t tOrig;
85 // Path to thumbnail cache for the current size
86 QString thumbPath;
87 // Original URL of current item in TMS format
88 // (file:///path/to/file instead of file:/path/to/file)
89 QString origName;
90 // Thumbnail file name for current item
91 QString thumbName;
92 // Size of thumbnail
93 int width;
94 int height;
95 // Unscaled size of thumbnail (128 or 256 if cache is enabled)
96 int cacheWidth;
97 int cacheHeight;
98 // Whether the thumbnail should be scaled
99 bool bScale;
100 // Whether we should save the thumbnail
101 bool bSave;
102 bool ignoreMaximumSize;
103 int sequenceIndex;
104 bool succeeded;
105 // If the file to create a thumb for was a temp file, this is its name
106 QString tempName;
107 KIO::filesize_t maximumLocalSize;
108 KIO::filesize_t maximumRemoteSize;
109 // the size for the icon overlay
110 int iconSize;
111 // the transparency of the blended mimetype icon
112 int iconAlpha;
113 // Shared memory segment Id. The segment is allocated to a size
114 // of extent x extent x 4 (32 bit image) on first need.
115 int shmid;
116 // And the data area
117 uchar *shmaddr;
118 // Root of thumbnail cache
119 QString thumbRoot;
120
121 void getOrCreateThumbnail();
122 bool statResultThumbnail();
123 void createThumbnail( const QString& );
124 void determineNextFile();
125 void emitPreview(const QImage &thumb);
126
127 void startPreview();
128 void slotThumbData(KIO::Job *, const QByteArray &);
129
130 Q_DECLARE_PUBLIC(PreviewJob)
131};
132
133#ifndef KDE_NO_DEPRECATED
134PreviewJob::PreviewJob( const KFileItemList &items, int width, int height,
135 int iconSize, int iconAlpha, bool scale, bool save,
136 const QStringList *enabledPlugins )
137 : KIO::Job(*new PreviewJobPrivate)
138{
139 Q_D(PreviewJob);
140 d->tOrig = 0;
141 d->shmid = -1;
142 d->shmaddr = 0;
143 d->initialItems = items;
144 d->enabledPlugins = enabledPlugins ? *enabledPlugins : availablePlugins();
145 d->width = width;
146 d->height = height ? height : width;
147 d->cacheWidth = d->width;
148 d->cacheHeight = d->height;
149 d->iconSize = iconSize;
150 d->iconAlpha = iconAlpha;
151 d->bScale = scale;
152 d->bSave = save && scale;
153 d->succeeded = false;
154 d->thumbRoot = QDir::homePath() + QLatin1String("/.thumbnails/");
155 d->ignoreMaximumSize = false;
156 d->sequenceIndex = 0;
157 d->maximumLocalSize = 0;
158 d->maximumRemoteSize = 0;
159
160 // Return to event loop first, determineNextFile() might delete this;
161 QTimer::singleShot(0, this, SLOT(startPreview()));
162}
163#endif
164
165PreviewJob::PreviewJob(const KFileItemList &items,
166 const QSize &size,
167 const QStringList *enabledPlugins) :
168 KIO::Job(*new PreviewJobPrivate)
169{
170 Q_D(PreviewJob);
171 d->tOrig = 0;
172 d->shmid = -1;
173 d->shmaddr = 0;
174 d->initialItems = items;
175 if (enabledPlugins) {
176 d->enabledPlugins = *enabledPlugins;
177 } else {
178 const KConfigGroup globalConfig(KGlobal::config(), "PreviewSettings");
179 d->enabledPlugins = globalConfig.readEntry("Plugins", QStringList()
180 << "directorythumbnail"
181 << "imagethumbnail"
182 << "jpegthumbnail");
183 }
184 d->width = size.width();
185 d->height = size.height();
186 d->cacheWidth = d->width;
187 d->cacheHeight = d->height;
188 d->iconSize = 0;
189 d->iconAlpha = 70;
190 d->bScale = true;
191 d->bSave = true;
192 d->succeeded = false;
193 d->thumbRoot = QDir::homePath() + QLatin1String("/.thumbnails/");
194 d->ignoreMaximumSize = false;
195 d->sequenceIndex = 0;
196 d->maximumLocalSize = 0;
197 d->maximumRemoteSize = 0;
198
199 // Return to event loop first, determineNextFile() might delete this;
200 QTimer::singleShot(0, this, SLOT(startPreview()));
201}
202
203PreviewJob::~PreviewJob()
204{
205#ifdef Q_OS_UNIX
206 Q_D(PreviewJob);
207 if (d->shmaddr) {
208 shmdt((char*)d->shmaddr);
209 shmctl(d->shmid, IPC_RMID, 0);
210 }
211#endif
212}
213
214void PreviewJob::setOverlayIconSize(int size)
215{
216 Q_D(PreviewJob);
217 d->iconSize = size;
218}
219
220int PreviewJob::overlayIconSize() const
221{
222 Q_D(const PreviewJob);
223 return d->iconSize;
224}
225
226void PreviewJob::setOverlayIconAlpha(int alpha)
227{
228 Q_D(PreviewJob);
229 d->iconAlpha = qBound(0, alpha, 255);
230}
231
232int PreviewJob::overlayIconAlpha() const
233{
234 Q_D(const PreviewJob);
235 return d->iconAlpha;
236}
237
238void PreviewJob::setScaleType(ScaleType type)
239{
240 Q_D(PreviewJob);
241 switch (type) {
242 case Unscaled:
243 d->bScale = false;
244 d->bSave = false;
245 break;
246 case Scaled:
247 d->bScale = true;
248 d->bSave = false;
249 break;
250 case ScaledAndCached:
251 d->bScale = true;
252 d->bSave = true;
253 break;
254 default:
255 break;
256 }
257}
258
259PreviewJob::ScaleType PreviewJob::scaleType() const
260{
261 Q_D(const PreviewJob);
262 if (d->bScale) {
263 return d->bSave ? ScaledAndCached : Scaled;
264 }
265 return Unscaled;
266}
267
268void PreviewJobPrivate::startPreview()
269{
270 Q_Q(PreviewJob);
271 // Load the list of plugins to determine which mimetypes are supported
272 const KService::List plugins = KServiceTypeTrader::self()->query("ThumbCreator");
273 QMap<QString, KService::Ptr> mimeMap;
274 QHash<QString, QHash<QString, KService::Ptr> > protocolMap;
275 for (KService::List::ConstIterator it = plugins.constBegin(); it != plugins.constEnd(); ++it) {
276 QStringList protocols = (*it)->property("X-KDE-Protocols").toStringList();
277 const QString p = (*it)->property("X-KDE-Protocol").toString();
278 if (!p.isEmpty()) {
279 protocols.append(p);
280 }
281 foreach (const QString &protocol, protocols) {
282 QStringList mtypes = (*it)->serviceTypes();
283 // Filter out non-mimetype servicetypes
284 // TODO KDE5: use KService::mimeTypes()
285 foreach (const QString &_mtype, mtypes) {
286 if (!((*it)->hasMimeType(_mtype))) {
287 mtypes.removeAll(_mtype);
288 }
289 }
290 // Add supported mimetype for this protocol
291 QStringList &_ms = m_remoteProtocolPlugins[protocol];
292 foreach (const QString &_m, mtypes) {
293 protocolMap[protocol].insert(_m, *it);
294 if (!_ms.contains(_m)) {
295 _ms.append(_m);
296 }
297 }
298 }
299 if (enabledPlugins.contains((*it)->desktopEntryName())) {
300 const QStringList mimeTypes = (*it)->serviceTypes();
301 for (QStringList::ConstIterator mt = mimeTypes.constBegin(); mt != mimeTypes.constEnd(); ++mt)
302 mimeMap.insert(*mt, *it);
303 }
304 }
305
306 // Look for images and store the items in our todo list :)
307 bool bNeedCache = false;
308 KFileItemList::const_iterator kit = initialItems.constBegin();
309 const KFileItemList::const_iterator kend = initialItems.constEnd();
310 for ( ; kit != kend; ++kit )
311 {
312 PreviewItem item;
313 item.item = *kit;
314 const QString mimeType = item.item.mimetype();
315 KService::Ptr plugin(0);
316
317 // look for protocol-specific thumbnail plugins first
318 QHash<QString, QHash<QString, KService::Ptr> >::const_iterator it = protocolMap.constFind(item.item.url().protocol());
319 if (it != protocolMap.constEnd()) {
320 plugin = it.value().value(mimeType);
321 }
322
323 if (!plugin) {
324 QMap<QString, KService::Ptr>::ConstIterator pluginIt = mimeMap.constFind(mimeType);
325 if (pluginIt == mimeMap.constEnd()) {
326 QString groupMimeType = mimeType;
327 groupMimeType.replace(QRegExp("/.*"), "/*");
328 pluginIt = mimeMap.constFind(groupMimeType);
329
330 if (pluginIt == mimeMap.constEnd()) {
331 // check mime type inheritance, resolve aliases
332 const KMimeType::Ptr mimeInfo = KMimeType::mimeType(mimeType);
333 if (mimeInfo) {
334 const QStringList parentMimeTypes = mimeInfo->allParentMimeTypes();
335 Q_FOREACH(const QString& parentMimeType, parentMimeTypes) {
336 pluginIt = mimeMap.constFind(parentMimeType);
337 if (pluginIt != mimeMap.constEnd())
338 break;
339 }
340 }
341 }
342 }
343
344 if (pluginIt != mimeMap.constEnd()) {
345 plugin = *pluginIt;
346 }
347 }
348
349 if (plugin) {
350 item.plugin = plugin;
351 items.append(item);
352 if (!bNeedCache && bSave &&
353 ((*kit).url().protocol() != "file" ||
354 !(*kit).url().directory( KUrl::AppendTrailingSlash ).startsWith(thumbRoot)) &&
355 plugin->property("CacheThumbnail").toBool()) {
356 bNeedCache = true;
357 }
358 } else {
359 emit q->failed( *kit );
360 }
361 }
362
363 KConfigGroup cg( KGlobal::config(), "PreviewSettings" );
364 maximumLocalSize = cg.readEntry( "MaximumSize", 5*1024*1024LL /* 5MB */ );
365 maximumRemoteSize = cg.readEntry( "MaximumRemoteSize", 0 );
366
367 if (bNeedCache)
368 {
369 if (width <= 128 && height <= 128) cacheWidth = cacheHeight = 128;
370 else cacheWidth = cacheHeight = 256;
371 thumbPath = thumbRoot + (cacheWidth == 128 ? "normal/" : "large/");
372 KStandardDirs::makeDir(thumbPath, 0700);
373 }
374 else
375 bSave = false;
376
377 initialItems.clear();
378 determineNextFile();
379}
380
381void PreviewJob::removeItem( const KUrl& url )
382{
383 Q_D(PreviewJob);
384 for (QLinkedList<PreviewItem>::Iterator it = d->items.begin(); it != d->items.end(); ++it)
385 if ((*it).item.url() == url)
386 {
387 d->items.erase(it);
388 break;
389 }
390
391 if (d->currentItem.item.url() == url)
392 {
393 KJob* job = subjobs().first();
394 job->kill();
395 removeSubjob( job );
396 d->determineNextFile();
397 }
398}
399
400void KIO::PreviewJob::setSequenceIndex(int index) {
401 d_func()->sequenceIndex = index;
402}
403
404int KIO::PreviewJob::sequenceIndex() const {
405 return d_func()->sequenceIndex;
406}
407
408void PreviewJob::setIgnoreMaximumSize(bool ignoreSize)
409{
410 d_func()->ignoreMaximumSize = ignoreSize;
411}
412
413void PreviewJobPrivate::determineNextFile()
414{
415 Q_Q(PreviewJob);
416 if (!currentItem.item.isNull())
417 {
418 if (!succeeded)
419 emit q->failed( currentItem.item );
420 }
421 // No more items ?
422 if ( items.isEmpty() )
423 {
424 q->emitResult();
425 return;
426 }
427 else
428 {
429 // First, stat the orig file
430 state = PreviewJobPrivate::STATE_STATORIG;
431 currentItem = items.first();
432 succeeded = false;
433 items.removeFirst();
434 KIO::Job *job = KIO::stat( currentItem.item.url(), KIO::HideProgressInfo );
435 job->addMetaData( "no-auth-prompt", "true" );
436 q->addSubjob(job);
437 }
438}
439
440void PreviewJob::slotResult( KJob *job )
441{
442 Q_D(PreviewJob);
443
444 removeSubjob(job);
445 Q_ASSERT ( !hasSubjobs() ); // We should have only one job at a time ...
446 switch ( d->state )
447 {
448 case PreviewJobPrivate::STATE_STATORIG:
449 {
450 if (job->error()) // that's no good news...
451 {
452 // Drop this one and move on to the next one
453 d->determineNextFile();
454 return;
455 }
456 const KIO::UDSEntry entry = static_cast<KIO::StatJob*>(job)->statResult();
457 d->tOrig = entry.numberValue( KIO::UDSEntry::UDS_MODIFICATION_TIME, 0 );
458
459 bool skipCurrentItem = false;
460 const KIO::filesize_t size = (KIO::filesize_t)entry.numberValue( KIO::UDSEntry::UDS_SIZE, 0 );
461 const KUrl itemUrl = d->currentItem.item.mostLocalUrl();
462
463 if (itemUrl.isLocalFile() || KProtocolInfo::protocolClass(itemUrl.protocol()) == QLatin1String(":local"))
464 {
465 skipCurrentItem = !d->ignoreMaximumSize && size > d->maximumLocalSize
466 && !d->currentItem.plugin->property("IgnoreMaximumSize").toBool();
467 }
468 else
469 {
470 // For remote items the "IgnoreMaximumSize" plugin property is not respected
471 skipCurrentItem = !d->ignoreMaximumSize && size > d->maximumRemoteSize;
472
473 // Remote directories are not supported, don't try to do a file_copy on them
474 if (!skipCurrentItem) {
475 // TODO update item.mimeType from the UDS entry, in case it wasn't set initially
476 KMimeType::Ptr mime = d->currentItem.item.mimeTypePtr();
477 if (mime && mime->is("inode/directory")) {
478 skipCurrentItem = true;
479 }
480 }
481 }
482 if (skipCurrentItem)
483 {
484 d->determineNextFile();
485 return;
486 }
487
488 bool pluginHandlesSequences = d->currentItem.plugin->property("HandleSequences", QVariant::Bool).toBool();
489 if ( !d->currentItem.plugin->property( "CacheThumbnail" ).toBool() || (d->sequenceIndex && pluginHandlesSequences) )
490 {
491 // This preview will not be cached, no need to look for a saved thumbnail
492 // Just create it, and be done
493 d->getOrCreateThumbnail();
494 return;
495 }
496
497 if ( d->statResultThumbnail() )
498 return;
499
500 d->getOrCreateThumbnail();
501 return;
502 }
503 case PreviewJobPrivate::STATE_GETORIG:
504 {
505 if (job->error())
506 {
507 d->determineNextFile();
508 return;
509 }
510
511 d->createThumbnail( static_cast<KIO::FileCopyJob*>(job)->destUrl().toLocalFile() );
512 return;
513 }
514 case PreviewJobPrivate::STATE_CREATETHUMB:
515 {
516 if (!d->tempName.isEmpty())
517 {
518 QFile::remove(d->tempName);
519 d->tempName.clear();
520 }
521 d->determineNextFile();
522 return;
523 }
524 }
525}
526
527bool PreviewJobPrivate::statResultThumbnail()
528{
529 if ( thumbPath.isEmpty() )
530 return false;
531
532 KUrl url = currentItem.item.mostLocalUrl();
533 // Don't include the password if any
534 url.setPass(QString());
535 origName = url.url();
536
537 KMD5 md5( QFile::encodeName( origName ) );
538 thumbName = QFile::encodeName( md5.hexDigest() ) + ".png";
539
540 QImage thumb;
541 if ( !thumb.load( thumbPath + thumbName ) ) return false;
542
543 if ( thumb.text( "Thumb::URI", 0 ) != origName ||
544 thumb.text( "Thumb::MTime", 0 ).toInt() != tOrig ) return false;
545
546 QString thumbnailerVersion = currentItem.plugin->property("ThumbnailerVersion", QVariant::String).toString();
547
548 if (!thumbnailerVersion.isEmpty() && thumb.text("Software", 0).startsWith("KDE Thumbnail Generator")) {
549 //Check if the version matches
550 //The software string should read "KDE Thumbnail Generator pluginName (vX)"
551 QString softwareString = thumb.text("Software", 0).remove("KDE Thumbnail Generator").trimmed();
552 if (softwareString.isEmpty()) {
553 // The thumbnail has been created with an older version, recreating
554 return false;
555 }
556 int versionIndex = softwareString.lastIndexOf("(v");
557 if (versionIndex < 0) {
558 return false;
559 }
560
561 QString cachedVersion = softwareString.remove(0, versionIndex+2);
562 cachedVersion.chop(1);
563 uint thumbnailerMajor = thumbnailerVersion.toInt();
564 uint cachedMajor = cachedVersion.toInt();
565 if (thumbnailerMajor > cachedMajor) {
566 return false;
567 }
568 }
569
570 // Found it, use it
571 emitPreview( thumb );
572 succeeded = true;
573 determineNextFile();
574 return true;
575}
576
577
578void PreviewJobPrivate::getOrCreateThumbnail()
579{
580 Q_Q(PreviewJob);
581 // We still need to load the orig file ! (This is getting tedious) :)
582 const KFileItem& item = currentItem.item;
583 const QString localPath = item.localPath();
584 if (!localPath.isEmpty()) {
585 createThumbnail( localPath );
586 } else {
587 const KUrl fileUrl = item.url();
588 // heuristics for remote URL support
589 bool supportsProtocol = false;
590 if (m_remoteProtocolPlugins.value(fileUrl.scheme()).contains(item.mimetype())) {
591 // There's a plugin supporting this protocol and mimetype
592 supportsProtocol = true;
593 } else if (m_remoteProtocolPlugins.value("KIO").contains(item.mimetype())) {
594 // Assume KIO understands any URL, ThumbCreator slaves who have
595 // X-KDE-Protocols=KIO will get fed the remote URL directly.
596 supportsProtocol = true;
597 }
598
599 if (supportsProtocol) {
600 createThumbnail(fileUrl.url());
601 return;
602 }
603 // No plugin support access to this remote content, copy the file
604 // to the local machine, then create the thumbnail
605 state = PreviewJobPrivate::STATE_GETORIG;
606 KTemporaryFile localFile;
607 localFile.setAutoRemove(false);
608 localFile.open();
609 KUrl localURL;
610 localURL.setPath( tempName = localFile.fileName() );
611 const KUrl currentURL = item.mostLocalUrl();
612 KIO::Job * job = KIO::file_copy( currentURL, localURL, -1, KIO::Overwrite | KIO::HideProgressInfo /* No GUI */ );
613 job->addMetaData("thumbnail","1");
614 q->addSubjob(job);
615 }
616}
617
618void PreviewJobPrivate::createThumbnail( const QString &pixPath )
619{
620 Q_Q(PreviewJob);
621 state = PreviewJobPrivate::STATE_CREATETHUMB;
622 KUrl thumbURL;
623 thumbURL.setProtocol("thumbnail");
624 thumbURL.setPath(pixPath);
625 KIO::TransferJob *job = KIO::get(thumbURL, NoReload, HideProgressInfo);
626 q->addSubjob(job);
627 q->connect(job, SIGNAL(data(KIO::Job*,QByteArray)), SLOT(slotThumbData(KIO::Job*,QByteArray)));
628 bool save = bSave && currentItem.plugin->property("CacheThumbnail").toBool() && !sequenceIndex;
629 job->addMetaData("mimeType", currentItem.item.mimetype());
630 job->addMetaData("width", QString().setNum(save ? cacheWidth : width));
631 job->addMetaData("height", QString().setNum(save ? cacheHeight : height));
632 job->addMetaData("iconSize", QString().setNum(save ? 64 : iconSize));
633 job->addMetaData("iconAlpha", QString().setNum(iconAlpha));
634 job->addMetaData("plugin", currentItem.plugin->library());
635 if(sequenceIndex)
636 job->addMetaData("sequence-index", QString().setNum(sequenceIndex));
637
638#ifdef Q_OS_UNIX
639 if (shmid == -1)
640 {
641 if (shmaddr) {
642 shmdt((char*)shmaddr);
643 shmctl(shmid, IPC_RMID, 0);
644 }
645 shmid = shmget(IPC_PRIVATE, cacheWidth * cacheHeight * 4, IPC_CREAT|0600);
646 if (shmid != -1)
647 {
648 shmaddr = (uchar *)(shmat(shmid, 0, SHM_RDONLY));
649 if (shmaddr == (uchar *)-1)
650 {
651 shmctl(shmid, IPC_RMID, 0);
652 shmaddr = 0;
653 shmid = -1;
654 }
655 }
656 else
657 shmaddr = 0;
658 }
659 if (shmid != -1)
660 job->addMetaData("shmid", QString().setNum(shmid));
661#endif
662}
663
664void PreviewJobPrivate::slotThumbData(KIO::Job *, const QByteArray &data)
665{
666 bool save = bSave &&
667 currentItem.plugin->property("CacheThumbnail").toBool() &&
668 (currentItem.item.url().protocol() != "file" ||
669 !currentItem.item.url().directory( KUrl::AppendTrailingSlash ).startsWith(thumbRoot)) && !sequenceIndex;
670 QImage thumb;
671#ifdef Q_OS_UNIX
672 if (shmaddr)
673 {
674 // Keep this in sync with kdebase/kioslave/thumbnail.cpp
675 QDataStream str(data);
676 int width, height;
677 quint8 iFormat;
678 str >> width >> height >> iFormat;
679 QImage::Format format = static_cast<QImage::Format>( iFormat );
680 thumb = QImage(shmaddr, width, height, format ).copy();
681 }
682 else
683#endif
684 thumb.loadFromData(data);
685
686 if (thumb.isNull()) {
687 QDataStream s(data);
688 s >> thumb;
689 }
690
691 QString tempFileName;
692 bool savedCorrectly = false;
693 if (save)
694 {
695 thumb.setText("Thumb::URI", origName);
696 thumb.setText("Thumb::MTime", QString::number(tOrig));
697 thumb.setText("Thumb::Size", number(currentItem.item.size()));
698 thumb.setText("Thumb::Mimetype", currentItem.item.mimetype());
699 QString thumbnailerVersion = currentItem.plugin->property("ThumbnailerVersion", QVariant::String).toString();
700 QString signature = QString("KDE Thumbnail Generator "+currentItem.plugin->name());
701 if (!thumbnailerVersion.isEmpty()) {
702 signature.append(" (v"+thumbnailerVersion+')');
703 }
704 thumb.setText("Software", signature);
705 KTemporaryFile temp;
706 temp.setPrefix(thumbPath + "kde-tmp-");
707 temp.setSuffix(".png");
708 temp.setAutoRemove(false);
709 if (temp.open()) //Only try to write out the thumbnail if we
710 { //actually created the temp file.
711 tempFileName = temp.fileName();
712 savedCorrectly = thumb.save(tempFileName, "PNG");
713 }
714 }
715 if(savedCorrectly)
716 {
717 Q_ASSERT(!tempFileName.isEmpty());
718 KDE::rename(tempFileName, thumbPath + thumbName);
719 }
720 emitPreview( thumb );
721 succeeded = true;
722}
723
724void PreviewJobPrivate::emitPreview(const QImage &thumb)
725{
726 Q_Q(PreviewJob);
727 QPixmap pix;
728 if (thumb.width() > width || thumb.height() > height)
729 pix = QPixmap::fromImage( thumb.scaled(QSize(width, height), Qt::KeepAspectRatio, Qt::SmoothTransformation) );
730 else
731 pix = QPixmap::fromImage( thumb );
732 emit q->gotPreview(currentItem.item, pix);
733}
734
735QStringList PreviewJob::availablePlugins()
736{
737 QStringList result;
738 const KService::List plugins = KServiceTypeTrader::self()->query("ThumbCreator");
739 for (KService::List::ConstIterator it = plugins.begin(); it != plugins.end(); ++it)
740 if (!result.contains((*it)->desktopEntryName()))
741 result.append((*it)->desktopEntryName());
742 return result;
743}
744
745QStringList PreviewJob::supportedMimeTypes()
746{
747 QStringList result;
748 const KService::List plugins = KServiceTypeTrader::self()->query("ThumbCreator");
749 for (KService::List::ConstIterator it = plugins.begin(); it != plugins.end(); ++it)
750 result += (*it)->serviceTypes();
751 return result;
752}
753
754#ifndef KDE_NO_DEPRECATED
755PreviewJob *KIO::filePreview( const KFileItemList &items, int width, int height,
756 int iconSize, int iconAlpha, bool scale, bool save,
757 const QStringList *enabledPlugins )
758{
759 return new PreviewJob(items, width, height, iconSize, iconAlpha,
760 scale, save, enabledPlugins);
761}
762
763PreviewJob *KIO::filePreview( const KUrl::List &items, int width, int height,
764 int iconSize, int iconAlpha, bool scale, bool save,
765 const QStringList *enabledPlugins )
766{
767 KFileItemList fileItems;
768 for (KUrl::List::ConstIterator it = items.begin(); it != items.end(); ++it) {
769 Q_ASSERT( (*it).isValid() ); // please call us with valid urls only
770 fileItems.append(KFileItem(KFileItem::Unknown, KFileItem::Unknown, *it, true));
771 }
772 return new PreviewJob(fileItems, width, height, iconSize, iconAlpha,
773 scale, save, enabledPlugins);
774}
775#endif
776
777PreviewJob *KIO::filePreview(const KFileItemList &items, const QSize &size, const QStringList *enabledPlugins)
778{
779 return new PreviewJob(items, size, enabledPlugins);
780}
781
782#ifndef KDE_NO_DEPRECATED
783KIO::filesize_t PreviewJob::maximumFileSize()
784{
785 KConfigGroup cg( KGlobal::config(), "PreviewSettings" );
786 return cg.readEntry( "MaximumSize", 5*1024*1024LL /* 5MB */ );
787}
788#endif
789
790#include "previewjob.moc"
KCompositeJob::subjobs
const QList< KJob * > & subjobs() const
KCompositeJob::hasSubjobs
bool hasSubjobs()
KConfigGroup
KConfigGroup::readEntry
QString readEntry(const char *key, const char *aDefault=0) const
KFileItemList
List of KFileItems, which adds a few helper methods to QList<KFileItem>.
Definition: kfileitem.h:675
KFileItem
A KFileItem is a generic class to handle a file, local or remote.
Definition: kfileitem.h:46
KFileItem::mostLocalUrl
KUrl mostLocalUrl(bool &local) const
Tries to give a local URL for this file item if possible.
Definition: kfileitem.cpp:1470
KFileItem::mimetype
QString mimetype() const
Returns the mimetype of the file item.
Definition: kfileitem.cpp:770
KFileItem::localPath
QString localPath() const
Returns the local path if isLocalFile() == true or the KIO item has a UDS_LOCAL_PATH atom.
Definition: kfileitem.cpp:602
KFileItem::url
KUrl url() const
Returns the url of the file.
Definition: kfileitem.cpp:1543
KFileItem::Unknown
@ Unknown
Definition: kfileitem.h:48
KIO::FileCopyJob
The FileCopyJob copies data from one place to another.
Definition: jobclasses.h:856
KIO::FileCopyJob::destUrl
KUrl destUrl() const
Returns the destination URL.
Definition: job.cpp:2087
KIO::JobPrivate
Definition: job_p.h:40
KIO::Job
The base class for all jobs.
Definition: jobclasses.h:94
KIO::Job::removeSubjob
virtual bool removeSubjob(KJob *job)
Mark a sub job as being done.
Definition: job.cpp:118
KIO::Job::addMetaData
void addMetaData(const QString &key, const QString &value)
Add key/value pair to the meta data that is sent to the slave.
Definition: job.cpp:264
KIO::PreviewJob
KIO Job to get a thumbnail picture.
Definition: previewjob.h:39
KIO::PreviewJob::sequenceIndex
int sequenceIndex() const
Returns the currently set sequence index.
Definition: previewjob.cpp:404
KIO::PreviewJob::setScaleType
void setScaleType(ScaleType type)
Sets the scale type for the generated preview.
Definition: previewjob.cpp:238
KIO::PreviewJob::~PreviewJob
virtual ~PreviewJob()
Definition: previewjob.cpp:203
KIO::PreviewJob::supportedMimeTypes
static QStringList supportedMimeTypes()
Returns a list of all supported MIME types.
Definition: previewjob.cpp:745
KIO::PreviewJob::availablePlugins
static QStringList availablePlugins()
Returns a list of all available preview plugins.
Definition: previewjob.cpp:735
KIO::PreviewJob::removeItem
void removeItem(const KUrl &url)
Removes an item from preview processing.
Definition: previewjob.cpp:381
KIO::PreviewJob::slotResult
virtual void slotResult(KJob *job)
Definition: previewjob.cpp:440
KIO::PreviewJob::ScaleType
ScaleType
Specifies the type of scaling that is applied to the generated preview.
Definition: previewjob.h:46
KIO::PreviewJob::Unscaled
@ Unscaled
The original size of the preview will be returned.
Definition: previewjob.h:51
KIO::PreviewJob::Scaled
@ Scaled
The preview will be scaled to the size specified when constructing the PreviewJob.
Definition: previewjob.h:56
KIO::PreviewJob::ScaledAndCached
@ ScaledAndCached
The preview will be scaled to the size specified when constructing the PreviewJob.
Definition: previewjob.h:62
KIO::PreviewJob::maximumFileSize
static KIO::filesize_t maximumFileSize()
Returns the default "maximum file size", in bytes, used by PreviewJob.
Definition: previewjob.cpp:783
KIO::PreviewJob::setOverlayIconSize
void setOverlayIconSize(int size)
Sets the size of the MIME-type icon which overlays the preview.
Definition: previewjob.cpp:214
KIO::PreviewJob::PreviewJob
PreviewJob(const KFileItemList &items, int width, int height, int iconSize, int iconAlpha, bool scale, bool save, const QStringList *enabledPlugins)
Creates a new PreviewJob.
Definition: previewjob.cpp:134
KIO::PreviewJob::setOverlayIconAlpha
void setOverlayIconAlpha(int alpha)
Sets the alpha-value for the MIME-type icon which overlays the preview.
Definition: previewjob.cpp:226
KIO::PreviewJob::setSequenceIndex
void setSequenceIndex(int index)
Sets the sequence index given to the thumb creators.
Definition: previewjob.cpp:400
KIO::PreviewJob::overlayIconSize
int overlayIconSize() const
Definition: previewjob.cpp:220
KIO::PreviewJob::scaleType
ScaleType scaleType() const
Definition: previewjob.cpp:259
KIO::PreviewJob::setIgnoreMaximumSize
void setIgnoreMaximumSize(bool ignoreSize=true)
If ignoreSize is true, then the preview is always generated regardless of the settings.
Definition: previewjob.cpp:408
KIO::PreviewJob::overlayIconAlpha
int overlayIconAlpha() const
Definition: previewjob.cpp:232
KIO::StatJob
A KIO job that retrieves information about a file or directory.
Definition: jobclasses.h:440
KIO::TransferJob
The transfer job pumps data into and/or out of a Slave.
Definition: jobclasses.h:555
KIO::UDSEntry
Universal Directory Service.
Definition: udsentry.h:59
KIO::UDSEntry::numberValue
long long numberValue(uint field, long long defaultValue=0) const
Definition: udsentry.cpp:78
KIO::UDSEntry::UDS_MODIFICATION_TIME
@ UDS_MODIFICATION_TIME
The last time the file was modified.
Definition: udsentry.h:173
KIO::UDSEntry::UDS_SIZE
@ UDS_SIZE
Size of the file.
Definition: udsentry.h:144
KJob
KJob::error
int error() const
KJob::kill
bool kill(KillVerbosity verbosity=Quietly)
KJob::result
void result(KJob *job)
KMD5
KMimeType::mimeType
static Ptr mimeType(const QString &name, FindByNameOption options=ResolveAliases)
KServiceTypeTrader::self
static KServiceTypeTrader * self()
KServiceTypeTrader::query
KService::List query(const QString &servicetype, const QString &constraint=QString()) const
KSharedPtr< KService >
KStandardDirs::makeDir
static bool makeDir(const QString &dir, int mode=0755)
KTemporaryFile
KTemporaryFile::setPrefix
void setPrefix(const QString &prefix)
KTemporaryFile::setSuffix
void setSuffix(const QString &suffix)
KUrl::List
KUrl
KUrl::AppendTrailingSlash
AppendTrailingSlash
KUrl::url
QString url(AdjustPathOption trailing=LeaveTrailingSlash) const
KUrl::setProtocol
void setProtocol(const QString &proto)
KUrl::isLocalFile
bool isLocalFile() const
KUrl::setPath
void setPath(const QString &path)
KUrl::setPass
void setPass(const QString &pass)
KUrl::protocol
QString protocol() const
KUrl::toLocalFile
QString toLocalFile(AdjustPathOption trailing=LeaveTrailingSlash) const
QHash
QList< Ptr >
QMap
job_p.h
jobuidelegate.h
kcodecs.h
kconfiggroup.h
kdebug.h
kfileitem.h
kglobal.h
kprotocolinfo.h
kservice.h
kservicetypetrader.h
kstandarddirs.h
ktemporaryfile.h
KDE::rename
int rename(const QString &in, const QString &out)
KGlobal::config
KSharedConfigPtr config()
KIO
A namespace for KIO globals.
Definition: kbookmarkmenu.h:55
KIO::stat
StatJob * stat(const KUrl &url, JobFlags flags=DefaultFlags)
Find all details for one file or directory.
Definition: job.cpp:924
KIO::file_copy
FileCopyJob * file_copy(const KUrl &src, const KUrl &dest, int permissions=-1, JobFlags flags=DefaultFlags)
Copy a single file.
Definition: job.cpp:2473
KIO::get
TransferJob * get(const KUrl &url, LoadType reload=NoReload, JobFlags flags=DefaultFlags)
Get (a.k.a.
Definition: job.cpp:1369
KIO::filePreview
PreviewJob * filePreview(const KFileItemList &items, int width, int height=0, int iconSize=0, int iconAlpha=70, bool scale=true, bool save=true, const QStringList *enabledPlugins=0)
Creates a PreviewJob to generate or retrieve a preview image for the given URL.
Definition: previewjob.cpp:755
KIO::NoReload
@ NoReload
Definition: job.h:29
KIO::HideProgressInfo
@ HideProgressInfo
Hide progress information dialog, i.e.
Definition: jobclasses.h:51
KIO::Overwrite
@ Overwrite
When set, automatically overwrite the destination if it exists already.
Definition: jobclasses.h:67
KIO::filesize_t
qulonglong filesize_t
64-bit file size
Definition: global.h:57
KIO::number
QString number(KIO::filesize_t size)
Converts a size to a string representation Not unlike QString::number(...)
Definition: global.cpp:63
KImageIO::mimeTypes
QStringList mimeTypes(Mode mode=Writing)
Returns a list of MIME types for all KImageIO supported formats.
Definition: kimageio.cpp:64
save
KAction * save(const QObject *recvr, const char *slot, QObject *parent)
previewjob.h
This file is part of the KDE documentation.
Documentation copyright © 1996-2023 The KDE developers.
Generated on Mon Feb 20 2023 00:00:00 by doxygen 1.9.6 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.

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-4.14.38 API Reference

Skip menu "kdelibs-4.14.38 API Reference"
  • 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
Report problems with this website to our bug tracking system.
Contact the specific authors with questions and comments about the page contents.

KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal