X-Git-Url: https://cloud.milkyroute.net/gitweb/dolphin.git/blobdiff_plain/629ec98952bcf38bc99f2b11bc37bdc2ec7aabcc..b8a4e0fac2820ec8fc442c2abeea700ae4947e01:/src/iconmanager.cpp diff --git a/src/iconmanager.cpp b/src/iconmanager.cpp index 002f4e86d..94432102c 100644 --- a/src/iconmanager.cpp +++ b/src/iconmanager.cpp @@ -154,28 +154,11 @@ void IconManager::generatePreviews(const KFileItemList& items) return; } - // Order the items in a way that the preview for the visible items - // is generated first, as this improves the feeled performance a lot. - // Implementation note: using KDirModel::itemForUrl() would lead to a more - // readable code, but it is a lot slower in comparison to itemListContains(). - const QRect visibleArea = m_view->viewport()->rect(); - KFileItemList orderedItems; - const int rowCount = m_proxyModel->rowCount(); - for (int row = 0; row < rowCount; ++row) { - const QModelIndex proxyIndex = m_proxyModel->index(row, 0); - const QRect itemRect = m_view->visualRect(proxyIndex); - const QModelIndex dirIndex = m_proxyModel->mapToSource(proxyIndex); - KFileItem item = m_dolphinModel->itemForIndex(dirIndex); - const KUrl url = item.url(); - if (itemListContains(items, url)) { - if (itemRect.intersects(visibleArea)) { - orderedItems.insert(0, item); - m_pendingItems.insert(0, url); - } else { - orderedItems.append(item); - m_pendingItems.append(url); - } - } + KFileItemList orderedItems = items; + orderItems(orderedItems); + + foreach (const KFileItem& item, orderedItems) { + m_pendingItems.append(item); } startPreviewJob(orderedItems); @@ -188,7 +171,7 @@ void IconManager::addToPreviewQueue(const KFileItem& item, const QPixmap& pixmap preview.pixmap = pixmap; m_previews.append(preview); - m_dispatchedItems.append(item.url()); + m_dispatchedItems.append(item); } void IconManager::slotPreviewJobFinished(KJob* job) @@ -269,11 +252,11 @@ void IconManager::resumePreviews() // queue is usually equal. So even when having a lot of elements the // nested loop is no performance bottle neck, as the inner loop is only // entered once in most cases. - foreach (const KUrl& url, m_dispatchedItems) { - QList::iterator begin = m_pendingItems.begin(); - QList::iterator end = m_pendingItems.end(); - for (QList::iterator it = begin; it != end; ++it) { - if ((*it) == url) { + foreach (const KFileItem& item, m_dispatchedItems) { + KFileItemList::iterator begin = m_pendingItems.begin(); + KFileItemList::iterator end = m_pendingItems.end(); + for (KFileItemList::iterator it = begin; it != end; ++it) { + if ((*it).url() == item.url()) { m_pendingItems.erase(it); break; } @@ -281,30 +264,8 @@ void IconManager::resumePreviews() } m_dispatchedItems.clear(); - // Create a new preview job for the remaining items. - // Order the items in a way that the preview for the visible items - // is generated first, as this improves the feeled performance a lot. - // Implementation note: using KDirModel::itemForUrl() would lead to a more - // readable code, but it is a lot slower in comparison - // to m_pendingItems.contains(). - const QRect visibleArea = m_view->viewport()->rect(); - KFileItemList orderedItems; - - const int rowCount = m_proxyModel->rowCount(); - for (int row = 0; row < rowCount; ++row) { - const QModelIndex proxyIndex = m_proxyModel->index(row, 0); - const QRect itemRect = m_view->visualRect(proxyIndex); - const QModelIndex dirIndex = m_proxyModel->mapToSource(proxyIndex); - KFileItem item = m_dolphinModel->itemForIndex(dirIndex); - const KUrl url = item.url(); - if (m_pendingItems.contains(url)) { - if (itemRect.intersects(visibleArea)) { - orderedItems.insert(0, item); - } else { - orderedItems.append(item); - } - } - } + KFileItemList orderedItems = m_pendingItems; + orderItems(orderedItems); // Kill all suspended preview jobs. Usually when a preview job // has been finished, slotPreviewJobFinished() clears all item queues. @@ -520,14 +481,67 @@ void IconManager::killPreviewJobs() m_previewJobs.clear(); } -bool IconManager::itemListContains(const KFileItemList& items, const KUrl& url) const +void IconManager::orderItems(KFileItemList& items) { - foreach (const KFileItem& item, items) { - if (url == item.url()) { - return true; + // Order the items in a way that the preview for the visible items + // is generated first, as this improves the feeled performance a lot. + // + // Implementation note: 2 different algorithms are used for the sorting. + // Algorithm 1 is faster when having a lot of items in comparison + // to the number of rows in the model. Algorithm 2 is faster + // when having quite less items in comparison to the number of rows in + // the model. Choosing the right algorithm is important when having directories + // with several hundreds or thousands of items. + + const int itemCount = items.count(); + const int rowCount = m_proxyModel->rowCount(); + const QRect visibleArea = m_view->viewport()->rect(); + + if (itemCount * 10 > rowCount) { + // Algorithm 1: The number of items is > 10 % of the row count. Parse all rows + // and check whether the received row is part of the item list. + for (int row = 0; row < rowCount; ++row) { + const QModelIndex proxyIndex = m_proxyModel->index(row, 0); + const QRect itemRect = m_view->visualRect(proxyIndex); + const QModelIndex dirIndex = m_proxyModel->mapToSource(proxyIndex); + + KFileItem item = m_dolphinModel->itemForIndex(dirIndex); // O(1) + const KUrl url = item.url(); + + // check whether the item is part of the item list 'items' + int index = -1; + for (int i = 0; i < itemCount; ++i) { + if (items[i].url() == url) { + index = i; + break; + } + } + + if ((index > 0) && itemRect.intersects(visibleArea)) { + // The current item is (at least partly) visible. Move it + // to the front of the list, so that the preview is + // generated earlier. + items.removeAt(index); + items.insert(0, item); + } + } + } else { + // Algorithm 2: The number of items is <= 10 % of the row count. In this case iterate + // all items and receive the corresponding row from the item. + for (int i = 0; i < itemCount; ++i) { + const QModelIndex dirIndex = m_dolphinModel->indexForItem(items[i]); // O(n) (n = number of rows) + const QModelIndex proxyIndex = m_proxyModel->mapFromSource(dirIndex); + const QRect itemRect = m_view->visualRect(proxyIndex); + + if (itemRect.intersects(visibleArea)) { + // The current item is (at least partly) visible. Move it + // to the front of the list, so that the preview is + // generated earlier. + items.insert(0, items[i]); + items.removeAt(i + 1); + } } } - return false; } #include "iconmanager.moc"