QObject(parent),
m_showPreview(false),
m_view(parent),
+ m_previewTimer(0),
m_previewJobs(),
m_dolphinModel(0),
m_proxyModel(model),
- m_cutItemsCache()
+ m_cutItemsCache(),
+ m_previews()
{
Q_ASSERT(m_view->iconSize().isValid()); // each view must provide its current icon size
QClipboard* clipboard = QApplication::clipboard();
connect(clipboard, SIGNAL(dataChanged()),
this, SLOT(updateCutItems()));
+
+ m_previewTimer = new QTimer(this);
+ connect(m_previewTimer, SIGNAL(timeout()), this, SLOT(dispatchPreviewQueue()));
}
IconManager::~IconManager()
}
}
-void IconManager::replaceIcon(const KFileItem& item, const QPixmap& pixmap)
+void IconManager::addToPreviewQueue(const KFileItem& item, const QPixmap& pixmap)
{
- Q_ASSERT(!item.isNull());
- if (!m_showPreview) {
- // the preview has been canceled in the meantime
- return;
- }
-
- // check whether the item is part of the directory lister (it is possible
- // that a preview from an old directory lister is received)
- KDirLister* dirLister = m_dolphinModel->dirLister();
- bool isOldPreview = true;
- const KUrl::List dirs = dirLister->directories();
- const QString itemDir = item.url().directory();
- foreach (KUrl url, dirs) {
- if (url.path() == itemDir) {
- isOldPreview = false;
- break;
- }
- }
- if (isOldPreview) {
- return;
- }
-
- const QModelIndex idx = m_dolphinModel->indexForItem(item);
- if (idx.isValid() && (idx.column() == 0)) {
- QPixmap icon = pixmap;
-
- const QString mimeType = item.mimetype();
- const QString mimeTypeGroup = mimeType.left(mimeType.indexOf('/'));
- if ((mimeTypeGroup != "image") || !applyImageFrame(icon)) {
- limitToSize(icon, m_view->iconSize());
- }
-
- const QMimeData* mimeData = QApplication::clipboard()->mimeData();
- if (KonqMimeData::decodeIsCutSelection(mimeData) && isCutItem(item)) {
- KIconEffect iconEffect;
- icon = iconEffect.apply(icon, KIconLoader::Desktop, KIconLoader::DisabledState);
- m_dolphinModel->setData(idx, QIcon(icon), Qt::DecorationRole);
- } else {
- m_dolphinModel->setData(idx, QIcon(icon), Qt::DecorationRole);
- }
- }
+ Preview preview;
+ preview.item = item;
+ preview.pixmap = pixmap;
+ m_previews.append(preview);
}
void IconManager::slotPreviewJobFinished(KJob* job)
applyCutItemEffect();
}
+void IconManager::dispatchPreviewQueue()
+{
+ const int previewsCount = m_previews.count();
+ if (previewsCount == 0) {
+ return;
+ }
+
+ // Applying the previews to the model must be done step by step
+ // in larger blocks: Applying a preview immediately when getting the signal
+ // 'gotPreview()' from the PreviewJob is too expensive, as a relayout
+ // of the view would be triggered for each single preview.
+
+ int dispatchCount = 30;
+ if (dispatchCount > previewsCount) {
+ dispatchCount = previewsCount;
+ }
+
+ for (int i = 0; i < dispatchCount; ++i) {
+ const Preview& preview = m_previews.first();
+ replaceIcon(preview.item, preview.pixmap);
+ m_previews.pop_front();
+ }
+
+ if (m_previews.count() > 0) {
+ // there are still pending previews; if no preview job is
+ // working, poll more aggressively:
+ const int timeout = (m_previewJobs.count() > 0) ? 200 : 10;
+ m_previewTimer->start(timeout);
+ }
+}
+
void IconManager::generatePreviews(const KFileItemList &items)
{
Q_ASSERT(m_showPreview);
const QSize size = m_view->iconSize();
KIO::PreviewJob* job = KIO::filePreview(orderedItems, 128, 128);
connect(job, SIGNAL(gotPreview(const KFileItem&, const QPixmap&)),
- this, SLOT(replaceIcon(const KFileItem&, const QPixmap&)));
+ this, SLOT(addToPreviewQueue(const KFileItem&, const QPixmap&)));
connect(job, SIGNAL(finished(KJob*)),
this, SLOT(slotPreviewJobFinished(KJob*)));
m_previewJobs.append(job);
+ m_previewTimer->start(200);
+}
+
+void IconManager::replaceIcon(const KFileItem& item, const QPixmap& pixmap)
+{
+ Q_ASSERT(!item.isNull());
+ if (!m_showPreview) {
+ // the preview has been canceled in the meantime
+ return;
+ }
+
+ // check whether the item is part of the directory lister (it is possible
+ // that a preview from an old directory lister is received)
+ KDirLister* dirLister = m_dolphinModel->dirLister();
+ bool isOldPreview = true;
+ const KUrl::List dirs = dirLister->directories();
+ const QString itemDir = item.url().directory();
+ foreach (KUrl url, dirs) {
+ if (url.path() == itemDir) {
+ isOldPreview = false;
+ break;
+ }
+ }
+ if (isOldPreview) {
+ return;
+ }
+
+ const QModelIndex idx = m_dolphinModel->indexForItem(item);
+ if (idx.isValid() && (idx.column() == 0)) {
+ QPixmap icon = pixmap;
+
+ const QString mimeType = item.mimetype();
+ const QString mimeTypeGroup = mimeType.left(mimeType.indexOf('/'));
+ if ((mimeTypeGroup != "image") || !applyImageFrame(icon)) {
+ limitToSize(icon, m_view->iconSize());
+ }
+
+ const QMimeData* mimeData = QApplication::clipboard()->mimeData();
+ if (KonqMimeData::decodeIsCutSelection(mimeData) && isCutItem(item)) {
+ KIconEffect iconEffect;
+ icon = iconEffect.apply(icon, KIconLoader::Desktop, KIconLoader::DisabledState);
+ m_dolphinModel->setData(idx, QIcon(icon), Qt::DecorationRole);
+ } else {
+ m_dolphinModel->setData(idx, QIcon(icon), Qt::DecorationRole);
+ }
+ }
}
bool IconManager::isCutItem(const KFileItem& item) const
void updateIcons(const KFileItemList& items);
/**
- * Replaces the icon of the item \a item by the preview pixmap
- * \a pixmap.
+ * Adds the preview \a pixmap for the item \a item to the preview
+ * queue and starts a timer which will dispatch the preview queue
+ * later.
*/
- void replaceIcon(const KFileItem& item, const QPixmap& pixmap);
+ void addToPreviewQueue(const KFileItem& item, const QPixmap& pixmap);
/**
* Is invoked when the preview job has been finished and
/** Synchronizes the item icon with the clipboard of cut items. */
void updateCutItems();
+ /**
+ * Dispatches the preview queue m_previews block by block within
+ * time slices.
+ */
+ void dispatchPreviewQueue();
+
private:
void generatePreviews(const KFileItemList &items);
+ /**
+ * Replaces the icon of the item \a item by the preview pixmap
+ * \a pixmap.
+ */
+ void replaceIcon(const KFileItem& item, const QPixmap& pixmap);
+
/**
* Returns true, if the item \a item has been cut into
* the clipboard.
QPixmap pixmap;
};
+ /**
+ * Remembers the received preview pixmap for an item.
+ */
+ struct Preview
+ {
+ KFileItem item;
+ QPixmap pixmap;
+ };
+
bool m_showPreview;
QAbstractItemView* m_view;
+ QTimer* m_previewTimer;
QList<KJob*> m_previewJobs;
DolphinModel* m_dolphinModel;
DolphinSortFilterProxyModel* m_proxyModel;
QList<CutItem> m_cutItemsCache;
+ QList<Preview> m_previews;
};
inline bool IconManager::showPreview() const