From 69f68a2349a6a8ef568ecb0a72f4f0e3f1903144 Mon Sep 17 00:00:00 2001 From: Peter Penz Date: Mon, 9 Jan 2012 22:10:12 +0100 Subject: [PATCH] Prevent generating previews all the time during downloading a large file When downloading a large file the preview should not be recreated each time a change-notification has been received. Create the preview after getting the first file change, but postpone creating the next previews until no change has been done during a longer period of time. BUG: 290698 FIXED-IN: 4.8.0 --- src/kitemviews/kfileitemmodelrolesupdater.cpp | 55 ++++++++++++++++++- src/kitemviews/kfileitemmodelrolesupdater.h | 15 +++++ 2 files changed, 67 insertions(+), 3 deletions(-) diff --git a/src/kitemviews/kfileitemmodelrolesupdater.cpp b/src/kitemviews/kfileitemmodelrolesupdater.cpp index 0ecc0e973..b00868a47 100644 --- a/src/kitemviews/kfileitemmodelrolesupdater.cpp +++ b/src/kitemviews/kfileitemmodelrolesupdater.cpp @@ -72,7 +72,9 @@ KFileItemModelRolesUpdater::KFileItemModelRolesUpdater(KFileItemModel* model, QO m_pendingVisibleItems(), m_pendingInvisibleItems(), m_previewJobs(), - m_resolvePendingRolesTimer(0) + m_resolvePendingRolesTimer(0), + m_changedItemsTimer(0), + m_changedItems() { Q_ASSERT(model); @@ -95,6 +97,13 @@ KFileItemModelRolesUpdater::KFileItemModelRolesUpdater(KFileItemModel* model, QO m_resolvePendingRolesTimer->setInterval(1); m_resolvePendingRolesTimer->setSingleShot(true); connect(m_resolvePendingRolesTimer, SIGNAL(timeout()), this, SLOT(resolvePendingRoles())); + + // Use a timer to prevent that each call of slotItemsChanged() results in a synchronous + // resolving of the roles. Postpone the resolving until no update has been done for 2 seconds. + m_changedItemsTimer = new QTimer(this); + m_changedItemsTimer->setInterval(2000); + m_changedItemsTimer->setSingleShot(true); + connect(m_changedItemsTimer, SIGNAL(timeout()), this, SLOT(resolveChangedItems())); } KFileItemModelRolesUpdater::~KFileItemModelRolesUpdater() @@ -270,9 +279,14 @@ void KFileItemModelRolesUpdater::slotItemsRemoved(const KItemRangeList& itemRang // Most probably a directory change is done. Clear all pending items // and also kill all ongoing preview-jobs. resetPendingRoles(); + + m_changedItems.clear(); + m_changedItemsTimer->stop(); } else { // Remove all items from m_pendingVisibleItems and m_pendingInvisibleItems - // that are not part of the model anymore. + // that are not part of the model anymore. The items from m_changedItems + // don't need to be handled here, removed items are just skipped in + // resolveChangedItems(). for (int i = 0; i <= 1; ++i) { QSet& pendingItems = (i == 0) ? m_pendingVisibleItems : m_pendingInvisibleItems; QMutableSetIterator it(pendingItems); @@ -290,7 +304,22 @@ void KFileItemModelRolesUpdater::slotItemsChanged(const KItemRangeList& itemRang const QSet& roles) { Q_UNUSED(roles); - startUpdating(itemRanges); + + if (m_changedItemsTimer->isActive()) { + // A call of slotItemsChanged() has been done recently. Postpone the resolving + // of the roles until the timer has exceeded. + foreach (const KItemRange& itemRange, itemRanges) { + int index = itemRange.index; + for (int count = itemRange.count; count >= 0; --count) { + m_changedItems.insert(m_model->fileItem(index)); + ++index; + } + } + } else { + // No call of slotItemsChanged() has been done recently, resolve the roles now. + startUpdating(itemRanges); + } + m_changedItemsTimer->start(); } void KFileItemModelRolesUpdater::slotGotPreview(const KFileItem& item, const QPixmap& pixmap) @@ -470,6 +499,26 @@ void KFileItemModelRolesUpdater::resolveNextPendingRoles() #endif } +void KFileItemModelRolesUpdater::resolveChangedItems() +{ + if (m_changedItems.isEmpty()) { + return; + } + + KItemRangeList itemRanges; + + QSetIterator it(m_changedItems); + while (it.hasNext()) { + const KFileItem& item = it.next(); + const int index = m_model->index(item); + if (index >= 0) { + itemRanges.append(KItemRange(index, 1)); + } + } + + startUpdating(itemRanges); +} + void KFileItemModelRolesUpdater::startUpdating(const KItemRangeList& itemRanges) { // If no valid index range is given assume that all items are visible. diff --git a/src/kitemviews/kfileitemmodelrolesupdater.h b/src/kitemviews/kfileitemmodelrolesupdater.h index b7d8ceab0..5ed45a6ec 100644 --- a/src/kitemviews/kfileitemmodelrolesupdater.h +++ b/src/kitemviews/kfileitemmodelrolesupdater.h @@ -126,6 +126,13 @@ private slots: void resolvePendingRoles(); void resolveNextPendingRoles(); + /** + * Resolves items that have not been resolved yet after the change has been + * notified by slotItemsChanged(). Is invoked if the m_changedItemsTimer + * exceeds. + */ + void resolveChangedItems(); + private: /** * Updates the roles for the given item ranges. The roles for the currently @@ -189,6 +196,14 @@ private: QList m_previewJobs; QTimer* m_resolvePendingRolesTimer; + + // When downloading or copying large files, the slot slotItemsChanged() + // will be called periodically within a quite short delay. To prevent + // a high CPU-load by generating e.g. previews for each notification, the update + // will be postponed until no file change has been done within a longer period + // of time. + QTimer* m_changedItemsTimer; + QSet m_changedItems; }; #endif -- 2.47.3