From d27f776cd2675e67b70556ad4033230435d89d8e Mon Sep 17 00:00:00 2001 From: Peter Penz Date: Mon, 31 Oct 2011 19:32:31 +0100 Subject: Internal KFileItemModel optimizations and cleanups - Use merge-sort instead of quick-sort. This assures a sane worst-case scenario where quick-sort has a runtime complexity of O(n*n) (e.g. when changing the sort-order from ascending to descending). - lessThan()-improvements: Change internal data-structures to allow a comparison of any role, not only roles available in KFileItem - Don't synchronously move an item if the value has been changed of a role defined as sort-role: This is too expensive in case if e.g. the sorting is done by "type" and the type is determined step by step. --- src/kitemviews/kfileitemmodel.h | 72 ++++++++++++++++++++++++++++++++--------- 1 file changed, 57 insertions(+), 15 deletions(-) (limited to 'src/kitemviews/kfileitemmodel.h') diff --git a/src/kitemviews/kfileitemmodel.h b/src/kitemviews/kfileitemmodel.h index 8bf299003..b28887b2c 100644 --- a/src/kitemviews/kfileitemmodel.h +++ b/src/kitemviews/kfileitemmodel.h @@ -131,6 +131,12 @@ protected: virtual void onSortOrderChanged(Qt::SortOrder current, Qt::SortOrder previous); private slots: + /** + * Resorts all items dependent on the set sortRole(), sortOrder() + * and foldersFirst() settings. + */ + void resortAllItems(); + void slotCompleted(); void slotCanceled(); void slotNewItems(const KFileItemList& items); @@ -142,13 +148,6 @@ private slots: void dispatchPendingItemsToInsert(); private: - void insertItems(const KFileItemList& items); - void removeItems(const KFileItemList& items); - - void resortAllItems(); - - void removeExpandedItems(); - enum Role { NoRole, NameRole, @@ -169,6 +168,25 @@ private: RolesCount // Mandatory last entry }; + struct ItemData + { + KFileItem item; + QHash values; + }; + + void insertItems(const KFileItemList& items); + void removeItems(const KFileItemList& items); + + /** + * Helper method for insertItems() and removeItems(): Creates + * a list of ItemData elements based on the given items. + * Note that the ItemData instances are created dynamically and + * must be deleted by the caller. + */ + QList createItemDataList(const KFileItemList& items) const; + + void removeExpandedItems(); + /** * Resets all values from m_requestRole to false. */ @@ -177,9 +195,33 @@ private: Role roleIndex(const QByteArray& role) const; QHash retrieveData(const KFileItem& item) const; - - bool lessThan(const KFileItem& a, const KFileItem& b) const; - void sort(const KFileItemList::iterator& start, const KFileItemList::iterator& end); + + bool lessThan(const ItemData* a, const ItemData* b) const; + + /** + * Sorts the items by using lessThan() as comparison criteria. + * The merge sort algorithm is used to assure a worst-case + * of O(n * log(n)) and to keep the number of comparisons low. + */ + void sort(QList::iterator begin, QList::iterator end); + + /** Helper method for sort(). */ + void merge(QList::iterator begin, + QList::iterator pivot, + QList::iterator end); + + /** Helper method for sort(). */ + QList::iterator lowerBound(QList::iterator begin, + QList::iterator end, + const ItemData* value); + + /** Helper method for sort(). */ + QList::iterator upperBound(QList::iterator begin, + QList::iterator end, + const ItemData* value); + /** Helper method for sort(). */ + void reverse(QList::iterator begin, QList::iterator end); + int stringCompare(const QString& a, const QString& b) const; /** @@ -226,15 +268,15 @@ private: Role m_sortRole; QSet m_roles; Qt::CaseSensitivity m_caseSensitivity; - - KFileItemList m_sortedItems; // Allows O(1) access for KFileItemModel::fileItem(int index) - QHash m_items; // Allows O(1) access for KFileItemModel::index(const KFileItem& item) - QList > m_data; + + QList m_itemData; + QHash m_items; // Allows O(1) access for KFileItemModel::index(const KFileItem& item) bool m_requestRole[RolesCount]; QTimer* m_minimumUpdateIntervalTimer; QTimer* m_maximumUpdateIntervalTimer; + QTimer* m_resortAllItemsTimer; KFileItemList m_pendingItemsToInsert; bool m_pendingEmitLoadingCompleted; @@ -257,7 +299,7 @@ private: inline bool KFileItemModel::isChildItem(int index) const { - return m_requestRole[ExpansionLevelRole] && m_data.at(index).value("expansionLevel").toInt() > 0; + return m_requestRole[ExpansionLevelRole] && m_itemData.at(index)->values.value("expansionLevel").toInt() > 0; } #endif -- cgit v1.3.1