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

KFile

  • sources
  • kde-4.14
  • kdelibs
  • kfile
kfilepreviewgenerator.cpp
Go to the documentation of this file.
1 /*******************************************************************************
2  * Copyright (C) 2008-2009 by Peter Penz <peter.penz@gmx.at> *
3  * *
4  * This library is free software; you can redistribute it and/or *
5  * modify it under the terms of the GNU Library General Public *
6  * License as published by the Free Software Foundation; either *
7  * version 2 of the License, or (at your option) any later version. *
8  * *
9  * This library is distributed in the hope that it will be useful, *
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of *
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
12  * Library General Public License for more details. *
13  * *
14  * You should have received a copy of the GNU Library General Public License *
15  * along with this library; see the file COPYING.LIB. If not, write to *
16  * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, *
17  * Boston, MA 02110-1301, USA. *
18  *******************************************************************************/
19 
20 #include "kfilepreviewgenerator.h"
21 
22 #include "../kio/kio/defaultviewadapter_p.h" // KDE5 TODO: move this class here
23 #include "../kio/kio/imagefilter_p.h"
24 #include <config.h> // for HAVE_XRENDER
25 #include <kconfiggroup.h>
26 #include <kfileitem.h>
27 #include <kiconeffect.h>
28 #include <kio/previewjob.h>
29 #include <kdirlister.h>
30 #include <kdirmodel.h>
31 #include <ksharedconfig.h>
32 
33 #include <QApplication>
34 #include <QAbstractItemView>
35 #include <QAbstractProxyModel>
36 #include <QClipboard>
37 #include <QColor>
38 #include <QHash>
39 #include <QList>
40 #include <QListView>
41 #include <QPainter>
42 #include <QPixmap>
43 #include <QScrollBar>
44 #include <QIcon>
45 
46 #if defined(Q_WS_X11) && defined(HAVE_XRENDER)
47 # include <QX11Info>
48 # include <X11/Xlib.h>
49 # include <X11/extensions/Xrender.h>
50 #endif
51 
72 class KFilePreviewGenerator::LayoutBlocker
73 {
74 public:
75  LayoutBlocker(QAbstractItemView* view) :
76  m_uniformSizes(false),
77  m_view(qobject_cast<QListView*>(view))
78  {
79  if (m_view != 0) {
80  m_uniformSizes = m_view->uniformItemSizes();
81  m_view->setUniformItemSizes(true);
82  }
83  }
84 
85  ~LayoutBlocker()
86  {
87  if (m_view != 0) {
88  m_view->setUniformItemSizes(m_uniformSizes);
89  }
90  }
91 
92 private:
93  bool m_uniformSizes;
94  QListView* m_view;
95 };
96 
98 class KFilePreviewGenerator::TileSet
99 {
100 public:
101  enum { LeftMargin = 3, TopMargin = 2, RightMargin = 3, BottomMargin = 4 };
102 
103  enum Tile { TopLeftCorner = 0, TopSide, TopRightCorner, LeftSide,
104  RightSide, BottomLeftCorner, BottomSide, BottomRightCorner,
105  NumTiles };
106 
107  TileSet()
108  {
109  QImage image(8 * 3, 8 * 3, QImage::Format_ARGB32_Premultiplied);
110 
111  QPainter p(&image);
112  p.setCompositionMode(QPainter::CompositionMode_Source);
113  p.fillRect(image.rect(), Qt::transparent);
114  p.fillRect(image.rect().adjusted(3, 3, -3, -3), Qt::black);
115  p.end();
116 
117  KIO::ImageFilter::shadowBlur(image, 3, Qt::black);
118 
119  QPixmap pixmap = QPixmap::fromImage(image);
120  m_tiles[TopLeftCorner] = pixmap.copy(0, 0, 8, 8);
121  m_tiles[TopSide] = pixmap.copy(8, 0, 8, 8);
122  m_tiles[TopRightCorner] = pixmap.copy(16, 0, 8, 8);
123  m_tiles[LeftSide] = pixmap.copy(0, 8, 8, 8);
124  m_tiles[RightSide] = pixmap.copy(16, 8, 8, 8);
125  m_tiles[BottomLeftCorner] = pixmap.copy(0, 16, 8, 8);
126  m_tiles[BottomSide] = pixmap.copy(8, 16, 8, 8);
127  m_tiles[BottomRightCorner] = pixmap.copy(16, 16, 8, 8);
128  }
129 
130  void paint(QPainter* p, const QRect& r)
131  {
132  p->drawPixmap(r.topLeft(), m_tiles[TopLeftCorner]);
133  if (r.width() - 16 > 0) {
134  p->drawTiledPixmap(r.x() + 8, r.y(), r.width() - 16, 8, m_tiles[TopSide]);
135  }
136  p->drawPixmap(r.right() - 8 + 1, r.y(), m_tiles[TopRightCorner]);
137  if (r.height() - 16 > 0) {
138  p->drawTiledPixmap(r.x(), r.y() + 8, 8, r.height() - 16, m_tiles[LeftSide]);
139  p->drawTiledPixmap(r.right() - 8 + 1, r.y() + 8, 8, r.height() - 16, m_tiles[RightSide]);
140  }
141  p->drawPixmap(r.x(), r.bottom() - 8 + 1, m_tiles[BottomLeftCorner]);
142  if (r.width() - 16 > 0) {
143  p->drawTiledPixmap(r.x() + 8, r.bottom() - 8 + 1, r.width() - 16, 8, m_tiles[BottomSide]);
144  }
145  p->drawPixmap(r.right() - 8 + 1, r.bottom() - 8 + 1, m_tiles[BottomRightCorner]);
146 
147  const QRect contentRect = r.adjusted(LeftMargin + 1, TopMargin + 1,
148  -(RightMargin + 1), -(BottomMargin + 1));
149  p->fillRect(contentRect, Qt::transparent);
150  }
151 
152 private:
153  QPixmap m_tiles[NumTiles];
154 };
155 
156 class KFilePreviewGenerator::Private
157 {
158 public:
159  Private(KFilePreviewGenerator* parent,
160  KAbstractViewAdapter* viewAdapter,
161  QAbstractItemModel* model);
162  ~Private();
163 
168  void requestSequenceIcon(const QModelIndex& index, int sequenceIndex);
169 
173  void updateIcons(const KFileItemList& items);
174 
179  void updateIcons(const QModelIndex& topLeft, const QModelIndex& bottomRight);
180 
186  void addToPreviewQueue(const KFileItem& item, const QPixmap& pixmap);
187 
192  void slotPreviewJobFinished(KJob* job);
193 
195  void updateCutItems();
196 
201  void clearCutItemsCache();
202 
207  void dispatchIconUpdateQueue();
208 
214  void pauseIconUpdates();
215 
221  void resumeIconUpdates();
222 
227  void startMimeTypeResolving();
228 
233  void resolveMimeType();
234 
239  bool isCutItem(const KFileItem& item) const;
240 
245  void applyCutItemEffect(const KFileItemList& items);
246 
251  bool applyImageFrame(QPixmap& icon);
252 
258  void limitToSize(QPixmap& icon, const QSize& maxSize);
259 
264  void createPreviews(const KFileItemList& items);
265 
270  void startPreviewJob(const KFileItemList& items, int width, int height);
271 
273  void killPreviewJobs();
274 
281  void orderItems(KFileItemList& items);
282 
287  bool decodeIsCutSelection(const QMimeData* mimeData);
288 
293  void addItemsToList(const QModelIndex& index, KFileItemList& list);
294 
299  void delayedIconUpdate();
300 
304  void rowsAboutToBeRemoved(const QModelIndex& parent, int start, int end);
305 
307  struct ItemInfo
308  {
309  KUrl url;
310  QPixmap pixmap;
311  };
312 
317  class DataChangeObtainer
318  {
319  public:
320  DataChangeObtainer(KFilePreviewGenerator::Private* generator) :
321  m_gen(generator) { ++m_gen->m_internalDataChange; }
322  ~DataChangeObtainer() { --m_gen->m_internalDataChange; }
323  private:
324  KFilePreviewGenerator::Private* m_gen;
325  };
326 
327  bool m_previewShown;
328 
333  bool m_clearItemQueues;
334 
338  bool m_hasCutSelection;
339 
344  bool m_iconUpdatesPaused;
345 
351  int m_internalDataChange;
352 
353  int m_pendingVisibleIconUpdates;
354 
355  KAbstractViewAdapter* m_viewAdapter;
356  QAbstractItemView* m_itemView;
357  QTimer* m_iconUpdateTimer;
358  QTimer* m_scrollAreaTimer;
359  QList<KJob*> m_previewJobs;
360  QWeakPointer<KDirModel> m_dirModel;
361  QAbstractProxyModel* m_proxyModel;
362 
370  QHash<KUrl, QPixmap> m_cutItemsCache;
371  QList<ItemInfo> m_previews;
372  QMap<KUrl, int> m_sequenceIndices;
373 
380  QHash<KUrl, bool> m_changedItems;
381  QTimer* m_changedItemsTimer;
382 
387  KFileItemList m_pendingItems;
388 
393  KFileItemList m_dispatchedItems;
394 
395  KFileItemList m_resolvedMimeTypes;
396 
397  QStringList m_enabledPlugins;
398 
399  TileSet* m_tileSet;
400 
401 private:
402  KFilePreviewGenerator* const q;
403 
404 };
405 
406 KFilePreviewGenerator::Private::Private(KFilePreviewGenerator* parent,
407  KAbstractViewAdapter* viewAdapter,
408  QAbstractItemModel* model) :
409  m_previewShown(true),
410  m_clearItemQueues(true),
411  m_hasCutSelection(false),
412  m_iconUpdatesPaused(false),
413  m_internalDataChange(0),
414  m_pendingVisibleIconUpdates(0),
415  m_viewAdapter(viewAdapter),
416  m_itemView(0),
417  m_iconUpdateTimer(0),
418  m_scrollAreaTimer(0),
419  m_previewJobs(),
420  m_proxyModel(0),
421  m_cutItemsCache(),
422  m_previews(),
423  m_sequenceIndices(),
424  m_changedItems(),
425  m_changedItemsTimer(0),
426  m_pendingItems(),
427  m_dispatchedItems(),
428  m_resolvedMimeTypes(),
429  m_enabledPlugins(),
430  m_tileSet(0),
431  q(parent)
432 {
433  if (!m_viewAdapter->iconSize().isValid()) {
434  m_previewShown = false;
435  }
436 
437  m_proxyModel = qobject_cast<QAbstractProxyModel*>(model);
438  m_dirModel = (m_proxyModel == 0) ?
439  qobject_cast<KDirModel*>(model) :
440  qobject_cast<KDirModel*>(m_proxyModel->sourceModel());
441  if (!m_dirModel) {
442  // previews can only get generated for directory models
443  m_previewShown = false;
444  } else {
445  KDirModel* dirModel = m_dirModel.data();
446  connect(dirModel->dirLister(), SIGNAL(newItems(KFileItemList)),
447  q, SLOT(updateIcons(KFileItemList)));
448  connect(dirModel, SIGNAL(dataChanged(QModelIndex,QModelIndex)),
449  q, SLOT(updateIcons(QModelIndex,QModelIndex)));
450  connect(dirModel, SIGNAL(needSequenceIcon(QModelIndex,int)),
451  q, SLOT(requestSequenceIcon(QModelIndex,int)));
452  connect(dirModel, SIGNAL(rowsAboutToBeRemoved(QModelIndex,int,int)),
453  q, SLOT(rowsAboutToBeRemoved(QModelIndex,int,int)));
454  }
455 
456  QClipboard* clipboard = QApplication::clipboard();
457  connect(clipboard, SIGNAL(dataChanged()),
458  q, SLOT(updateCutItems()));
459 
460  m_iconUpdateTimer = new QTimer(q);
461  m_iconUpdateTimer->setSingleShot(true);
462  m_iconUpdateTimer->setInterval(200);
463  connect(m_iconUpdateTimer, SIGNAL(timeout()), q, SLOT(dispatchIconUpdateQueue()));
464 
465  // Whenever the scrollbar values have been changed, the pending previews should
466  // be reordered in a way that the previews for the visible items are generated
467  // first. The reordering is done with a small delay, so that during moving the
468  // scrollbars the CPU load is kept low.
469  m_scrollAreaTimer = new QTimer(q);
470  m_scrollAreaTimer->setSingleShot(true);
471  m_scrollAreaTimer->setInterval(200);
472  connect(m_scrollAreaTimer, SIGNAL(timeout()),
473  q, SLOT(resumeIconUpdates()));
474  m_viewAdapter->connect(KAbstractViewAdapter::ScrollBarValueChanged,
475  q, SLOT(pauseIconUpdates()));
476 
477  m_changedItemsTimer = new QTimer(q);
478  m_changedItemsTimer->setSingleShot(true);
479  m_changedItemsTimer->setInterval(5000);
480  connect(m_changedItemsTimer, SIGNAL(timeout()),
481  q, SLOT(delayedIconUpdate()));
482 
483  KConfigGroup globalConfig(KGlobal::config(), "PreviewSettings");
484  m_enabledPlugins = globalConfig.readEntry("Plugins", QStringList()
485  << "directorythumbnail"
486  << "imagethumbnail"
487  << "jpegthumbnail");
488 
489  // If the user is upgrading from KDE <= 4.6, we must check if he had the 'jpegrotatedthumbnail' plugin enabled.
490  // This plugin does not exist any more in KDE >= 4.7, so we have to replace it with the 'jpegthumbnail' plugin.
491  if(m_enabledPlugins.contains(QLatin1String("jpegrotatedthumbnail"))) {
492  m_enabledPlugins.removeAll(QLatin1String("jpegrotatedthumbnail"));
493  m_enabledPlugins.append(QLatin1String("jpegthumbnail"));
494  globalConfig.writeEntry("Plugins", m_enabledPlugins);
495  globalConfig.sync();
496  }
497 }
498 
499 KFilePreviewGenerator::Private::~Private()
500 {
501  killPreviewJobs();
502  m_pendingItems.clear();
503  m_dispatchedItems.clear();
504  delete m_tileSet;
505 }
506 
507 void KFilePreviewGenerator::Private::requestSequenceIcon(const QModelIndex& index,
508  int sequenceIndex)
509 {
510  if (m_pendingItems.isEmpty() || (sequenceIndex == 0)) {
511  KDirModel* dirModel = m_dirModel.data();
512  if (!dirModel) {
513  return;
514  }
515 
516  KFileItem item = dirModel->itemForIndex(index);
517  if (sequenceIndex == 0) {
518  m_sequenceIndices.remove(item.url());
519  } else {
520  m_sequenceIndices.insert(item.url(), sequenceIndex);
521  }
522 
524  updateIcons(KFileItemList() << item);
525  }
526 }
527 
528 void KFilePreviewGenerator::Private::updateIcons(const KFileItemList& items)
529 {
530  if (items.isEmpty()) {
531  return;
532  }
533 
534  applyCutItemEffect(items);
535 
536  KFileItemList orderedItems = items;
537  orderItems(orderedItems);
538 
539  foreach (const KFileItem& item, orderedItems) {
540  m_pendingItems.append(item);
541  }
542 
543  if (m_previewShown) {
544  createPreviews(orderedItems);
545  } else {
546  startMimeTypeResolving();
547  }
548 }
549 
550 void KFilePreviewGenerator::Private::updateIcons(const QModelIndex& topLeft,
551  const QModelIndex& bottomRight)
552 {
553  if (m_internalDataChange > 0) {
554  // QAbstractItemModel::setData() has been invoked internally by the KFilePreviewGenerator.
555  // The signal dataChanged() is connected with this method, but previews only need
556  // to be generated when an external data change has occurred.
557  return;
558  }
559 
560  // dataChanged emitted for the root dir (e.g. permission changes)
561  if (!topLeft.isValid() || !bottomRight.isValid()) {
562  return;
563  }
564 
565  KDirModel* dirModel = m_dirModel.data();
566  if (!dirModel) {
567  return;
568  }
569 
570  KFileItemList itemList;
571  for (int row = topLeft.row(); row <= bottomRight.row(); ++row) {
572  const QModelIndex index = dirModel->index(row, 0);
573  if (!index.isValid()) {
574  continue;
575  }
576  const KFileItem item = dirModel->itemForIndex(index);
577  Q_ASSERT(!item.isNull());
578 
579  if (m_previewShown) {
580  const KUrl url = item.url();
581  const bool hasChanged = m_changedItems.contains(url); // O(1)
582  m_changedItems.insert(url, hasChanged);
583  if (!hasChanged) {
584  // only update the icon if it has not been already updated within
585  // the last 5 seconds (the other icons will be updated later with
586  // the help of m_changedItemsTimer)
587  itemList.append(item);
588  }
589  } else {
590  itemList.append(item);
591  }
592  }
593 
594  updateIcons(itemList);
595  m_changedItemsTimer->start();
596 }
597 
598 void KFilePreviewGenerator::Private::addToPreviewQueue(const KFileItem& item, const QPixmap& pixmap)
599 {
600  KIO::PreviewJob* senderJob = qobject_cast<KIO::PreviewJob*>(q->sender());
601  Q_ASSERT(senderJob != 0);
602  if (senderJob != 0) {
603  QMap<KUrl, int>::iterator it = m_sequenceIndices.find(item.url());
604  if (senderJob->sequenceIndex() && (it == m_sequenceIndices.end() || *it != senderJob->sequenceIndex())) {
605  return; // the sequence index does not match the one we want
606  }
607  if (!senderJob->sequenceIndex() && it != m_sequenceIndices.end()) {
608  return; // the sequence index does not match the one we want
609  }
610 
611  m_sequenceIndices.erase(it);
612  }
613 
614  if (!m_previewShown) {
615  // the preview has been canceled in the meantime
616  return;
617  }
618 
619  KDirModel* dirModel = m_dirModel.data();
620  if (!dirModel) {
621  return;
622  }
623 
624  // check whether the item is part of the directory lister (it is possible
625  // that a preview from an old directory lister is received)
626  bool isOldPreview = true;
627 
628  KUrl itemParentDir(item.url());
629  itemParentDir.setPath(itemParentDir.directory());
630 
631  foreach (const KUrl& dir, dirModel->dirLister()->directories()) {
632  if (dir == itemParentDir || !dir.hasPath()) {
633  isOldPreview = false;
634  break;
635  }
636  }
637  if (isOldPreview) {
638  return;
639  }
640 
641  QPixmap icon = pixmap;
642 
643  const QString mimeType = item.mimetype();
644  const int slashIndex = mimeType.indexOf(QLatin1Char('/'));
645  const QString mimeTypeGroup = mimeType.left(slashIndex);
646  if ((mimeTypeGroup != QLatin1String("image")) || !applyImageFrame(icon)) {
647  limitToSize(icon, m_viewAdapter->iconSize());
648  }
649 
650  if (m_hasCutSelection && isCutItem(item)) {
651  // apply the disabled effect to the icon for marking it as "cut item"
652  // and apply the icon to the item
653  KIconEffect *iconEffect = KIconLoader::global()->iconEffect();
654  icon = iconEffect->apply(icon, KIconLoader::Desktop, KIconLoader::DisabledState);
655  }
656 
657  KIconLoader::global()->drawOverlays(item.overlays(), icon, KIconLoader::Desktop);
658 
659  // remember the preview and URL, so that it can be applied to the model
660  // in KFilePreviewGenerator::dispatchIconUpdateQueue()
661  ItemInfo preview;
662  preview.url = item.url();
663  preview.pixmap = icon;
664  m_previews.append(preview);
665 
666  m_dispatchedItems.append(item);
667 }
668 
669 void KFilePreviewGenerator::Private::slotPreviewJobFinished(KJob* job)
670 {
671  const int index = m_previewJobs.indexOf(job);
672  m_previewJobs.removeAt(index);
673 
674  if (m_previewJobs.isEmpty()) {
675  if (m_clearItemQueues) {
676  m_pendingItems.clear();
677  m_dispatchedItems.clear();
678  m_pendingVisibleIconUpdates = 0;
679  QMetaObject::invokeMethod(q, "dispatchIconUpdateQueue", Qt::QueuedConnection);
680  }
681  m_sequenceIndices.clear(); // just to be sure that we don't leak anything
682  }
683 }
684 
685 void KFilePreviewGenerator::Private::updateCutItems()
686 {
687  KDirModel* dirModel = m_dirModel.data();
688  if (!dirModel) {
689  return;
690  }
691 
692  DataChangeObtainer obt(this);
693  clearCutItemsCache();
694 
695  KFileItemList items;
696  KDirLister* dirLister = dirModel->dirLister();
697  const KUrl::List dirs = dirLister->directories();
698  foreach (const KUrl& url, dirs) {
699  items << dirLister->itemsForDir(url);
700  }
701  applyCutItemEffect(items);
702 }
703 
704 void KFilePreviewGenerator::Private::clearCutItemsCache()
705 {
706  KDirModel* dirModel = m_dirModel.data();
707  if (!dirModel) {
708  return;
709  }
710 
711  DataChangeObtainer obt(this);
712  KFileItemList previews;
713  // Reset the icons of all items that are stored in the cache
714  // to use their default MIME type icon.
715  foreach (const KUrl& url, m_cutItemsCache.keys()) {
716  const QModelIndex index = dirModel->indexForUrl(url);
717  if (index.isValid()) {
718  dirModel->setData(index, QIcon(), Qt::DecorationRole);
719  if (m_previewShown) {
720  previews.append(dirModel->itemForIndex(index));
721  }
722  }
723  }
724  m_cutItemsCache.clear();
725 
726  if (previews.size() > 0) {
727  // assure that the previews gets restored
728  Q_ASSERT(m_previewShown);
729  orderItems(previews);
730  updateIcons(previews);
731  }
732 }
733 
734 void KFilePreviewGenerator::Private::dispatchIconUpdateQueue()
735 {
736  KDirModel* dirModel = m_dirModel.data();
737  if (!dirModel) {
738  return;
739  }
740 
741  const int count = m_previewShown ? m_previews.count()
742  : m_resolvedMimeTypes.count();
743  if (count > 0) {
744  LayoutBlocker blocker(m_itemView);
745  DataChangeObtainer obt(this);
746 
747  if (m_previewShown) {
748  // dispatch preview queue
749  foreach (const ItemInfo& preview, m_previews) {
750  const QModelIndex idx = dirModel->indexForUrl(preview.url);
751  if (idx.isValid() && (idx.column() == 0)) {
752  dirModel->setData(idx, QIcon(preview.pixmap), Qt::DecorationRole);
753  }
754  }
755  m_previews.clear();
756  } else {
757  // dispatch mime type queue
758  foreach (const KFileItem& item, m_resolvedMimeTypes) {
759  const QModelIndex idx = dirModel->indexForItem(item);
760  dirModel->itemChanged(idx);
761  }
762  m_resolvedMimeTypes.clear();
763  }
764 
765  m_pendingVisibleIconUpdates -= count;
766  if (m_pendingVisibleIconUpdates < 0) {
767  m_pendingVisibleIconUpdates = 0;
768  }
769  }
770 
771  if (m_pendingVisibleIconUpdates > 0) {
772  // As long as there are pending previews for visible items, poll
773  // the preview queue periodically. If there are no pending previews,
774  // the queue is dispatched in slotPreviewJobFinished().
775  m_iconUpdateTimer->start();
776  }
777 }
778 
779 void KFilePreviewGenerator::Private::pauseIconUpdates()
780 {
781  m_iconUpdatesPaused = true;
782  foreach (KJob* job, m_previewJobs) {
783  Q_ASSERT(job != 0);
784  job->suspend();
785  }
786  m_scrollAreaTimer->start();
787 }
788 
789 void KFilePreviewGenerator::Private::resumeIconUpdates()
790 {
791  m_iconUpdatesPaused = false;
792 
793  // Before creating new preview jobs the m_pendingItems queue must be
794  // cleaned up by removing the already dispatched items. Implementation
795  // note: The order of the m_dispatchedItems queue and the m_pendingItems
796  // queue is usually equal. So even when having a lot of elements the
797  // nested loop is no performance bottle neck, as the inner loop is only
798  // entered once in most cases.
799  foreach (const KFileItem& item, m_dispatchedItems) {
800  KFileItemList::iterator begin = m_pendingItems.begin();
801  KFileItemList::iterator end = m_pendingItems.end();
802  for (KFileItemList::iterator it = begin; it != end; ++it) {
803  if ((*it).url() == item.url()) {
804  m_pendingItems.erase(it);
805  break;
806  }
807  }
808  }
809  m_dispatchedItems.clear();
810 
811  m_pendingVisibleIconUpdates = 0;
812  dispatchIconUpdateQueue();
813 
814 
815  if (m_previewShown) {
816  KFileItemList orderedItems = m_pendingItems;
817  orderItems(orderedItems);
818 
819  // Kill all suspended preview jobs. Usually when a preview job
820  // has been finished, slotPreviewJobFinished() clears all item queues.
821  // This is not wanted in this case, as a new job is created afterwards
822  // for m_pendingItems.
823  m_clearItemQueues = false;
824  killPreviewJobs();
825  m_clearItemQueues = true;
826 
827  createPreviews(orderedItems);
828  } else {
829  orderItems(m_pendingItems);
830  startMimeTypeResolving();
831  }
832 }
833 
834 void KFilePreviewGenerator::Private::startMimeTypeResolving()
835 {
836  resolveMimeType();
837  m_iconUpdateTimer->start();
838 }
839 
840 void KFilePreviewGenerator::Private::resolveMimeType()
841 {
842  if (m_pendingItems.isEmpty()) {
843  return;
844  }
845 
846  // resolve at least one MIME type
847  bool resolved = false;
848  do {
849  KFileItem item = m_pendingItems.takeFirst();
850  if (item.isMimeTypeKnown()) {
851  if (m_pendingVisibleIconUpdates > 0) {
852  // The item is visible and the MIME type already known.
853  // Decrease the update counter for dispatchIconUpdateQueue():
854  --m_pendingVisibleIconUpdates;
855  }
856  } else {
857  // The MIME type is unknown and must get resolved. The
858  // directory model is not informed yet, as a single update
859  // would be very expensive. Instead the item is remembered in
860  // m_resolvedMimeTypes and will be dispatched later
861  // by dispatchIconUpdateQueue().
862  item.determineMimeType();
863  m_resolvedMimeTypes.append(item);
864  resolved = true;
865  }
866  } while (!resolved && !m_pendingItems.isEmpty());
867 
868  if (m_pendingItems.isEmpty()) {
869  // All MIME types have been resolved now. Assure
870  // that the directory model gets informed about
871  // this, so that an update of the icons is done.
872  dispatchIconUpdateQueue();
873  } else if (!m_iconUpdatesPaused) {
874  // assure that the MIME type of the next
875  // item will be resolved asynchronously
876  QMetaObject::invokeMethod(q, "resolveMimeType", Qt::QueuedConnection);
877  }
878 }
879 
880 bool KFilePreviewGenerator::Private::isCutItem(const KFileItem& item) const
881 {
882  const QMimeData* mimeData = QApplication::clipboard()->mimeData();
883  const KUrl::List cutUrls = KUrl::List::fromMimeData(mimeData);
884  return cutUrls.contains(item.url());
885 }
886 
887 void KFilePreviewGenerator::Private::applyCutItemEffect(const KFileItemList& items)
888 {
889  const QMimeData* mimeData = QApplication::clipboard()->mimeData();
890  m_hasCutSelection = decodeIsCutSelection(mimeData);
891  if (!m_hasCutSelection) {
892  return;
893  }
894 
895  KDirModel* dirModel = m_dirModel.data();
896  if (!dirModel) {
897  return;
898  }
899 
900  const QSet<KUrl> cutUrls = KUrl::List::fromMimeData(mimeData).toSet();
901 
902  DataChangeObtainer obt(this);
903  KIconEffect *iconEffect = KIconLoader::global()->iconEffect();
904  foreach (const KFileItem& item, items) {
905  if (cutUrls.contains(item.url())) {
906  const QModelIndex index = dirModel->indexForItem(item);
907  const QVariant value = dirModel->data(index, Qt::DecorationRole);
908  if (value.type() == QVariant::Icon) {
909  const QIcon icon(qvariant_cast<QIcon>(value));
910  const QSize actualSize = icon.actualSize(m_viewAdapter->iconSize());
911  QPixmap pixmap = icon.pixmap(actualSize);
912 
913  const QHash<KUrl, QPixmap>::const_iterator cacheIt = m_cutItemsCache.constFind(item.url());
914  if ((cacheIt == m_cutItemsCache.constEnd()) || (cacheIt->cacheKey() != pixmap.cacheKey())) {
915  pixmap = iconEffect->apply(pixmap, KIconLoader::Desktop, KIconLoader::DisabledState);
916  dirModel->setData(index, QIcon(pixmap), Qt::DecorationRole);
917 
918  m_cutItemsCache.insert(item.url(), pixmap);
919  }
920  }
921  }
922  }
923 }
924 
925 bool KFilePreviewGenerator::Private::applyImageFrame(QPixmap& icon)
926 {
927  const QSize maxSize = m_viewAdapter->iconSize();
928 
929  // The original size of an image is not exported by the thumbnail mechanism.
930  // Still it would be helpful to not apply an image frame for e. g. icons that
931  // fit into the given boundaries:
932  const bool isIconCandidate = (icon.width() == icon.height()) &&
933  ((icon.width() & 0x7) == 0);
934 
935  const bool applyFrame = (maxSize.width() > KIconLoader::SizeSmallMedium) &&
936  (maxSize.height() > KIconLoader::SizeSmallMedium) &&
937  !isIconCandidate;
938  if (!applyFrame) {
939  // the maximum size or the image itself is too small for a frame
940  return false;
941  }
942 
943  // resize the icon to the maximum size minus the space required for the frame
944  const QSize size(maxSize.width() - TileSet::LeftMargin - TileSet::RightMargin,
945  maxSize.height() - TileSet::TopMargin - TileSet::BottomMargin);
946  limitToSize(icon, size);
947 
948  if (m_tileSet == 0) {
949  m_tileSet = new TileSet();
950  }
951 
952  QPixmap framedIcon(icon.size().width() + TileSet::LeftMargin + TileSet::RightMargin,
953  icon.size().height() + TileSet::TopMargin + TileSet::BottomMargin);
954  framedIcon.fill(Qt::transparent);
955 
956  QPainter painter;
957  painter.begin(&framedIcon);
958  painter.setCompositionMode(QPainter::CompositionMode_Source);
959  m_tileSet->paint(&painter, framedIcon.rect());
960  painter.setCompositionMode(QPainter::CompositionMode_SourceOver);
961  painter.drawPixmap(TileSet::LeftMargin, TileSet::TopMargin, icon);
962  painter.end();
963 
964  icon = framedIcon;
965  return true;
966 }
967 
968 void KFilePreviewGenerator::Private::limitToSize(QPixmap& icon, const QSize& maxSize)
969 {
970  if ((icon.width() > maxSize.width()) || (icon.height() > maxSize.height())) {
971 #if defined(Q_WS_X11) && defined(HAVE_XRENDER)
972  // Assume that the texture size limit is 2048x2048
973  if ((icon.width() <= 2048) && (icon.height() <= 2048) && icon.x11PictureHandle()) {
974  QSize size = icon.size();
975  size.scale(maxSize, Qt::KeepAspectRatio);
976 
977  const qreal factor = size.width() / qreal(icon.width());
978 
979  XTransform xform = {{
980  { XDoubleToFixed(1 / factor), 0, 0 },
981  { 0, XDoubleToFixed(1 / factor), 0 },
982  { 0, 0, XDoubleToFixed(1) }
983  }};
984 
985  QPixmap pixmap(size);
986  pixmap.fill(Qt::transparent);
987 
988  Display* dpy = QX11Info::display();
989 
990  XRenderPictureAttributes attr;
991  attr.repeat = RepeatPad;
992  XRenderChangePicture(dpy, icon.x11PictureHandle(), CPRepeat, &attr);
993 
994  XRenderSetPictureFilter(dpy, icon.x11PictureHandle(), FilterBilinear, 0, 0);
995  XRenderSetPictureTransform(dpy, icon.x11PictureHandle(), &xform);
996  XRenderComposite(dpy, PictOpOver, icon.x11PictureHandle(), None, pixmap.x11PictureHandle(),
997  0, 0, 0, 0, 0, 0, pixmap.width(), pixmap.height());
998  icon = pixmap;
999  } else {
1000  icon = icon.scaled(maxSize, Qt::KeepAspectRatio, Qt::FastTransformation);
1001  }
1002 #else
1003  icon = icon.scaled(maxSize, Qt::KeepAspectRatio, Qt::FastTransformation);
1004 #endif
1005  }
1006 }
1007 
1008 void KFilePreviewGenerator::Private::createPreviews(const KFileItemList& items)
1009 {
1010  if (items.count() == 0) {
1011  return;
1012  }
1013 
1014  const QMimeData* mimeData = QApplication::clipboard()->mimeData();
1015  m_hasCutSelection = decodeIsCutSelection(mimeData);
1016 
1017  // PreviewJob internally caches items always with the size of
1018  // 128 x 128 pixels or 256 x 256 pixels. A downscaling is done
1019  // by PreviewJob if a smaller size is requested. For images KFilePreviewGenerator must
1020  // do a downscaling anyhow because of the frame, so in this case only the provided
1021  // cache sizes are requested.
1022  KFileItemList imageItems;
1023  KFileItemList otherItems;
1024  QString mimeType;
1025  QString mimeTypeGroup;
1026  foreach (const KFileItem& item, items) {
1027  mimeType = item.mimetype();
1028  const int slashIndex = mimeType.indexOf(QLatin1Char('/'));
1029  mimeTypeGroup = mimeType.left(slashIndex);
1030  if (mimeTypeGroup == QLatin1String("image")) {
1031  imageItems.append(item);
1032  } else {
1033  otherItems.append(item);
1034  }
1035  }
1036  const QSize size = m_viewAdapter->iconSize();
1037  startPreviewJob(otherItems, size.width(), size.height());
1038 
1039  const int cacheSize = (size.width() > 128) || (size.height() > 128) ? 256 : 128;
1040  startPreviewJob(imageItems, cacheSize, cacheSize);
1041 
1042  m_iconUpdateTimer->start();
1043 }
1044 
1045 void KFilePreviewGenerator::Private::startPreviewJob(const KFileItemList& items, int width, int height)
1046 {
1047  if (items.count() > 0) {
1048  KIO::PreviewJob* job = KIO::filePreview(items, QSize(width, height), &m_enabledPlugins);
1049 
1050  // Set the sequence index to the target. We only need to check if items.count() == 1,
1051  // because requestSequenceIcon(..) creates exactly such a request.
1052  if (!m_sequenceIndices.isEmpty() && (items.count() == 1)) {
1053  QMap<KUrl, int>::iterator it = m_sequenceIndices.find(items[0].url());
1054  if (it != m_sequenceIndices.end()) {
1055  job->setSequenceIndex(*it);
1056  }
1057  }
1058 
1059  connect(job, SIGNAL(gotPreview(KFileItem,QPixmap)),
1060  q, SLOT(addToPreviewQueue(KFileItem,QPixmap)));
1061  connect(job, SIGNAL(finished(KJob*)),
1062  q, SLOT(slotPreviewJobFinished(KJob*)));
1063  m_previewJobs.append(job);
1064  }
1065 }
1066 
1067 void KFilePreviewGenerator::Private::killPreviewJobs()
1068 {
1069  foreach (KJob* job, m_previewJobs) {
1070  Q_ASSERT(job != 0);
1071  job->kill();
1072  }
1073  m_previewJobs.clear();
1074  m_sequenceIndices.clear();
1075 
1076  m_iconUpdateTimer->stop();
1077  m_scrollAreaTimer->stop();
1078  m_changedItemsTimer->stop();
1079 }
1080 
1081 void KFilePreviewGenerator::Private::orderItems(KFileItemList& items)
1082 {
1083  KDirModel* dirModel = m_dirModel.data();
1084  if (!dirModel) {
1085  return;
1086  }
1087 
1088  // Order the items in a way that the preview for the visible items
1089  // is generated first, as this improves the feeled performance a lot.
1090  const bool hasProxy = (m_proxyModel != 0);
1091  const int itemCount = items.count();
1092  const QRect visibleArea = m_viewAdapter->visibleArea();
1093 
1094  QModelIndex dirIndex;
1095  QRect itemRect;
1096  int insertPos = 0;
1097  for (int i = 0; i < itemCount; ++i) {
1098  dirIndex = dirModel->indexForItem(items.at(i)); // O(n) (n = number of rows)
1099  if (hasProxy) {
1100  const QModelIndex proxyIndex = m_proxyModel->mapFromSource(dirIndex);
1101  itemRect = m_viewAdapter->visualRect(proxyIndex);
1102  } else {
1103  itemRect = m_viewAdapter->visualRect(dirIndex);
1104  }
1105 
1106  if (itemRect.intersects(visibleArea)) {
1107  // The current item is (at least partly) visible. Move it
1108  // to the front of the list, so that the preview is
1109  // generated earlier.
1110  items.insert(insertPos, items.at(i));
1111  items.removeAt(i + 1);
1112  ++insertPos;
1113  ++m_pendingVisibleIconUpdates;
1114  }
1115  }
1116 }
1117 
1118 bool KFilePreviewGenerator::Private::decodeIsCutSelection(const QMimeData* mimeData)
1119 {
1120  const QByteArray data = mimeData->data("application/x-kde-cutselection");
1121  if (data.isEmpty()) {
1122  return false;
1123  } else {
1124  return data.at(0) == QLatin1Char('1');
1125  }
1126 }
1127 
1128 void KFilePreviewGenerator::Private::addItemsToList(const QModelIndex& index, KFileItemList& list)
1129 {
1130  KDirModel* dirModel = m_dirModel.data();
1131  if (!dirModel) {
1132  return;
1133  }
1134 
1135  const int rowCount = dirModel->rowCount(index);
1136  for (int row = 0; row < rowCount; ++row) {
1137  const QModelIndex subIndex = dirModel->index(row, 0, index);
1138  KFileItem item = dirModel->itemForIndex(subIndex);
1139  list.append(item);
1140 
1141  if (dirModel->rowCount(subIndex) > 0) {
1142  // the model is hierarchical (treeview)
1143  addItemsToList(subIndex, list);
1144  }
1145  }
1146 }
1147 
1148 void KFilePreviewGenerator::Private::delayedIconUpdate()
1149 {
1150  KDirModel* dirModel = m_dirModel.data();
1151  if (!dirModel) {
1152  return;
1153  }
1154 
1155  // Precondition: No items have been changed within the last
1156  // 5 seconds. This means that items that have been changed constantly
1157  // due to a copy operation should be updated now.
1158 
1159  KFileItemList itemList;
1160 
1161  QHash<KUrl, bool>::const_iterator it = m_changedItems.constBegin();
1162  while (it != m_changedItems.constEnd()) {
1163  const bool hasChanged = it.value();
1164  if (hasChanged) {
1165  const QModelIndex index = dirModel->indexForUrl(it.key());
1166  const KFileItem item = dirModel->itemForIndex(index);
1167  itemList.append(item);
1168  }
1169  ++it;
1170  }
1171  m_changedItems.clear();
1172 
1173  updateIcons(itemList);
1174 }
1175 
1176 void KFilePreviewGenerator::Private::rowsAboutToBeRemoved(const QModelIndex& parent, int start, int end)
1177 {
1178  if (m_changedItems.isEmpty()) {
1179  return;
1180  }
1181 
1182  KDirModel* dirModel = m_dirModel.data();
1183  if (!dirModel) {
1184  return;
1185  }
1186 
1187  for (int row = start; row <= end; row++) {
1188  const QModelIndex index = dirModel->index(row, 0, parent);
1189 
1190  const KFileItem item = dirModel->itemForIndex(index);
1191  if (!item.isNull()) {
1192  m_changedItems.remove(item.url());
1193  }
1194 
1195  if (dirModel->hasChildren(index)) {
1196  rowsAboutToBeRemoved(index, 0, dirModel->rowCount(index) - 1);
1197  }
1198  }
1199 }
1200 
1201 KFilePreviewGenerator::KFilePreviewGenerator(QAbstractItemView* parent) :
1202  QObject(parent),
1203  d(new Private(this, new KIO::DefaultViewAdapter(parent, this), parent->model()))
1204 {
1205  d->m_itemView = parent;
1206 }
1207 
1208 KFilePreviewGenerator::KFilePreviewGenerator(KAbstractViewAdapter* parent, QAbstractProxyModel* model) :
1209  QObject(parent),
1210  d(new Private(this, parent, model))
1211 {
1212 }
1213 
1214 KFilePreviewGenerator::~KFilePreviewGenerator()
1215 {
1216  delete d;
1217 }
1218 
1219 void KFilePreviewGenerator::setPreviewShown(bool show)
1220 {
1221  if (d->m_previewShown == show) {
1222  return;
1223  }
1224 
1225  KDirModel* dirModel = d->m_dirModel.data();
1226  if (show && (!d->m_viewAdapter->iconSize().isValid() || !dirModel)) {
1227  // The view must provide an icon size and a directory model,
1228  // otherwise the showing the previews will get ignored
1229  return;
1230  }
1231 
1232  d->m_previewShown = show;
1233  if (!show) {
1234  // Clear the icon for all items so that the MIME type
1235  // gets reloaded
1236  KFileItemList itemList;
1237  d->addItemsToList(QModelIndex(), itemList);
1238 
1239  const bool blocked = dirModel->signalsBlocked();
1240  dirModel->blockSignals(true);
1241 
1242  QList<QModelIndex> indexesWithKnownMimeType;
1243  foreach (const KFileItem& item, itemList) {
1244  const QModelIndex index = dirModel->indexForItem(item);
1245  if (item.isMimeTypeKnown()) {
1246  indexesWithKnownMimeType.append(index);
1247  }
1248  dirModel->setData(index, QIcon(), Qt::DecorationRole);
1249  }
1250 
1251  dirModel->blockSignals(blocked);
1252 
1253  // Items without a known mimetype will be handled (delayed) by updateIcons.
1254  // So we need to update items with a known mimetype ourselves.
1255  foreach (const QModelIndex& index, indexesWithKnownMimeType) {
1256  dirModel->itemChanged(index);
1257  }
1258  }
1259  updateIcons();
1260 }
1261 
1262 bool KFilePreviewGenerator::isPreviewShown() const
1263 {
1264  return d->m_previewShown;
1265 }
1266 
1267 // deprecated (use updateIcons() instead)
1268 void KFilePreviewGenerator::updatePreviews()
1269 {
1270  updateIcons();
1271 }
1272 
1273 void KFilePreviewGenerator::updateIcons()
1274 {
1275  d->killPreviewJobs();
1276 
1277  d->clearCutItemsCache();
1278  d->m_pendingItems.clear();
1279  d->m_dispatchedItems.clear();
1280 
1281  KFileItemList itemList;
1282  d->addItemsToList(QModelIndex(), itemList);
1283 
1284  d->updateIcons(itemList);
1285 }
1286 
1287 void KFilePreviewGenerator::cancelPreviews()
1288 {
1289  d->killPreviewJobs();
1290  d->m_pendingItems.clear();
1291  d->m_dispatchedItems.clear();
1292  updateIcons();
1293 }
1294 
1295 void KFilePreviewGenerator::setEnabledPlugins(const QStringList& plugins)
1296 {
1297  d->m_enabledPlugins = plugins;
1298 }
1299 
1300 QStringList KFilePreviewGenerator::enabledPlugins() const
1301 {
1302  return d->m_enabledPlugins;
1303 }
1304 
1305 #include "kfilepreviewgenerator.moc"
kdirlister.h
KDirModel::rowCount
virtual int rowCount(const QModelIndex &parent=QModelIndex()) const
QModelIndex
KFilePreviewGenerator::cancelPreviews
void cancelPreviews()
Cancels all pending previews.
Definition: kfilepreviewgenerator.cpp:1287
QString::indexOf
int indexOf(QChar ch, int from, Qt::CaseSensitivity cs) const
QPixmap::size
QSize size() const
QMimeData::data
QByteArray data(const QString &mimeType) const
KFileItem::determineMimeType
KMimeType::Ptr determineMimeType() const
QSize::width
int width() const
QPixmap::width
int width() const
QPainter::end
bool end()
QHash::key
const Key key(const T &value) const
QAbstractItemView
QPainter::fillRect
void fillRect(const QRectF &rectangle, const QBrush &brush)
QPainter::setCompositionMode
void setCompositionMode(CompositionMode mode)
QPixmap::copy
QPixmap copy(int x, int y, int width, int height) const
KFilePreviewGenerator::KFilePreviewGenerator
KFilePreviewGenerator(QAbstractItemView *parent)
Definition: kfilepreviewgenerator.cpp:1201
QClipboard::mimeData
const QMimeData * mimeData(Mode mode) const
QPixmap::fill
void fill(const QColor &color)
KFilePreviewGenerator
Generates previews for files of an item view.
Definition: kfilepreviewgenerator.h:50
QRect::right
int right() const
QAbstractProxyModel
QByteArray
QByteArray::at
char at(int i) const
KDirLister::directories
KUrl::List directories() const
KIconLoader::global
static KIconLoader * global()
KFileItem::mimetype
QString mimetype() const
KAbstractViewAdapter
KDirModel::itemChanged
void itemChanged(const QModelIndex &index)
timeout
int timeout
KFileItem::isNull
bool isNull() const
QX11Info::display
Display * display()
KDirModel::data
virtual QVariant data(const QModelIndex &index, int role=Qt::DisplayRole) const
KIconLoader::SizeSmallMedium
QMap::constBegin
const_iterator constBegin() const
QList::at
const T & at(int i) const
QMap< KUrl, int >
QList::removeAt
void removeAt(int i)
dirs
KStandardDirs * dirs()
QByteArray::isEmpty
bool isEmpty() const
QRect::intersects
bool intersects(const QRect &rectangle) const
KDirModel::setData
virtual bool setData(const QModelIndex &index, const QVariant &value, int role=Qt::EditRole)
KDirModel::indexForUrl
QModelIndex indexForUrl(const KUrl &url) const
KDirModel::index
virtual QModelIndex index(int row, int column, const QModelIndex &parent=QModelIndex()) const
QPixmap::fromImage
QPixmap fromImage(const QImage &image, QFlags< Qt::ImageConversionFlag > flags)
QPainter::drawTiledPixmap
void drawTiledPixmap(const QRectF &rectangle, const QPixmap &pixmap, const QPointF &position)
QHash::constFind
const_iterator constFind(const Key &key) const
QRect::height
int height() const
QSize::scale
void scale(int width, int height, Qt::AspectRatioMode mode)
QRect::x
int x() const
QRect::y
int y() const
QList::toSet
QSet< T > toSet() const
KFilePreviewGenerator::~KFilePreviewGenerator
virtual ~KFilePreviewGenerator()
Definition: kfilepreviewgenerator.cpp:1214
KDirModel::dirLister
KDirLister * dirLister() const
KDirModel::indexForItem
QModelIndex indexForItem(const KFileItem *) const
KFilePreviewGenerator::enabledPlugins
QStringList enabledPlugins() const
Returns the list of enabled thumbnail plugins.
Definition: kfilepreviewgenerator.cpp:1300
KIconLoader::Desktop
QMimeData
KUrl
QList::size
int size() const
KGlobal::config
KSharedConfigPtr config()
KDirModel::itemForIndex
KFileItem itemForIndex(const QModelIndex &index) const
KUrl::setPath
void setPath(const QString &path)
QClipboard
QListView
None
QRect
QModelIndex::isValid
bool isValid() const
KIconLoader::DisabledState
KIO::PreviewJob::sequenceIndex
int sequenceIndex() const
QList::count
int count(const T &value) const
QList::append
void append(const T &value)
QHash::constEnd
const_iterator constEnd() const
QTimer
QApplication::clipboard
QClipboard * clipboard()
QHash< KUrl, QPixmap >
KUrl::List::fromMimeData
static KUrl::List fromMimeData(const QMimeData *mimeData, KUrl::MetaDataMap *metaData=0)
QObject
QPainter::drawPixmap
void drawPixmap(const QRectF &target, const QPixmap &pixmap, const QRectF &source)
QList::isEmpty
bool isEmpty() const
QPainter
previewjob.h
QModelIndex::row
int row() const
actualSize
KAction * actualSize(const QObject *recvr, const char *slot, QObject *parent)
KFilePreviewGenerator::setPreviewShown
void setPreviewShown(bool show)
If show is set to true, a preview is generated for each item.
Definition: kfilepreviewgenerator.cpp:1219
KFileItemList
QPixmap::cacheKey
qint64 cacheKey() const
kfilepreviewgenerator.h
QSet
ksharedconfig.h
QPixmap::scaled
QPixmap scaled(int width, int height, Qt::AspectRatioMode aspectRatioMode, Qt::TransformationMode transformMode) const
QString
QList< KJob * >
QMap::end
iterator end()
KUrl::hasPath
bool hasPath() const
KDirModel::hasChildren
virtual bool hasChildren(const QModelIndex &parent=QModelIndex()) const
QStringList
QObject::signalsBlocked
bool signalsBlocked() const
KIconLoader::iconEffect
KIconEffect * iconEffect() const
QPixmap
QRect::adjusted
QRect adjusted(int dx1, int dy1, int dx2, int dy2) const
QHash::clear
void clear()
QHash::value
const T value(const Key &key) const
QObject::blockSignals
bool blockSignals(bool block)
KIO::PreviewJob
QSize
QLatin1Char
QPixmap::height
int height() const
QList::contains
bool contains(const T &value) const
KFilePreviewGenerator::updateIcons
void updateIcons()
Updates the icons for all items.
Definition: kfilepreviewgenerator.cpp:1273
QImage
QMetaObject::invokeMethod
bool invokeMethod(QObject *obj, const char *member, Qt::ConnectionType type, QGenericReturnArgument ret, QGenericArgument val0, QGenericArgument val1, QGenericArgument val2, QGenericArgument val3, QGenericArgument val4, QGenericArgument val5, QGenericArgument val6, QGenericArgument val7, QGenericArgument val8, QGenericArgument val9)
QSet::contains
bool contains(const T &value) const
KFilePreviewGenerator::isPreviewShown
bool isPreviewShown() const
Definition: kfilepreviewgenerator.cpp:1262
KConfigGroup
KUrl::List
kdirmodel.h
QRect::width
int width() const
QLatin1String
QList::insert
void insert(int i, const T &value)
QPixmap::x11PictureHandle
Qt::HANDLE x11PictureHandle() const
QSize::height
int height() const
KAbstractViewAdapter::ScrollBarValueChanged
QRect::bottom
int bottom() const
QRect::topLeft
QPoint topLeft() const
QModelIndex::column
int column() const
QAbstractItemModel
QWeakPointer< KDirModel >
QString::left
QString left(int n) const
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)
KIconEffect::apply
QImage apply(const QImage &src, int group, int state) const
KIconLoader::drawOverlays
void drawOverlays(const QStringList &overlays, QPixmap &pixmap, KIconLoader::Group group, int state=KIconLoader::DefaultState) const
KDirLister
KFileItem::isMimeTypeKnown
bool isMimeTypeKnown() const
QVariant::type
Type type() const
KIO::ImageFilter::shadowBlur
static void shadowBlur(QImage &image, float radius, const QColor &color)
QObject::connect
bool connect(const QObject *sender, const char *signal, const QObject *receiver, const char *method, Qt::ConnectionType type)
QObject::parent
QObject * parent() const
KIconEffect
QPainter::begin
bool begin(QPaintDevice *device)
end
const KShortcut & end()
KDirModel
KJob
QMap::find
iterator find(const Key &key)
kfileitem.h
KFileItem::overlays
QStringList overlays() const
KFilePreviewGenerator::updatePreviews
void updatePreviews()
Definition: kfilepreviewgenerator.cpp:1268
KFileItem::url
KUrl url() const
KFileItem
kconfiggroup.h
QIcon
begin
const KShortcut & begin()
kiconeffect.h
KFilePreviewGenerator::setEnabledPlugins
void setEnabledPlugins(const QStringList &list)
Sets the list of enabled thumbnail plugins.
Definition: kfilepreviewgenerator.cpp:1295
QVariant
KDirLister::itemsForDir
KFileItemList itemsForDir(const KUrl &dir, WhichItems which=FilteredItems) const
KIO::PreviewJob::setSequenceIndex
void setSequenceIndex(int index)
This file is part of the KDE documentation.
Documentation copyright © 1996-2020 The KDE developers.
Generated on Mon Jun 22 2020 13:27:26 by doxygen 1.8.7 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.

KFile

Skip menu "KFile"
  • Main Page
  • 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