From fd5ba3b4b22e923cff11b65654e9b6f931ce9a3c Mon Sep 17 00:00:00 2001 From: Frank Reininghaus Date: Wed, 14 Aug 2013 23:44:57 +0200 Subject: [PATCH] Fix slow scrolling when hidden files or symbolic links are shown The problem was that we drawed the overlays using KIconLoader, which can be very slow, every time an item appeared on the screen. This commit makes sure that not only the icon, but the icon including overlays is cached in QPixmapCache. Therefore, the overlay drawing is done just once for each icon+overlays combination. For previews, the overlay drawing is done in KFileItemModelRolesUpdater just after the preview is received. BUG: 310662 BUG: 314339 FIXED-IN: 4.11.1 REVIEW: 111956 --- src/kitemviews/kfileitemmodelrolesupdater.cpp | 16 ++++++++ src/kitemviews/kstandarditemlistwidget.cpp | 37 +++++++++---------- src/kitemviews/kstandarditemlistwidget.h | 2 +- 3 files changed, 35 insertions(+), 20 deletions(-) diff --git a/src/kitemviews/kfileitemmodelrolesupdater.cpp b/src/kitemviews/kfileitemmodelrolesupdater.cpp index 698a6c5f00..e9b69566d5 100644 --- a/src/kitemviews/kfileitemmodelrolesupdater.cpp +++ b/src/kitemviews/kfileitemmodelrolesupdater.cpp @@ -570,6 +570,22 @@ void KFileItemModelRolesUpdater::slotGotPreview(const KFileItem& item, const QPi } QHash data = rolesData(item); + + const QStringList overlays = data["iconOverlays"].toStringList(); + // Strangely KFileItem::overlays() returns empty string-values, so + // we need to check first whether an overlay must be drawn at all. + // It is more efficient to do it here, as KIconLoader::drawOverlays() + // assumes that an overlay will be drawn and has some additional + // setup time. + foreach (const QString& overlay, overlays) { + if (!overlay.isEmpty()) { + // There is at least one overlay, draw all overlays above m_pixmap + // and cancel the check + KIconLoader::global()->drawOverlays(overlays, scaledPixmap, KIconLoader::Desktop); + break; + } + } + data.insert("iconPixmap", scaledPixmap); disconnect(m_model, SIGNAL(itemsChanged(KItemRangeList,QSet)), diff --git a/src/kitemviews/kstandarditemlistwidget.cpp b/src/kitemviews/kstandarditemlistwidget.cpp index b429211b88..621cd81cc8 100644 --- a/src/kitemviews/kstandarditemlistwidget.cpp +++ b/src/kitemviews/kstandarditemlistwidget.cpp @@ -839,29 +839,14 @@ void KStandardItemListWidget::updatePixmapCache() // use a generic icon as fallback iconName = QLatin1String("unknown"); } - m_pixmap = pixmapForIcon(iconName, maxIconHeight); + const QStringList overlays = values["iconOverlays"].toStringList(); + m_pixmap = pixmapForIcon(iconName, overlays, maxIconHeight); } else if (m_pixmap.width() != maxIconWidth || m_pixmap.height() != maxIconHeight) { // A custom pixmap has been applied. Assure that the pixmap // is scaled to the maximum available size. KPixmapModifier::scale(m_pixmap, QSize(maxIconWidth, maxIconHeight)); } - const QStringList overlays = values["iconOverlays"].toStringList(); - - // Strangely KFileItem::overlays() returns empty string-values, so - // we need to check first whether an overlay must be drawn at all. - // It is more efficient to do it here, as KIconLoader::drawOverlays() - // assumes that an overlay will be drawn and has some additional - // setup time. - foreach (const QString& overlay, overlays) { - if (!overlay.isEmpty()) { - // There is at least one overlay, draw all overlays above m_pixmap - // and cancel the check - KIconLoader::global()->drawOverlays(overlays, m_pixmap, KIconLoader::Desktop); - break; - } - } - if (m_isCut) { KIconEffect* effect = KIconLoader::global()->iconEffect(); m_pixmap = effect->apply(m_pixmap, KIconLoader::Desktop, KIconLoader::DisabledState); @@ -1323,9 +1308,9 @@ void KStandardItemListWidget::closeRoleEditor() m_roleEditor = 0; } -QPixmap KStandardItemListWidget::pixmapForIcon(const QString& name, int size) +QPixmap KStandardItemListWidget::pixmapForIcon(const QString& name, const QStringList& overlays, int size) { - const QString key = "KStandardItemListWidget:" % name % ":" % QString::number(size); + const QString key = "KStandardItemListWidget:" % name % ":" % overlays.join(":") % ":" % QString::number(size); QPixmap pixmap; if (!QPixmapCache::find(key, pixmap)) { @@ -1355,6 +1340,20 @@ QPixmap KStandardItemListWidget::pixmapForIcon(const QString& name, int size) KPixmapModifier::scale(pixmap, QSize(size, size)); } + // Strangely KFileItem::overlays() returns empty string-values, so + // we need to check first whether an overlay must be drawn at all. + // It is more efficient to do it here, as KIconLoader::drawOverlays() + // assumes that an overlay will be drawn and has some additional + // setup time. + foreach (const QString& overlay, overlays) { + if (!overlay.isEmpty()) { + // There is at least one overlay, draw all overlays above m_pixmap + // and cancel the check + KIconLoader::global()->drawOverlays(overlays, pixmap, KIconLoader::Desktop); + break; + } + } + QPixmapCache::insert(key, pixmap); } diff --git a/src/kitemviews/kstandarditemlistwidget.h b/src/kitemviews/kstandarditemlistwidget.h index ecf3a3b606..4bf6116fd1 100644 --- a/src/kitemviews/kstandarditemlistwidget.h +++ b/src/kitemviews/kstandarditemlistwidget.h @@ -186,7 +186,7 @@ private: */ void closeRoleEditor(); - static QPixmap pixmapForIcon(const QString& name, int size); + static QPixmap pixmapForIcon(const QString& name, const QStringList& overlays, int size); /** * @return Preferred size of the rating-image based on the given