]> cloud.milkyroute.net Git - dolphin.git/blobdiff - src/kitemviews/kfileitemmodelrolesupdater.cpp
Fix slow scrolling when hidden files or symbolic links are shown
[dolphin.git] / src / kitemviews / kfileitemmodelrolesupdater.cpp
index bfb4e644eae0341691f64a5439dee05ea5f782bc..e9b69566d5b542ddb5234961b32bbd1652b85b61 100644 (file)
@@ -43,6 +43,7 @@
 #ifdef HAVE_NEPOMUK
     #include "private/knepomukrolesprovider.h"
     #include <Nepomuk2/ResourceWatcher>
+    #include <Nepomuk2/ResourceManager>
 #endif
 
 // Required includes for subItemsCount():
@@ -88,8 +89,6 @@ KFileItemModelRolesUpdater::KFileItemModelRolesUpdater(KFileItemModel* model, QO
     m_resolvableRoles(),
     m_enabledPlugins(),
     m_pendingSortRoleItems(),
-    m_hasUnknownIcons(false),
-    m_firstIndexWithoutIcon(0),
     m_pendingIndexes(),
     m_pendingPreviewItems(),
     m_previewJob(),
@@ -274,31 +273,33 @@ void KFileItemModelRolesUpdater::setRoles(const QSet<QByteArray>& roles)
         m_roles = roles;
 
 #ifdef HAVE_NEPOMUK
-        // Check whether there is at least one role that must be resolved
-        // with the help of Nepomuk. If this is the case, a (quite expensive)
-        // resolving will be done in KFileItemModelRolesUpdater::rolesData() and
-        // the role gets watched for changes.
-        const KNepomukRolesProvider& rolesProvider = KNepomukRolesProvider::instance();
-        bool hasNepomukRole = false;
-        QSetIterator<QByteArray> it(roles);
-        while (it.hasNext()) {
-            const QByteArray& role = it.next();
-            if (rolesProvider.roles().contains(role)) {
-                hasNepomukRole = true;
-                break;
+        if (Nepomuk2::ResourceManager::instance()->initialized()) {
+            // Check whether there is at least one role that must be resolved
+            // with the help of Nepomuk. If this is the case, a (quite expensive)
+            // resolving will be done in KFileItemModelRolesUpdater::rolesData() and
+            // the role gets watched for changes.
+            const KNepomukRolesProvider& rolesProvider = KNepomukRolesProvider::instance();
+            bool hasNepomukRole = false;
+            QSetIterator<QByteArray> it(roles);
+            while (it.hasNext()) {
+                const QByteArray& role = it.next();
+                if (rolesProvider.roles().contains(role)) {
+                    hasNepomukRole = true;
+                    break;
+                }
             }
-        }
 
-        if (hasNepomukRole && !m_nepomukResourceWatcher) {
-            Q_ASSERT(m_nepomukUriItems.isEmpty());
+            if (hasNepomukRole && !m_nepomukResourceWatcher) {
+                Q_ASSERT(m_nepomukUriItems.isEmpty());
 
-            m_nepomukResourceWatcher = new Nepomuk2::ResourceWatcher(this);
-            connect(m_nepomukResourceWatcher, SIGNAL(propertyChanged(Nepomuk2::Resource,Nepomuk2::Types::Property,QVariantList,QVariantList)),
-                    this, SLOT(applyChangedNepomukRoles(Nepomuk2::Resource)));
-        } else if (!hasNepomukRole && m_nepomukResourceWatcher) {
-            delete m_nepomukResourceWatcher;
-            m_nepomukResourceWatcher = 0;
-            m_nepomukUriItems.clear();
+                m_nepomukResourceWatcher = new Nepomuk2::ResourceWatcher(this);
+                connect(m_nepomukResourceWatcher, SIGNAL(propertyChanged(Nepomuk2::Resource,Nepomuk2::Types::Property,QVariantList,QVariantList)),
+                        this, SLOT(applyChangedNepomukRoles(Nepomuk2::Resource,Nepomuk2::Types::Property)));
+            } else if (!hasNepomukRole && m_nepomukResourceWatcher) {
+                delete m_nepomukResourceWatcher;
+                m_nepomukResourceWatcher = 0;
+                m_nepomukUriItems.clear();
+            }
         }
 #endif
 
@@ -330,10 +331,6 @@ void KFileItemModelRolesUpdater::slotItemsInserted(const KItemRangeList& itemRan
     QElapsedTimer timer;
     timer.start();
 
-    const int firstInsertedIndex = itemRanges.first().index;
-    m_firstIndexWithoutIcon = qMin(m_firstIndexWithoutIcon, firstInsertedIndex);
-    m_hasUnknownIcons = true;
-
     // Determine the sort role synchronously for as many items as possible.
     if (m_resolvableRoles.contains(m_model->sortRole())) {
         int insertedCount = 0;
@@ -370,11 +367,6 @@ void KFileItemModelRolesUpdater::slotItemsRemoved(const KItemRangeList& itemRang
 
     const bool allItemsRemoved = (m_model->count() == 0);
 
-    if (m_hasUnknownIcons) {
-        const int firstRemovedIndex = itemRanges.first().index;
-        m_firstIndexWithoutIcon = qMin(m_firstIndexWithoutIcon, firstRemovedIndex);
-    }
-
     if (!m_watchedDirs.isEmpty()) {
         // Don't let KDirWatch watch for removed items
         if (allItemsRemoved) {
@@ -456,11 +448,6 @@ void KFileItemModelRolesUpdater::slotItemsMoved(const KItemRange& itemRange, QLi
     Q_UNUSED(itemRange);
     Q_UNUSED(movedToIndexes);
 
-    if (m_hasUnknownIcons) {
-        const int firstMovedIndex = itemRange.index;
-        m_firstIndexWithoutIcon = qMin(m_firstIndexWithoutIcon, firstMovedIndex);
-    }
-
     // The visible items might have changed.
     startUpdating();
 }
@@ -583,6 +570,22 @@ void KFileItemModelRolesUpdater::slotGotPreview(const KFileItem& item, const QPi
     }
 
     QHash<QByteArray, QVariant> 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<QByteArray>)),
@@ -678,7 +681,7 @@ void KFileItemModelRolesUpdater::resolveNextSortRole()
 
 void KFileItemModelRolesUpdater::resolveNextPendingRoles()
 {
-    if (m_state != ResolvingAllRoles && m_state != PreviewJobRunning) {
+    if (m_state != ResolvingAllRoles) {
         return;
     }
 
@@ -690,21 +693,15 @@ void KFileItemModelRolesUpdater::resolveNextPendingRoles()
             continue;
         }
 
-        if (m_previewShown) {
-            // Only determine the icon. The other roles are resolved when the preview is received.
-            applyResolvedRoles(item, ResolveFast);
-        } else {
-            applyResolvedRoles(item, ResolveAll);
-            m_finishedItems.insert(item);
-            m_changedItems.remove(item);
-        }
-
+        applyResolvedRoles(item, ResolveAll);
+        m_finishedItems.insert(item);
+        m_changedItems.remove(item);
         break;
     }
 
     if (!m_pendingIndexes.isEmpty()) {
         QTimer::singleShot(0, this, SLOT(resolveNextPendingRoles()));
-    } else if (m_state != PreviewJobRunning) {
+    } else {
         m_state = Idle;
 
         if (m_clearPreviews) {
@@ -740,9 +737,13 @@ void KFileItemModelRolesUpdater::resolveRecentlyChangedItems()
     updateChangedItems();
 }
 
-void KFileItemModelRolesUpdater::applyChangedNepomukRoles(const Nepomuk2::Resource& resource)
+void KFileItemModelRolesUpdater::applyChangedNepomukRoles(const Nepomuk2::Resource& resource, const Nepomuk2::Types::Property& property)
 {
 #ifdef HAVE_NEPOMUK
+    if (!Nepomuk2::ResourceManager::instance()->initialized()) {
+        return;
+    }
+
     const KUrl itemUrl = m_nepomukUriItems.value(resource.uri());
     const KFileItem item = m_model->fileItem(itemUrl);
 
@@ -755,6 +756,14 @@ void KFileItemModelRolesUpdater::applyChangedNepomukRoles(const Nepomuk2::Resour
     QHash<QByteArray, QVariant> data = rolesData(item);
 
     const KNepomukRolesProvider& rolesProvider = KNepomukRolesProvider::instance();
+    const QByteArray role = rolesProvider.roleForPropertyUri(property.uri());
+    if (!role.isEmpty() && m_roles.contains(role)) {
+        // Overwrite the changed role value with an empty QVariant, because the roles
+        // provider doesn't overwrite it when the property value list is empty.
+        // See bug 322348
+        data.insert(role, QVariant());
+    }
+
     QHashIterator<QByteArray, QVariant> it(rolesProvider.roleValues(resource, m_roles));
     while (it.hasNext()) {
         it.next();
@@ -828,13 +837,6 @@ void KFileItemModelRolesUpdater::startUpdating()
     // Determine the icons for the visible items synchronously.
     updateVisibleIcons();
 
-    // Try to do at least a fast icon loading (without determining the
-    // mime type) for all items, to reduce the risk that the user sees
-    // "unknown" icons when scrolling.
-    if (m_hasUnknownIcons) {
-        updateAllIconsFast(MaxBlockTimeout - timer.elapsed());
-    }
-
     // A detailed update of the items in and near the visible area
     // only makes sense if sorting is finished.
     if (m_state == ResolvingSortRole) {
@@ -886,58 +888,9 @@ void KFileItemModelRolesUpdater::updateVisibleIcons()
         applyResolvedRoles(item, ResolveFast);
     }
 
-    if (index > lastVisibleIndex) {
-        return;
-    }
-
-    // If this didn't work before MaxBlockTimeout was reached, at least
-    // prevent that the user sees 'unknown' icons.
-    disconnect(m_model, SIGNAL(itemsChanged(KItemRangeList,QSet<QByteArray>)),
-               this,    SLOT(slotItemsChanged(KItemRangeList,QSet<QByteArray>)));
-
-    while (index <= lastVisibleIndex) {
-        if (!m_model->data(index).contains("iconName")) {
-            const KFileItem item = m_model->fileItem(index);
-            QHash<QByteArray, QVariant> data;
-            data.insert("iconName", item.iconName());
-            m_model->setData(index, data);
-        }
-        ++index;
-    }
-
-    connect(m_model, SIGNAL(itemsChanged(KItemRangeList,QSet<QByteArray>)),
-            this,    SLOT(slotItemsChanged(KItemRangeList,QSet<QByteArray>)));
-}
-
-void KFileItemModelRolesUpdater::updateAllIconsFast(int timeout)
-{
-    if (timeout <= 0) {
-        return;
-    }
-
-    QElapsedTimer timer;
-    timer.start();
-
-    disconnect(m_model, SIGNAL(itemsChanged(KItemRangeList,QSet<QByteArray>)),
-               this,    SLOT(slotItemsChanged(KItemRangeList,QSet<QByteArray>)));
-
-    const int count = m_model->count();
-    while (m_firstIndexWithoutIcon < count && timer.elapsed() < timeout) {
-        if (!m_model->data(m_firstIndexWithoutIcon).contains("iconName")) {
-            const KFileItem item = m_model->fileItem(m_firstIndexWithoutIcon);
-            QHash<QByteArray, QVariant> data;
-            data.insert("iconName", item.iconName());
-            m_model->setData(m_firstIndexWithoutIcon, data);
-        }
-        ++m_firstIndexWithoutIcon;
-    }
-
-    if (m_firstIndexWithoutIcon == count) {
-        m_hasUnknownIcons = false;
-    }
-
-    connect(m_model, SIGNAL(itemsChanged(KItemRangeList,QSet<QByteArray>)),
-            this,    SLOT(slotItemsChanged(KItemRangeList,QSet<QByteArray>)));
+    // KFileItemListView::initializeItemListWidget(KItemListWidget*) will load
+    // preliminary icons (i.e., without mime type determination) for the
+    // remaining items.
 }
 
 void KFileItemModelRolesUpdater::startPreviewJob()
@@ -1117,9 +1070,7 @@ bool KFileItemModelRolesUpdater::applyResolvedRoles(const KFileItem& item, Resol
     if (!item.isMimeTypeKnown() || !item.isFinalIconKnown()) {
         item.determineMimeType();
         iconChanged = true;
-    } else if (m_state == ResolvingSortRole || m_state == PreviewJobRunning) {
-        // We are currently performing a fast determination of all icons
-        // in the visible area.
+    } else {
         const int index = m_model->index(item);
         if (!m_model->data(index).contains("iconName")) {
             iconChanged = true;