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

KIO

  • sources
  • kde-4.14
  • kdelibs
  • 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 
56 namespace KIO { struct PreviewItem; }
57 using namespace KIO;
58 
59 struct KIO::PreviewItem
60 {
61  KFileItem item;
62  KService::Ptr plugin;
63 };
64 
65 class KIO::PreviewJobPrivate: public KIO::JobPrivate
66 {
67 public:
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
134 PreviewJob::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 
165 PreviewJob::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 
203 PreviewJob::~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 
214 void PreviewJob::setOverlayIconSize(int size)
215 {
216  Q_D(PreviewJob);
217  d->iconSize = size;
218 }
219 
220 int PreviewJob::overlayIconSize() const
221 {
222  Q_D(const PreviewJob);
223  return d->iconSize;
224 }
225 
226 void PreviewJob::setOverlayIconAlpha(int alpha)
227 {
228  Q_D(PreviewJob);
229  d->iconAlpha = qBound(0, alpha, 255);
230 }
231 
232 int PreviewJob::overlayIconAlpha() const
233 {
234  Q_D(const PreviewJob);
235  return d->iconAlpha;
236 }
237 
238 void 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 
259 PreviewJob::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 
268 void 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 
381 void 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 
400 void KIO::PreviewJob::setSequenceIndex(int index) {
401  d_func()->sequenceIndex = index;
402 }
403 
404 int KIO::PreviewJob::sequenceIndex() const {
405  return d_func()->sequenceIndex;
406 }
407 
408 void PreviewJob::setIgnoreMaximumSize(bool ignoreSize)
409 {
410  d_func()->ignoreMaximumSize = ignoreSize;
411 }
412 
413 void 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 
440 void 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 
527 bool 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 
578 void 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 
618 void 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 
664 void 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 
724 void 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 
735 QStringList 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 
745 QStringList 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
755 PreviewJob *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 
763 PreviewJob *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 
777 PreviewJob *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
783 KIO::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"
KIO::PreviewJob::removeItem
void removeItem(const KUrl &url)
Removes an item from preview processing.
Definition: previewjob.cpp:381
KIO::Overwrite
When set, automatically overwrite the destination if it exists already.
Definition: jobclasses.h:67
KIO::PreviewJob::availablePlugins
static QStringList availablePlugins()
Returns a list of all available preview plugins.
Definition: previewjob.cpp:735
KSharedPtr< KService >
QImage::loadFromData
bool loadFromData(const uchar *data, int len, const char *format)
QString::append
QString & append(QChar ch)
KIO::filesize_t
qulonglong filesize_t
64-bit file size
Definition: global.h:57
QHash::insert
iterator insert(const Key &key, const T &value)
QSize::width
int width() const
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
kdebug.h
KIO::PreviewJob::setOverlayIconSize
void setOverlayIconSize(int size)
Sets the size of the MIME-type icon which overlays the preview.
Definition: previewjob.cpp:214
KTemporaryFile::setPrefix
void setPrefix(const QString &prefix)
QByteArray
KIO::UDSEntry
Universal Directory Service.
Definition: udsentry.h:58
KFileItem::mimetype
QString mimetype() const
Returns the mimetype of the file item.
Definition: kfileitem.cpp:770
QFile::remove
bool remove()
KServiceTypeTrader::self
static KServiceTypeTrader * self()
QDataStream
QImage::save
bool save(const QString &fileName, const char *format, int quality) const
KIO::HideProgressInfo
Hide progress information dialog, i.e.
Definition: jobclasses.h:51
KIO::PreviewJob::setScaleType
void setScaleType(ScaleType type)
Sets the scale type for the generated preview.
Definition: previewjob.cpp:238
QMap
Definition: netaccess.h:36
QStringList::contains
bool contains(const QString &str, Qt::CaseSensitivity cs) const
KIO::get
TransferJob * get(const KUrl &url, LoadType reload=NoReload, JobFlags flags=DefaultFlags)
Get (a.k.a.
Definition: job.cpp:1369
KDE::rename
int rename(const QString &in, const QString &out)
KIO::stat
StatJob * stat(const KUrl &url, JobFlags flags=DefaultFlags)
Find all details for one file or directory.
Definition: job.cpp:924
QPixmap::fromImage
QPixmap fromImage(const QImage &image, QFlags< Qt::ImageConversionFlag > flags)
QHash::constFind
const_iterator constFind(const Key &key) const
KIO::StatJob
A KIO job that retrieves information about a file or directory.
Definition: jobclasses.h:440
QMap::constFind
const_iterator constFind(const Key &key) const
QImage::isNull
bool isNull() const
KTemporaryFile
KIO::Job::removeSubjob
virtual bool removeSubjob(KJob *job)
Mark a sub job as being done.
Definition: job.cpp:118
QString::remove
QString & remove(int position, int n)
QImage::copy
QImage copy(const QRect &rectangle) const
KTemporaryFile::setSuffix
void setSuffix(const QString &suffix)
QString::chop
void chop(int n)
QDir::homePath
QString homePath()
KUrl
KIO::PreviewJob::Unscaled
The original size of the preview will be returned.
Definition: previewjob.h:51
KIO::PreviewJob::overlayIconAlpha
int overlayIconAlpha() const
Definition: previewjob.cpp:232
KGlobal::config
KSharedConfigPtr config()
QString::lastIndexOf
int lastIndexOf(QChar ch, int from, Qt::CaseSensitivity cs) const
KUrl::setPath
void setPath(const QString &path)
KStandardDirs::makeDir
static bool makeDir(const QString &dir, int mode=0755)
KFileItem::Unknown
Definition: kfileitem.h:48
kservicetypetrader.h
QLinkedList< PreviewItem >
QRegExp
QImage::setText
void setText(const QString &key, const QString &text)
kglobal.h
KIO::PreviewJob::sequenceIndex
int sequenceIndex() const
Returns the currently set sequence index.
Definition: previewjob.cpp:404
KUrl::setProtocol
void setProtocol(const QString &proto)
QString::number
QString number(int n, int base)
QList::append
void append(const T &value)
QObject::property
QVariant property(const char *name) const
QHash::constEnd
const_iterator constEnd() const
KIO::PreviewJob::maximumFileSize
static KIO::filesize_t maximumFileSize()
Returns the default "maximum file size", in bytes, used by PreviewJob.
Definition: previewjob.cpp:783
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::PreviewJob::scaleType
ScaleType scaleType() const
Definition: previewjob.cpp:259
KIO::UDSEntry::numberValue
long long numberValue(uint field, long long defaultValue=0) const
Definition: udsentry.cpp:78
QHash< QString, QStringList >
QImage::width
int width() const
KIO::PreviewJob::~PreviewJob
virtual ~PreviewJob()
Definition: previewjob.cpp:203
KUrl::protocol
QString protocol() const
QTemporaryFile::setAutoRemove
void setAutoRemove(bool b)
QString::toInt
int toInt(bool *ok, int base) const
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
QString::isEmpty
bool isEmpty() const
previewjob.h
QList::removeAll
int removeAll(const T &value)
QString::trimmed
QString trimmed() const
QMap::constEnd
const_iterator constEnd() const
QHash::begin
iterator begin()
KFileItemList
List of KFileItems, which adds a few helper methods to QList.
Definition: kfileitem.h:674
KUrl::setPass
void setPass(const QString &pass)
QList::first
T & first()
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
QString
QList
KProtocolInfo::protocolClass
static QString protocolClass(const QString &protocol)
QUrl::scheme
QString scheme() const
QStringList
KImageIO::mimeTypes
QStringList mimeTypes(Mode mode=Writing)
Returns a list of MIME types for all KImageIO supported formats.
Definition: kimageio.cpp:64
kservice.h
QPixmap
KIO::UDSEntry::UDS_MODIFICATION_TIME
The last time the file was modified.
Definition: udsentry.h:173
jobuidelegate.h
QList::end
iterator end()
QHash::value
const T value(const Key &key) const
kprotocolinfo.h
KIO::PreviewJob
KIO Job to get a thumbnail picture.
Definition: previewjob.h:38
QSize
KMD5
QImage
QTemporaryFile::fileName
QString fileName() const
KConfigGroup
job_p.h
QString::replace
QString & replace(int position, int n, QChar after)
KUrl::List
KServiceTypeTrader::query
KService::List query(const QString &servicetype, const QString &constraint=QString()) const
KIO::PreviewJob::ScaledAndCached
The preview will be scaled to the size specified when constructing the PreviewJob.
Definition: previewjob.h:62
ktemporaryfile.h
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
QLatin1String
kstandarddirs.h
KIO::PreviewJob::setOverlayIconAlpha
void setOverlayIconAlpha(int alpha)
Sets the alpha-value for the MIME-type icon which overlays the preview.
Definition: previewjob.cpp:226
QList::ConstIterator
typedef ConstIterator
QSize::height
int height() const
KIO::Job
The base class for all jobs.
Definition: jobclasses.h:94
KIO::NoReload
Definition: job.h:29
KCompositeJob::subjobs
const QList< KJob * > & subjobs() const
KUrl::AppendTrailingSlash
QVariant::toBool
bool toBool() const
KCompositeJob::hasSubjobs
bool hasSubjobs()
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
QImage::height
int height() const
QMap::insert
iterator insert(const Key &key, const T &value)
KIO::PreviewJob::ScaleType
ScaleType
Specifies the type of scaling that is applied to the generated preview.
Definition: previewjob.h:46
KUrl::url
QString url(AdjustPathOption trailing=LeaveTrailingSlash) const
kcodecs.h
KCompositeJob::result
void result(KJob *job)
KIO::PreviewJob::slotResult
virtual void slotResult(KJob *job)
Definition: previewjob.cpp:440
QHash::end
iterator end()
QList::constEnd
const_iterator constEnd() const
KIO::TransferJob
The transfer job pumps data into and/or out of a Slave.
Definition: jobclasses.h:555
KIO::PreviewJob::supportedMimeTypes
static QStringList supportedMimeTypes()
Returns a list of all supported MIME types.
Definition: previewjob.cpp:745
QList::constBegin
const_iterator constBegin() const
KUrl::isLocalFile
bool isLocalFile() const
save
KAction * save(const QObject *recvr, const char *slot, QObject *parent)
KIO::JobPrivate
Definition: job_p.h:39
QTemporaryFile::open
bool open()
KConfigGroup::readEntry
T readEntry(const QString &key, const T &aDefault) const
KJob
KIO::UDSEntry::UDS_SIZE
Size of the file.
Definition: udsentry.h:144
QList::begin
iterator begin()
kfileitem.h
KIO::PreviewJob::Scaled
The preview will be scaled to the size specified when constructing the PreviewJob.
Definition: previewjob.h:56
QImage::scaled
QImage scaled(int width, int height, Qt::AspectRatioMode aspectRatioMode, Qt::TransformationMode transformMode) const
KFileItem::url
KUrl url() const
Returns the url of the file.
Definition: kfileitem.cpp:1543
QFile::encodeName
QByteArray encodeName(const QString &fileName)
KFileItem::mostLocalUrl
KUrl mostLocalUrl(bool &local) const
Tries to give a local URL for this file item if possible.
Definition: kfileitem.cpp:1470
KFileItem
A KFileItem is a generic class to handle a file, local or remote.
Definition: kfileitem.h:45
kconfiggroup.h
KIO::PreviewJob::overlayIconSize
int overlayIconSize() const
Definition: previewjob.cpp:220
KIO::number
QString number(KIO::filesize_t size)
Converts a size to a string representation Not unlike QString::number(...)
Definition: global.cpp:63
QTimer::singleShot
singleShot
KIO::PreviewJob::setSequenceIndex
void setSequenceIndex(int index)
Sets the sequence index given to the thumb creators.
Definition: previewjob.cpp:400
This file is part of the KDE documentation.
Documentation copyright © 1996-2020 The KDE developers.
Generated on Mon Jun 22 2020 13:24:53 by doxygen 1.8.7 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 API Reference

Skip menu "kdelibs 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

Search



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