mirror of
https://invent.kde.org/system/dolphin
synced 2024-11-05 18:47:12 +00:00
Extract sorting-algorithm from KFileItemModel into custom class
This commit is contained in:
parent
4657459937
commit
1e6031c04d
5 changed files with 225 additions and 150 deletions
|
@ -23,6 +23,7 @@ set(dolphinprivate_LIB_SRCS
|
|||
kitemviews/kfileitemlistview.cpp
|
||||
kitemviews/kfileitemlistwidget.cpp
|
||||
kitemviews/kfileitemmodel.cpp
|
||||
kitemviews/kfileitemmodelsortalgorithm.cpp
|
||||
kitemviews/kfileitemmodelfilter.cpp
|
||||
kitemviews/kfileitemmodelrolesupdater.cpp
|
||||
kitemviews/kitemlistcontainer.cpp
|
||||
|
|
|
@ -21,6 +21,7 @@
|
|||
|
||||
#include <KDirLister>
|
||||
#include <KDirModel>
|
||||
#include "kfileitemmodelsortalgorithm_p.h"
|
||||
#include <KGlobalSettings>
|
||||
#include <KLocale>
|
||||
#include <KStringHandler>
|
||||
|
@ -613,7 +614,7 @@ void KFileItemModel::resortAllItems()
|
|||
m_items.clear();
|
||||
|
||||
// Resort the items
|
||||
sort(m_itemData.begin(), m_itemData.end());
|
||||
KFileItemModelSortAlgorithm::sort(this, m_itemData.begin(), m_itemData.end());
|
||||
for (int i = 0; i < itemCount; ++i) {
|
||||
m_items.insert(m_itemData.at(i)->item.url(), i);
|
||||
}
|
||||
|
@ -887,7 +888,7 @@ void KFileItemModel::insertItems(const KFileItemList& items)
|
|||
m_groups.clear();
|
||||
|
||||
QList<ItemData*> sortedItems = createItemDataList(items);
|
||||
sort(sortedItems.begin(), sortedItems.end());
|
||||
KFileItemModelSortAlgorithm::sort(this, sortedItems.begin(), sortedItems.end());
|
||||
|
||||
#ifdef KFILEITEMMODEL_DEBUG
|
||||
kDebug() << "[TIME] Sorting:" << timer.elapsed();
|
||||
|
@ -966,7 +967,7 @@ void KFileItemModel::removeItems(const KFileItemList& items)
|
|||
sortedItems.append(m_itemData.at(index));
|
||||
}
|
||||
}
|
||||
sort(sortedItems.begin(), sortedItems.end());
|
||||
KFileItemModelSortAlgorithm::sort(this, sortedItems.begin(), sortedItems.end());
|
||||
|
||||
QList<int> indexesToRemove;
|
||||
indexesToRemove.reserve(items.count());
|
||||
|
@ -1386,128 +1387,6 @@ int KFileItemModel::sortRoleCompare(const ItemData* a, const ItemData* b) const
|
|||
return QString::compare(itemA.url().url(), itemB.url().url(), Qt::CaseSensitive);
|
||||
}
|
||||
|
||||
void KFileItemModel::sort(QList<ItemData*>::iterator begin,
|
||||
QList<ItemData*>::iterator end)
|
||||
{
|
||||
// The implementation is based on qStableSortHelper() from qalgorithms.h
|
||||
// Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
|
||||
// In opposite to qStableSort() it allows to use a member-function for the comparison of elements.
|
||||
|
||||
const int span = end - begin;
|
||||
if (span < 2) {
|
||||
return;
|
||||
}
|
||||
|
||||
const QList<ItemData*>::iterator middle = begin + span / 2;
|
||||
sort(begin, middle);
|
||||
sort(middle, end);
|
||||
merge(begin, middle, end);
|
||||
}
|
||||
|
||||
void KFileItemModel::merge(QList<ItemData*>::iterator begin,
|
||||
QList<ItemData*>::iterator pivot,
|
||||
QList<ItemData*>::iterator end)
|
||||
{
|
||||
// The implementation is based on qMerge() from qalgorithms.h
|
||||
// Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
|
||||
|
||||
const int len1 = pivot - begin;
|
||||
const int len2 = end - pivot;
|
||||
|
||||
if (len1 == 0 || len2 == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (len1 + len2 == 2) {
|
||||
if (lessThan(*(begin + 1), *(begin))) {
|
||||
qSwap(*begin, *(begin + 1));
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
QList<ItemData*>::iterator firstCut;
|
||||
QList<ItemData*>::iterator secondCut;
|
||||
int len2Half;
|
||||
if (len1 > len2) {
|
||||
const int len1Half = len1 / 2;
|
||||
firstCut = begin + len1Half;
|
||||
secondCut = lowerBound(pivot, end, *firstCut);
|
||||
len2Half = secondCut - pivot;
|
||||
} else {
|
||||
len2Half = len2 / 2;
|
||||
secondCut = pivot + len2Half;
|
||||
firstCut = upperBound(begin, pivot, *secondCut);
|
||||
}
|
||||
|
||||
reverse(firstCut, pivot);
|
||||
reverse(pivot, secondCut);
|
||||
reverse(firstCut, secondCut);
|
||||
|
||||
const QList<ItemData*>::iterator newPivot = firstCut + len2Half;
|
||||
merge(begin, firstCut, newPivot);
|
||||
merge(newPivot, secondCut, end);
|
||||
}
|
||||
|
||||
QList<KFileItemModel::ItemData*>::iterator KFileItemModel::lowerBound(QList<ItemData*>::iterator begin,
|
||||
QList<ItemData*>::iterator end,
|
||||
const ItemData* value)
|
||||
{
|
||||
// The implementation is based on qLowerBound() from qalgorithms.h
|
||||
// Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
|
||||
|
||||
QList<ItemData*>::iterator middle;
|
||||
int n = int(end - begin);
|
||||
int half;
|
||||
|
||||
while (n > 0) {
|
||||
half = n >> 1;
|
||||
middle = begin + half;
|
||||
if (lessThan(*middle, value)) {
|
||||
begin = middle + 1;
|
||||
n -= half + 1;
|
||||
} else {
|
||||
n = half;
|
||||
}
|
||||
}
|
||||
return begin;
|
||||
}
|
||||
|
||||
QList<KFileItemModel::ItemData*>::iterator KFileItemModel::upperBound(QList<ItemData*>::iterator begin,
|
||||
QList<ItemData*>::iterator end,
|
||||
const ItemData* value)
|
||||
{
|
||||
// The implementation is based on qUpperBound() from qalgorithms.h
|
||||
// Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
|
||||
|
||||
QList<ItemData*>::iterator middle;
|
||||
int n = end - begin;
|
||||
int half;
|
||||
|
||||
while (n > 0) {
|
||||
half = n >> 1;
|
||||
middle = begin + half;
|
||||
if (lessThan(value, *middle)) {
|
||||
n = half;
|
||||
} else {
|
||||
begin = middle + 1;
|
||||
n -= half + 1;
|
||||
}
|
||||
}
|
||||
return begin;
|
||||
}
|
||||
|
||||
void KFileItemModel::reverse(QList<ItemData*>::iterator begin,
|
||||
QList<ItemData*>::iterator end)
|
||||
{
|
||||
// The implementation is based on qReverse() from qalgorithms.h
|
||||
// Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
|
||||
|
||||
--end;
|
||||
while (begin < end) {
|
||||
qSwap(*begin++, *end--);
|
||||
}
|
||||
}
|
||||
|
||||
int KFileItemModel::stringCompare(const QString& a, const QString& b) const
|
||||
{
|
||||
// Taken from KDirSortFilterProxyModel (kdelibs/kfile/kdirsortfilterproxymodel.*)
|
||||
|
|
|
@ -274,30 +274,6 @@ private:
|
|||
*/
|
||||
int sortRoleCompare(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<ItemData*>::iterator begin, QList<ItemData*>::iterator end);
|
||||
|
||||
/** Helper method for sort(). */
|
||||
void merge(QList<ItemData*>::iterator begin,
|
||||
QList<ItemData*>::iterator pivot,
|
||||
QList<ItemData*>::iterator end);
|
||||
|
||||
/** Helper method for sort(). */
|
||||
QList<ItemData*>::iterator lowerBound(QList<ItemData*>::iterator begin,
|
||||
QList<ItemData*>::iterator end,
|
||||
const ItemData* value);
|
||||
|
||||
/** Helper method for sort(). */
|
||||
QList<ItemData*>::iterator upperBound(QList<ItemData*>::iterator begin,
|
||||
QList<ItemData*>::iterator end,
|
||||
const ItemData* value);
|
||||
/** Helper method for sort(). */
|
||||
void reverse(QList<ItemData*>::iterator begin, QList<ItemData*>::iterator end);
|
||||
|
||||
int stringCompare(const QString& a, const QString& b) const;
|
||||
|
||||
/**
|
||||
|
@ -408,6 +384,7 @@ private:
|
|||
// and done step after step in slotCompleted().
|
||||
QSet<KUrl> m_urlsToExpand;
|
||||
|
||||
friend class KFileItemModelSortAlgorithm; // Accesses lessThan() method
|
||||
friend class KFileItemModelTest; // For unit testing
|
||||
};
|
||||
|
||||
|
|
148
src/kitemviews/kfileitemmodelsortalgorithm.cpp
Normal file
148
src/kitemviews/kfileitemmodelsortalgorithm.cpp
Normal file
|
@ -0,0 +1,148 @@
|
|||
/***************************************************************************
|
||||
* Copyright (C) 2012 by Peter Penz <peter.penz19@gmail.com> *
|
||||
* *
|
||||
* This program is free software; you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU General Public License as published by *
|
||||
* the Free Software Foundation; either version 2 of the License, or *
|
||||
* (at your option) any later version. *
|
||||
* *
|
||||
* This program is distributed in the hope that it will be useful, *
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||
* GNU General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU General Public License *
|
||||
* along with this program; if not, write to the *
|
||||
* Free Software Foundation, Inc., *
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA *
|
||||
***************************************************************************/
|
||||
|
||||
#include "kfileitemmodelsortalgorithm_p.h"
|
||||
|
||||
void KFileItemModelSortAlgorithm::sort(KFileItemModel* model,
|
||||
QList<KFileItemModel::ItemData*>::iterator begin,
|
||||
QList<KFileItemModel::ItemData*>::iterator end)
|
||||
{
|
||||
// The implementation is based on qStableSortHelper() from qalgorithms.h
|
||||
// Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
|
||||
|
||||
const int span = end - begin;
|
||||
if (span < 2) {
|
||||
return;
|
||||
}
|
||||
|
||||
const QList<KFileItemModel::ItemData*>::iterator middle = begin + span / 2;
|
||||
sort(model, begin, middle);
|
||||
sort(model, middle, end);
|
||||
merge(model, begin, middle, end);
|
||||
}
|
||||
|
||||
void KFileItemModelSortAlgorithm::merge(KFileItemModel* model,
|
||||
QList<KFileItemModel::ItemData*>::iterator begin,
|
||||
QList<KFileItemModel::ItemData*>::iterator pivot,
|
||||
QList<KFileItemModel::ItemData*>::iterator end)
|
||||
{
|
||||
// The implementation is based on qMerge() from qalgorithms.h
|
||||
// Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
|
||||
|
||||
const int len1 = pivot - begin;
|
||||
const int len2 = end - pivot;
|
||||
|
||||
if (len1 == 0 || len2 == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (len1 + len2 == 2) {
|
||||
if (model->lessThan(*(begin + 1), *(begin))) {
|
||||
qSwap(*begin, *(begin + 1));
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
QList<KFileItemModel::ItemData*>::iterator firstCut;
|
||||
QList<KFileItemModel::ItemData*>::iterator secondCut;
|
||||
int len2Half;
|
||||
if (len1 > len2) {
|
||||
const int len1Half = len1 / 2;
|
||||
firstCut = begin + len1Half;
|
||||
secondCut = lowerBound(model, pivot, end, *firstCut);
|
||||
len2Half = secondCut - pivot;
|
||||
} else {
|
||||
len2Half = len2 / 2;
|
||||
secondCut = pivot + len2Half;
|
||||
firstCut = upperBound(model, begin, pivot, *secondCut);
|
||||
}
|
||||
|
||||
reverse(firstCut, pivot);
|
||||
reverse(pivot, secondCut);
|
||||
reverse(firstCut, secondCut);
|
||||
|
||||
const QList<KFileItemModel::ItemData*>::iterator newPivot = firstCut + len2Half;
|
||||
merge(model, begin, firstCut, newPivot);
|
||||
merge(model, newPivot, secondCut, end);
|
||||
}
|
||||
|
||||
|
||||
QList<KFileItemModel::ItemData*>::iterator
|
||||
KFileItemModelSortAlgorithm::lowerBound(KFileItemModel* model,
|
||||
QList<KFileItemModel::ItemData*>::iterator begin,
|
||||
QList<KFileItemModel::ItemData*>::iterator end,
|
||||
const KFileItemModel::ItemData* value)
|
||||
{
|
||||
// The implementation is based on qLowerBound() from qalgorithms.h
|
||||
// Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
|
||||
|
||||
QList<KFileItemModel::ItemData*>::iterator middle;
|
||||
int n = int(end - begin);
|
||||
int half;
|
||||
|
||||
while (n > 0) {
|
||||
half = n >> 1;
|
||||
middle = begin + half;
|
||||
if (model->lessThan(*middle, value)) {
|
||||
begin = middle + 1;
|
||||
n -= half + 1;
|
||||
} else {
|
||||
n = half;
|
||||
}
|
||||
}
|
||||
return begin;
|
||||
}
|
||||
|
||||
QList<KFileItemModel::ItemData*>::iterator
|
||||
KFileItemModelSortAlgorithm::upperBound(KFileItemModel* model,
|
||||
QList<KFileItemModel::ItemData*>::iterator begin,
|
||||
QList<KFileItemModel::ItemData*>::iterator end,
|
||||
const KFileItemModel::ItemData* value)
|
||||
{
|
||||
// The implementation is based on qUpperBound() from qalgorithms.h
|
||||
// Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
|
||||
|
||||
QList<KFileItemModel::ItemData*>::iterator middle;
|
||||
int n = end - begin;
|
||||
int half;
|
||||
|
||||
while (n > 0) {
|
||||
half = n >> 1;
|
||||
middle = begin + half;
|
||||
if (model->lessThan(value, *middle)) {
|
||||
n = half;
|
||||
} else {
|
||||
begin = middle + 1;
|
||||
n -= half + 1;
|
||||
}
|
||||
}
|
||||
return begin;
|
||||
}
|
||||
|
||||
void KFileItemModelSortAlgorithm::reverse(QList<KFileItemModel::ItemData*>::iterator begin,
|
||||
QList<KFileItemModel::ItemData*>::iterator end)
|
||||
{
|
||||
// The implementation is based on qReverse() from qalgorithms.h
|
||||
// Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
|
||||
|
||||
--end;
|
||||
while (begin < end) {
|
||||
qSwap(*begin++, *end--);
|
||||
}
|
||||
}
|
70
src/kitemviews/kfileitemmodelsortalgorithm_p.h
Normal file
70
src/kitemviews/kfileitemmodelsortalgorithm_p.h
Normal file
|
@ -0,0 +1,70 @@
|
|||
/***************************************************************************
|
||||
* Copyright (C) 2012 by Peter Penz <peter.penz19@gmail.com> *
|
||||
* *
|
||||
* This program is free software; you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU General Public License as published by *
|
||||
* the Free Software Foundation; either version 2 of the License, or *
|
||||
* (at your option) any later version. *
|
||||
* *
|
||||
* This program is distributed in the hope that it will be useful, *
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||
* GNU General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU General Public License *
|
||||
* along with this program; if not, write to the *
|
||||
* Free Software Foundation, Inc., *
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA *
|
||||
***************************************************************************/
|
||||
|
||||
#ifndef KFILEITEMMODELSORTALGORITHM_H
|
||||
#define KFILEITEMMODELSORTALGORITHM_H
|
||||
|
||||
#include <libdolphin_export.h>
|
||||
|
||||
#include <kitemviews/kfileitemmodel.h>
|
||||
|
||||
/**
|
||||
* @brief Sort algorithm for sorting items of KFileItemModel.
|
||||
*
|
||||
* Sorts the items by using KFileItemModel::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.
|
||||
*
|
||||
* The implementation is based on qStableSortHelper() from qalgorithms.h
|
||||
* Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
|
||||
* The sorting implementations of qAlgorithms could not be used as they
|
||||
* don't support having a member-function as comparison criteria.
|
||||
*/
|
||||
class LIBDOLPHINPRIVATE_EXPORT KFileItemModelSortAlgorithm
|
||||
{
|
||||
public:
|
||||
static void sort(KFileItemModel* model,
|
||||
QList<KFileItemModel::ItemData*>::iterator begin,
|
||||
QList<KFileItemModel::ItemData*>::iterator end);
|
||||
|
||||
private:
|
||||
static void merge(KFileItemModel* model,
|
||||
QList<KFileItemModel::ItemData*>::iterator begin,
|
||||
QList<KFileItemModel::ItemData*>::iterator pivot,
|
||||
QList<KFileItemModel::ItemData*>::iterator end);
|
||||
|
||||
static QList<KFileItemModel::ItemData*>::iterator
|
||||
lowerBound(KFileItemModel* model,
|
||||
QList<KFileItemModel::ItemData*>::iterator begin,
|
||||
QList<KFileItemModel::ItemData*>::iterator end,
|
||||
const KFileItemModel::ItemData* value);
|
||||
|
||||
static QList<KFileItemModel::ItemData*>::iterator
|
||||
upperBound(KFileItemModel* model,
|
||||
QList<KFileItemModel::ItemData*>::iterator begin,
|
||||
QList<KFileItemModel::ItemData*>::iterator end,
|
||||
const KFileItemModel::ItemData* value);
|
||||
|
||||
static void reverse(QList<KFileItemModel::ItemData*>::iterator begin,
|
||||
QList<KFileItemModel::ItemData*>::iterator end);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
|
Loading…
Reference in a new issue