void testExpandItems();
void testExpandParentItems();
void testMakeExpandedItemHidden();
+ void testRemoveFilteredExpandedItems();
void testSorting();
void testIndexForKeyboardSearch();
void testNameFilter();
void removeParentOfHiddenItems();
void testGeneralParentChildRelationships();
void testNameRoleGroups();
+ void testNameRoleGroupsWithExpandedItems();
+ void testInconsistentModel();
private:
QStringList itemsInModel() const;
QVERIFY(QTest::kWaitForSignal(m_model, SIGNAL(itemsMoved(KItemRange,QList<int>)), DefaultTimeout));
QCOMPARE(itemsInModel(), QStringList() << "b.txt" << "c.txt" << "d.txt");
+
+ // We rename d.txt back to a.txt using the dir lister's refreshItems() signal.
+ const KFileItem fileItemD = m_model->fileItem(2);
+ KFileItem fileItemA = fileItemD;
+ KUrl urlA = fileItemA.url();
+ urlA.setFileName("a.txt");
+ fileItemA.setUrl(urlA);
+
+ m_model->slotRefreshItems(QList<QPair<KFileItem, KFileItem> >() << qMakePair(fileItemD, fileItemA));
+
+ QVERIFY(QTest::kWaitForSignal(m_model, SIGNAL(itemsMoved(KItemRange,QList<int>)), DefaultTimeout));
+ QCOMPARE(itemsInModel(), QStringList() << "a.txt" << "b.txt" << "c.txt");
}
void KFileItemModelTest::testModelConsistencyWhenInsertingItems()
}
+void KFileItemModelTest::testRemoveFilteredExpandedItems()
+{
+ QSet<QByteArray> originalModelRoles = m_model->roles();
+ QSet<QByteArray> modelRoles = originalModelRoles;
+ modelRoles << "isExpanded" << "isExpandable" << "expandedParentsCount";
+ m_model->setRoles(modelRoles);
+
+ QStringList files;
+ files << "folder/child" << "file"; // missing folders are created automatically
+ m_testDir->createFiles(files);
+
+ m_model->loadDirectory(m_testDir->url());
+ QVERIFY(QTest::kWaitForSignal(m_model, SIGNAL(itemsInserted(KItemRangeList)), DefaultTimeout));
+
+ // So far, the model contains only "folder/" and "file".
+ QCOMPARE(m_model->count(), 2);
+ QVERIFY(m_model->isExpandable(0));
+ QVERIFY(!m_model->isExpandable(1));
+ QVERIFY(!m_model->isExpanded(0));
+ QVERIFY(!m_model->isExpanded(1));
+ QCOMPARE(itemsInModel(), QStringList() << "folder" << "file");
+
+ // Expand "folder" -> "folder/child" becomes visible.
+ m_model->setExpanded(0, true);
+ QVERIFY(m_model->isExpanded(0));
+ QVERIFY(QTest::kWaitForSignal(m_model, SIGNAL(itemsInserted(KItemRangeList)), DefaultTimeout));
+ QCOMPARE(itemsInModel(), QStringList() << "folder" << "child" << "file");
+
+ // Add a name filter.
+ m_model->setNameFilter("f");
+ QCOMPARE(itemsInModel(), QStringList() << "folder" << "file");
+
+ m_model->setNameFilter("fo");
+ QCOMPARE(itemsInModel(), QStringList() << "folder");
+
+ // Remove all expanded items by changing the roles
+ m_model->setRoles(originalModelRoles);
+ QVERIFY(!m_model->isExpanded(0));
+ QCOMPARE(itemsInModel(), QStringList() << "folder");
+
+ // Remove the name filter and verify that "folder/child" does not reappear.
+ m_model->setNameFilter(QString());
+ QCOMPARE(itemsInModel(), QStringList() << "folder" << "file");
+}
+
void KFileItemModelTest::testSorting()
{
// Create some files with different sizes and modification times to check the different sorting options
QCOMPARE(m_model->groups(), expectedGroups);
}
+void KFileItemModelTest::testNameRoleGroupsWithExpandedItems()
+{
+ QSet<QByteArray> modelRoles = m_model->roles();
+ modelRoles << "isExpanded" << "isExpandable" << "expandedParentsCount";
+ m_model->setRoles(modelRoles);
+
+ QStringList files;
+ files << "a/b.txt" << "a/c.txt" << "d/e.txt" << "d/f.txt";
+
+ m_testDir->createFiles(files);
+
+ m_model->setGroupedSorting(true);
+ m_model->loadDirectory(m_testDir->url());
+ QVERIFY(QTest::kWaitForSignal(m_model, SIGNAL(itemsInserted(KItemRangeList)), DefaultTimeout));
+ QCOMPARE(itemsInModel(), QStringList() << "a" << "d");
+
+ QList<QPair<int, QVariant> > expectedGroups;
+ expectedGroups << QPair<int, QVariant>(0, QLatin1String("A"));
+ expectedGroups << QPair<int, QVariant>(1, QLatin1String("D"));
+ QCOMPARE(m_model->groups(), expectedGroups);
+
+ // Verify that expanding "a" and "d" will not change the groups (except for the index of "D").
+ expectedGroups.clear();
+ expectedGroups << QPair<int, QVariant>(0, QLatin1String("A"));
+ expectedGroups << QPair<int, QVariant>(3, QLatin1String("D"));
+
+ m_model->setExpanded(0, true);
+ QVERIFY(m_model->isExpanded(0));
+ QVERIFY(QTest::kWaitForSignal(m_model, SIGNAL(itemsInserted(KItemRangeList)), DefaultTimeout));
+ QCOMPARE(itemsInModel(), QStringList() << "a" << "b.txt" << "c.txt" << "d");
+ QCOMPARE(m_model->groups(), expectedGroups);
+
+ m_model->setExpanded(3, true);
+ QVERIFY(m_model->isExpanded(3));
+ QVERIFY(QTest::kWaitForSignal(m_model, SIGNAL(itemsInserted(KItemRangeList)), DefaultTimeout));
+ QCOMPARE(itemsInModel(), QStringList() << "a" << "b.txt" << "c.txt" << "d" << "e.txt" << "f.txt");
+ QCOMPARE(m_model->groups(), expectedGroups);
+}
+
+void KFileItemModelTest::testInconsistentModel()
+{
+ QSet<QByteArray> modelRoles = m_model->roles();
+ modelRoles << "isExpanded" << "isExpandable" << "expandedParentsCount";
+ m_model->setRoles(modelRoles);
+
+ QStringList files;
+ files << "a/b/c1.txt" << "a/b/c2.txt";
+
+ m_testDir->createFiles(files);
+
+ m_model->loadDirectory(m_testDir->url());
+ QVERIFY(QTest::kWaitForSignal(m_model, SIGNAL(itemsInserted(KItemRangeList)), DefaultTimeout));
+ QCOMPARE(itemsInModel(), QStringList() << "a");
+
+ // Expand "a/" and "a/b/".
+ m_model->setExpanded(0, true);
+ QVERIFY(m_model->isExpanded(0));
+ QVERIFY(QTest::kWaitForSignal(m_model, SIGNAL(itemsInserted(KItemRangeList)), DefaultTimeout));
+ QCOMPARE(itemsInModel(), QStringList() << "a" << "b");
+
+ m_model->setExpanded(1, true);
+ QVERIFY(m_model->isExpanded(1));
+ QVERIFY(QTest::kWaitForSignal(m_model, SIGNAL(itemsInserted(KItemRangeList)), DefaultTimeout));
+ QCOMPARE(itemsInModel(), QStringList() << "a" << "b" << "c1.txt" << "c2.txt");
+
+ // Add the files "c1.txt" and "c2.txt" to the model also as top-level items.
+ // Such a thing can in principle happen when performing a search, and there
+ // are files which
+ // (a) match the search string, and
+ // (b) are children of a folder that matches the search string and is expanded.
+ //
+ // Note that the first item in the list of added items must be new (i.e., not
+ // in the model yet). Otherwise, KFileItemModel::slotItemsAdded() will see that
+ // it receives items that are in the model already and ignore them.
+ KUrl url(m_model->directory().url() + "/a2");
+ KFileItem newItem(KFileItem::Unknown, KFileItem::Unknown, url);
+
+ KFileItemList items;
+ items << newItem << m_model->fileItem(2) << m_model->fileItem(3);
+ m_model->slotItemsAdded(m_model->directory(), items);
+ m_model->slotCompleted();
+ QCOMPARE(itemsInModel(), QStringList() << "a" << "b" << "c1.txt" << "c2.txt" << "a2" << "c1.txt" << "c2.txt");
+
+ m_model->setExpanded(0, false);
+
+ // Test that the right items have been removed, see
+ // https://bugs.kde.org/show_bug.cgi?id=324371
+ QCOMPARE(itemsInModel(), QStringList() << "a" << "a2" << "c1.txt" << "c2.txt");
+
+ // Test that resorting does not cause a crash, see
+ // https://bugs.kde.org/show_bug.cgi?id=325359
+ // The crash is not 100% reproducible, but Valgrind will report an invalid memory access.
+ m_model->resortAllItems();
+
+}
+
QStringList KFileItemModelTest::itemsInModel() const
{
QStringList items;
for (int i = 0; i < m_model->count(); i++) {
- items << m_model->data(i).value("text").toString();
+ items << m_model->fileItem(i).text();
}
return items;
}