Make sure that the sort order is correct after renaming

KFileItemModel::setData() should not only cause a resorting when the
sort role is changed. The name is always used as a fallback if the sort
role of multiple files is equal, therefore, renaming a file can change
the correct order of the files even if the files are not sorted by
"name".

Unit test included.

BUG: 323518
FIXED-IN: 4.11.1
REVIEW: 111721
This commit is contained in:
Frank Reininghaus 2013-08-15 00:07:43 +02:00
parent 59723fca41
commit 7c99a9c2ad
2 changed files with 49 additions and 2 deletions

View file

@ -192,8 +192,30 @@ bool KFileItemModel::setData(int index, const QHash<QByteArray, QVariant>& value
emit itemsChanged(KItemRangeList() << KItemRange(index, 1), changedRoles);
if (changedRoles.contains(sortRole())) {
m_resortAllItemsTimer->start();
// Trigger a resorting if the item's correct position has changed. Note
// that this can happen even if the sort role has not changed at all
// because the file name can be used as a fallback.
if (changedRoles.contains(sortRole()) || changedRoles.contains(roleForType(NameRole))) {
// Compare the changed item with its neighbors to see
// if an expensive resorting is needed at all.
const ItemData* changedItem = m_itemData.at(index);
const ItemData* previousItem = (index == 0) ? 0 : m_itemData.at(index - 1);
const ItemData* nextItem = (index == m_itemData.count() - 1) ? 0 : m_itemData.at(index + 1);
if ((previousItem && lessThan(changedItem, previousItem))
|| (nextItem && lessThan(nextItem, changedItem))) {
m_resortAllItemsTimer->start();
} else if (groupedSorting() && changedRoles.contains(sortRole())) {
// The position is still correct, but the groups might have changed
// if the changed item is either the first or the last item in a
// group.
// In principle, we could try to find out if the item really is the
// first or last one in its group and then update the groups
// (possibly with a delayed timer to make sure that we don't
// re-calculate the groups very often if items are updated one by
// one), but starting m_resortAllItemsTimer is easier.
m_resortAllItemsTimer->start();
}
}
return true;

View file

@ -70,6 +70,7 @@ private slots:
void testSetDataWithModifiedSortRole_data();
void testSetDataWithModifiedSortRole();
void testChangeSortRole();
void testResortAfterChangingName();
void testModelConsistencyWhenInsertingItems();
void testItemRangeConsistencyWhenInsertingItems();
void testExpandItems();
@ -368,6 +369,30 @@ void KFileItemModelTest::testChangeSortRole()
QVERIFY(ok1 || ok2);
}
void KFileItemModelTest::testResortAfterChangingName()
{
// We sort by size in a directory where all files have the same size.
// Therefore, the files are sorted by their names.
m_model->setSortRole("size");
QStringList files;
files << "a.txt" << "b.txt" << "c.txt";
m_testDir->createFiles(files);
m_model->loadDirectory(m_testDir->url());
QVERIFY(QTest::kWaitForSignal(m_model, SIGNAL(itemsInserted(KItemRangeList)), DefaultTimeout));
QCOMPARE(itemsInModel(), QStringList() << "a.txt" << "b.txt" << "c.txt");
// We rename a.txt to d.txt. Even though the size has not changed at all,
// the model must re-sort the items.
QHash<QByteArray, QVariant> data;
data.insert("text", "d.txt");
m_model->setData(0, data);
QVERIFY(QTest::kWaitForSignal(m_model, SIGNAL(itemsMoved(KItemRange,QList<int>)), DefaultTimeout));
QCOMPARE(itemsInModel(), QStringList() << "b.txt" << "c.txt" << "d.txt");
}
void KFileItemModelTest::testModelConsistencyWhenInsertingItems()
{
//QSKIP("Temporary disabled", SkipSingle);