File indexing completed on 2024-10-13 03:37:57
0001 /* 0002 This file is part of the KDE project 0003 SPDX-FileCopyrightText: 2007 Kevin Ottens <ervin@kde.org> 0004 0005 SPDX-License-Identifier: GPL-2.0-only 0006 */ 0007 0008 #include <QDBusInterface> 0009 #include <QDebug> 0010 #include <QObject> 0011 #include <QSignalSpy> 0012 #include <QTemporaryDir> 0013 #include <QTest> 0014 0015 #include <KBookmark> 0016 #include <KBookmarkManager> 0017 #include <KConfig> 0018 #include <KConfigGroup> 0019 #include <KProtocolInfo> 0020 #include <QStandardPaths> 0021 #include <kfileplacesmodel.h> 0022 #include <solid/device.h> 0023 0024 #include <stdlib.h> 0025 0026 Q_DECLARE_METATYPE(KFilePlacesModel::GroupType) 0027 0028 // Avoid QHash randomization so that the order of the devices is stable 0029 static void seedInit() 0030 { 0031 qputenv("QT_HASH_SEED", "0"); 0032 // This env var has no effect because this comes too late. qCpuFeatures() was already called by 0033 // a Q_CONSTRUCTOR_FUNCTION inside QtGui (see image/qimage_conversions.cpp). Argh. QTBUG-47566. 0034 qputenv("QT_NO_CPU_FEATURE", "sse4.2"); 0035 } 0036 Q_CONSTRUCTOR_FUNCTION(seedInit) 0037 0038 class KFilePlacesModelTest : public QObject 0039 { 0040 Q_OBJECT 0041 0042 private Q_SLOTS: 0043 void initTestCase(); 0044 void cleanupTestCase(); 0045 0046 void testInitialList(); 0047 void testAddingInLaterVersion_data(); 0048 void testAddingInLaterVersion(); 0049 void testReparse(); 0050 void testInternalBookmarksHaveIds(); 0051 void testHiding(); 0052 void testMove(); 0053 void testPlacesLifecycle(); 0054 void testDevicePlugging(); 0055 void testDragAndDrop(); 0056 void testDeviceSetupTeardown(); 0057 void testEnableBaloo(); 0058 void testRemoteUrls_data(); 0059 void testRemoteUrls(); 0060 void testRefresh(); 0061 void testConvertedUrl_data(); 0062 void testConvertedUrl(); 0063 void testBookmarkObject(); 0064 void testDataChangedSignal(); 0065 void testIconRole_data(); 0066 void testIconRole(); 0067 void testMoveFunction(); 0068 void testPlaceGroupHidden(); 0069 void testPlaceGroupHiddenVsPlaceChildShown(); 0070 void testPlaceGroupHiddenAndShownWithHiddenChild(); 0071 void testPlaceGroupHiddenGroupIndexesIntegrity(); 0072 void testPlaceGroupHiddenSignal(); 0073 void testPlaceGroupHiddenRole(); 0074 void testSupportedSchemes(); 0075 0076 private: 0077 QStringList placesUrls(KFilePlacesModel *model = nullptr) const; 0078 QDBusInterface *fakeManager(); 0079 QDBusInterface *fakeDevice(const QString &udi); 0080 void createPlacesModels(); 0081 0082 KFilePlacesModel *m_places; 0083 KFilePlacesModel *m_places2; // To check that they always stay in sync 0084 // actually supposed to work across processes, 0085 // but much harder to test 0086 0087 QMap<QString, QDBusInterface *> m_interfacesMap; 0088 QTemporaryDir m_tmpHome; 0089 bool m_hasRecentlyUsedKio; 0090 }; 0091 0092 static QString bookmarksFile() 0093 { 0094 return QStandardPaths::writableLocation(QStandardPaths::GenericDataLocation) + QStringLiteral("/user-places.xbel"); 0095 } 0096 0097 void KFilePlacesModelTest::initTestCase() 0098 { 0099 QVERIFY(m_tmpHome.isValid()); 0100 qputenv("HOME", m_tmpHome.path().toUtf8()); // use a empty home dir 0101 0102 QStandardPaths::setTestModeEnabled(true); 0103 0104 // Ensure we'll have a clean bookmark file to start 0105 QFile::remove(bookmarksFile()); 0106 0107 // disable baloo by default 0108 KConfig config(QStringLiteral("baloofilerc")); 0109 KConfigGroup basicSettings = config.group(QStringLiteral("Basic Settings")); 0110 basicSettings.writeEntry("Indexing-Enabled", false); 0111 config.sync(); 0112 0113 qRegisterMetaType<QModelIndex>(); 0114 qRegisterMetaType<KFilePlacesModel::GroupType>(); 0115 0116 const QString fakeHw = QFINDTESTDATA("fakecomputer.xml"); 0117 QVERIFY(!fakeHw.isEmpty()); 0118 qputenv("SOLID_FAKEHW", QFile::encodeName(fakeHw)); 0119 m_hasRecentlyUsedKio = qEnvironmentVariableIsSet("KDE_FULL_SESSION") && KProtocolInfo::isKnownProtocol(QStringLiteral("recentlyused")); 0120 0121 createPlacesModels(); 0122 } 0123 0124 void KFilePlacesModelTest::createPlacesModels() 0125 { 0126 KBookmarkManager mgr(bookmarksFile()); 0127 QSignalSpy spy(&mgr, &KBookmarkManager::changed); 0128 m_places = new KFilePlacesModel(); 0129 m_places2 = new KFilePlacesModel(); 0130 0131 // When the xbel file is empty, KFilePlacesModel fills it with 3 default items 0132 // 5 when KIO worker recentlyused:/ is installed 0133 QCOMPARE(m_places->rowCount(), m_hasRecentlyUsedKio ? 5 : 3); 0134 0135 QVERIFY(spy.wait()); 0136 0137 // Devices have a delayed loading. Waiting for KDirWatch also waits for that to happen 0138 QCOMPARE(m_places->rowCount(), m_hasRecentlyUsedKio ? 10 : 8); 0139 } 0140 0141 void KFilePlacesModelTest::cleanupTestCase() 0142 { 0143 delete m_places; 0144 delete m_places2; 0145 qDeleteAll(m_interfacesMap); 0146 QFile::remove(bookmarksFile()); 0147 } 0148 0149 QStringList KFilePlacesModelTest::placesUrls(KFilePlacesModel *model) const 0150 { 0151 KFilePlacesModel *currentModel = model; 0152 if (!currentModel) { 0153 currentModel = m_places; 0154 } 0155 QStringList urls; 0156 for (int row = 0; row < currentModel->rowCount(); ++row) { 0157 QModelIndex index = currentModel->index(row, 0); 0158 urls << currentModel->url(index).toDisplayString(QUrl::PreferLocalFile); 0159 } 0160 return urls; 0161 } 0162 0163 /* clang-format off */ 0164 #define CHECK_PLACES_URLS(urls) \ 0165 if (placesUrls() != urls) { \ 0166 qDebug() << "Expected:" << urls; \ 0167 qDebug() << "Got:" << placesUrls(); \ 0168 QCOMPARE(placesUrls(), urls); \ 0169 } \ 0170 for (int row = 0; row < urls.size(); ++row) { \ 0171 QModelIndex index = m_places->index(row, 0); \ 0172 \ 0173 QCOMPARE(m_places->url(index).toString(), QUrl::fromUserInput(urls[row]).toString()); \ 0174 QCOMPARE(m_places->data(index, KFilePlacesModel::UrlRole).toUrl(), QUrl(m_places->url(index))); \ 0175 \ 0176 index = m_places2->index(row, 0); \ 0177 \ 0178 QCOMPARE(m_places2->url(index).toString(), QUrl::fromUserInput(urls[row]).toString()); \ 0179 QCOMPARE(m_places2->data(index, KFilePlacesModel::UrlRole).toUrl(), QUrl(m_places2->url(index))); \ 0180 } \ 0181 \ 0182 QCOMPARE(urls.size(), m_places->rowCount()); \ 0183 QCOMPARE(urls.size(), m_places2->rowCount()); 0184 /*clang-format on */ 0185 0186 QDBusInterface *KFilePlacesModelTest::fakeManager() 0187 { 0188 return fakeDevice(QStringLiteral("/org/kde/solid/fakehw")); 0189 } 0190 0191 QDBusInterface *KFilePlacesModelTest::fakeDevice(const QString &udi) 0192 { 0193 QDBusInterface *interface = m_interfacesMap[udi]; 0194 if (interface) { 0195 return interface; 0196 } 0197 0198 QDBusInterface *iface = new QDBusInterface(QDBusConnection::sessionBus().baseService(), udi); 0199 m_interfacesMap[udi] = iface; 0200 0201 return iface; 0202 } 0203 0204 static const QStringList initialListOfPlaces() 0205 { 0206 return QStringList{QDir::homePath(), QStringLiteral("trash:/")}; 0207 } 0208 0209 static const QStringList initialListOfShared() 0210 { 0211 return QStringList{QStringLiteral("remote:/"), QStringLiteral("/media/nfs")}; 0212 } 0213 0214 static const QStringList initialListOfRecent() 0215 { 0216 auto list = QStringList(); 0217 if (qEnvironmentVariableIsSet("KDE_FULL_SESSION") && KProtocolInfo::isKnownProtocol(QStringLiteral("recentlyused"))) { 0218 list << QStringLiteral("recentlyused:/files"); 0219 list << QStringLiteral("recentlyused:/locations"); 0220 } 0221 return list; 0222 } 0223 0224 static const QStringList initialListOfDevices() 0225 { 0226 return QStringList{QStringLiteral("/foreign")}; 0227 } 0228 0229 static const QStringList initialListOfRemovableDevices() 0230 { 0231 return QStringList{QStringLiteral("/media/floppy0"), QStringLiteral("/media/XO-Y4"), QStringLiteral("/media/cdrom")}; 0232 } 0233 0234 static const QStringList initialListOfUrls() 0235 { 0236 return QStringList() << initialListOfPlaces() << initialListOfShared() << initialListOfRecent() << initialListOfDevices() 0237 << initialListOfRemovableDevices(); 0238 } 0239 0240 void KFilePlacesModelTest::testInitialList() 0241 { 0242 const QStringList urls = initialListOfUrls(); 0243 CHECK_PLACES_URLS(urls); 0244 } 0245 0246 void KFilePlacesModelTest::testAddingInLaterVersion_data() 0247 { 0248 QTest::addColumn<QByteArray>("contents"); 0249 QTest::addColumn<QStringList>("expectedUrls"); 0250 0251 // Create a places file with only Home in it, and no version number 0252 static const char contentsPart1[] = 0253 "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" 0254 "<xbel xmlns:bookmark=\"http://www.freedesktop.org/standards/desktop-bookmarks\">\n"; 0255 0256 static const char versionXml[] = 0257 " <info>\n" 0258 " <metadata owner=\"http://www.kde.org\">\n" 0259 " <kde_places_version>2</kde_places_version>\n" 0260 " </metadata>\n" 0261 " </info>\n"; 0262 0263 static const char contentsPart2[] = 0264 " <bookmark href=\"trash:/\">\n" 0265 " <title>Home</title>\n" 0266 " <info>\n" 0267 " <metadata owner=\"http://freedesktop.org\">\n" 0268 " <bookmark:icon name=\"user-home\"/>\n" 0269 " </metadata>\n" 0270 " <metadata owner=\"http://www.kde.org\">\n" 0271 " <ID>1481703882/0</ID>\n" 0272 " <isSystemItem>true</isSystemItem>\n" 0273 " </metadata>\n" 0274 " </info>\n" 0275 " </bookmark>\n" 0276 "</xbel>"; 0277 0278 // No version key: KFilePlacesModel will add the missing entries: home and remote 0279 // Just not in the usual order 0280 QStringList expectedWithReorder = initialListOfUrls(); 0281 expectedWithReorder.move(1, 0); 0282 QTest::newRow("just_home_no_version") << (QByteArray(contentsPart1) + contentsPart2) << expectedWithReorder; 0283 0284 // Existing version key: home and remote were removed by the user, leave them out 0285 QStringList expectedUrls{QStringLiteral("trash:/")}; 0286 expectedUrls << initialListOfShared() << initialListOfRecent() << initialListOfDevices() << initialListOfRemovableDevices(); 0287 QVERIFY(expectedUrls.removeOne(QStringLiteral("remote:/"))); 0288 QTest::newRow("just_home_version_2") << (QByteArray(contentsPart1) + versionXml + contentsPart2) << expectedUrls; 0289 } 0290 0291 void KFilePlacesModelTest::testAddingInLaterVersion() 0292 { 0293 QFETCH(QByteArray, contents); 0294 QFETCH(QStringList, expectedUrls); 0295 0296 // Avoid interference 0297 delete m_places; 0298 delete m_places2; 0299 QCoreApplication::processEvents(); 0300 0301 KBookmarkManager mgr(bookmarksFile()); 0302 0303 auto cleanupFunc = [this, &mgr]() { 0304 QFile::remove(bookmarksFile()); 0305 // let KDirWatch process the deletion 0306 QTRY_VERIFY(mgr.root().first().isNull()); 0307 createPlacesModels(); 0308 testInitialList(); 0309 }; 0310 struct Cleanup { 0311 explicit Cleanup(const std::function<void()> &f) 0312 : func(f) 0313 { 0314 } 0315 ~Cleanup() 0316 { 0317 func(); 0318 } 0319 std::function<void()> func; 0320 } cleanup(cleanupFunc); 0321 0322 QTest::qWait(1000); // for KDirWatch 0323 QSignalSpy spy(&mgr, &KBookmarkManager::changed); 0324 0325 // WHEN 0326 QFile file(bookmarksFile()); 0327 QVERIFY(file.open(QIODevice::WriteOnly)); 0328 file.write(contents); 0329 file.close(); 0330 QVERIFY(spy.wait()); 0331 0332 // THEN 0333 KFilePlacesModel model; 0334 QCoreApplication::processEvents(); // Devices have a delayed loading 0335 0336 if (placesUrls(&model) != expectedUrls) { 0337 qDebug() << "Expected:" << expectedUrls; 0338 qDebug() << "Got:" << placesUrls(&model); 0339 QCOMPARE(placesUrls(&model), expectedUrls); 0340 } 0341 } 0342 0343 void KFilePlacesModelTest::testReparse() 0344 { 0345 // add item 0346 m_places->addPlace(QStringLiteral("foo"), QUrl::fromLocalFile(QStringLiteral("/foo")), QString(), QString()); 0347 0348 QStringList urls = initialListOfUrls(); 0349 // it will be added at the end of places section 0350 urls.insert(2, QStringLiteral("/foo")); 0351 CHECK_PLACES_URLS(urls); 0352 0353 // reparse the bookmark file 0354 KBookmarkManager bookmarkManager(bookmarksFile()); 0355 0356 // check if they are the same 0357 CHECK_PLACES_URLS(urls); 0358 0359 // try to remove item 0360 m_places->removePlace(m_places->index(2, 0)); 0361 0362 urls = initialListOfUrls(); 0363 CHECK_PLACES_URLS(urls); 0364 } 0365 0366 void KFilePlacesModelTest::testInternalBookmarksHaveIds() 0367 { 0368 KBookmarkManager bookmarkManager(bookmarksFile()); 0369 KBookmarkGroup root = bookmarkManager.root(); 0370 0371 // Verify every entry has an id or an udi 0372 KBookmark bookmark = root.first(); 0373 while (!bookmark.isNull()) { 0374 QVERIFY(!bookmark.metaDataItem(QStringLiteral("ID")).isEmpty() || !bookmark.metaDataItem(QStringLiteral("UDI")).isEmpty()); 0375 // It's mutually exclusive though 0376 QVERIFY(bookmark.metaDataItem(QStringLiteral("ID")).isEmpty() || bookmark.metaDataItem(QStringLiteral("UDI")).isEmpty()); 0377 0378 bookmark = root.next(bookmark); 0379 } 0380 0381 // Verify that adding a bookmark behind its back the model gives it an id 0382 // (in real life it requires the user to modify the file by hand, 0383 // unlikely but better safe than sorry). 0384 // It induces a small race condition which means several ids will be 0385 // successively set on the same bookmark but no big deal since it won't 0386 // break the system 0387 KBookmark foo = root.addBookmark(QStringLiteral("Foo"), QUrl(QStringLiteral("file:/foo")), QStringLiteral("red-folder")); 0388 QCOMPARE(foo.text(), QStringLiteral("Foo")); 0389 QVERIFY(foo.metaDataItem(QStringLiteral("ID")).isEmpty()); 0390 bookmarkManager.emitChanged(root); 0391 QCOMPARE(foo.text(), QStringLiteral("Foo")); 0392 QVERIFY(!foo.metaDataItem(QStringLiteral("ID")).isEmpty()); 0393 0394 // Verify that all the ids are different 0395 bookmark = root.first(); 0396 QSet<QString> ids; 0397 while (!bookmark.isNull()) { 0398 QString id; 0399 if (!bookmark.metaDataItem(QStringLiteral("UDI")).isEmpty()) { 0400 id = bookmark.metaDataItem(QStringLiteral("UDI")); 0401 } else { 0402 id = bookmark.metaDataItem(QStringLiteral("ID")); 0403 } 0404 0405 if (ids.contains(id)) { 0406 // Some debugging help 0407 qDebug() << "Bookmarks file:" << bookmarksFile() << "contains one (or more) duplicated bookmarks:"; 0408 QFile debugFile(bookmarksFile()); 0409 QVERIFY(debugFile.open(QIODevice::ReadOnly)); 0410 qDebug() << QString::fromUtf8(debugFile.readAll()); 0411 QVERIFY2(!ids.contains(id), qPrintable("Duplicated ID found: " + id)); 0412 } 0413 ids << id; 0414 bookmark = root.next(bookmark); 0415 } 0416 0417 // Cleanup foo 0418 root.deleteBookmark(foo); 0419 bookmarkManager.emitChanged(root); 0420 } 0421 0422 void KFilePlacesModelTest::testHiding() 0423 { 0424 // Verify that nothing is hidden 0425 for (int row = 0; row < m_places->rowCount(); ++row) { 0426 QModelIndex index = m_places->index(row, 0); 0427 QVERIFY(!m_places->isHidden(index)); 0428 } 0429 0430 QModelIndex a = m_places->index(2, 0); 0431 QModelIndex b = m_places->index(6, 0); 0432 0433 QList<QVariant> args; 0434 QSignalSpy spy(m_places, &QAbstractItemModel::dataChanged); 0435 0436 // Verify that hidden is taken into account and is not global 0437 m_places->setPlaceHidden(a, true); 0438 QVERIFY(m_places->isHidden(a)); 0439 QVERIFY(m_places->data(a, KFilePlacesModel::HiddenRole).toBool()); 0440 QVERIFY(!m_places->isHidden(b)); 0441 QVERIFY(!m_places->data(b, KFilePlacesModel::HiddenRole).toBool()); 0442 QCOMPARE(spy.count(), 1); 0443 args = spy.takeFirst(); 0444 QCOMPARE(args.at(0).toModelIndex(), a); 0445 QCOMPARE(args.at(1).toModelIndex(), a); 0446 0447 m_places->setPlaceHidden(b, true); 0448 QVERIFY(m_places->isHidden(a)); 0449 QVERIFY(m_places->data(a, KFilePlacesModel::HiddenRole).toBool()); 0450 QVERIFY(m_places->isHidden(b)); 0451 QVERIFY(m_places->data(b, KFilePlacesModel::HiddenRole).toBool()); 0452 QCOMPARE(spy.count(), 1); 0453 args = spy.takeFirst(); 0454 QCOMPARE(args.at(0).toModelIndex(), b); 0455 QCOMPARE(args.at(1).toModelIndex(), b); 0456 0457 m_places->setPlaceHidden(a, false); 0458 m_places->setPlaceHidden(b, false); 0459 QVERIFY(!m_places->isHidden(a)); 0460 QVERIFY(!m_places->data(a, KFilePlacesModel::HiddenRole).toBool()); 0461 QVERIFY(!m_places->isHidden(b)); 0462 QVERIFY(!m_places->data(b, KFilePlacesModel::HiddenRole).toBool()); 0463 QCOMPARE(spy.count(), 2); 0464 args = spy.takeFirst(); 0465 QCOMPARE(args.at(0).toModelIndex(), a); 0466 QCOMPARE(args.at(1).toModelIndex(), a); 0467 args = spy.takeFirst(); 0468 QCOMPARE(args.at(0).toModelIndex(), b); 0469 QCOMPARE(args.at(1).toModelIndex(), b); 0470 } 0471 0472 void KFilePlacesModelTest::testMove() 0473 { 0474 QList<QVariant> args; 0475 QSignalSpy spy_inserted(m_places, &QAbstractItemModel::rowsInserted); 0476 QSignalSpy spy_removed(m_places, &QAbstractItemModel::rowsRemoved); 0477 0478 KBookmarkManager bookmarkManager(bookmarksFile()); 0479 KBookmarkGroup root = bookmarkManager.root(); 0480 0481 KBookmark system_home = m_places->bookmarkForIndex(m_places->index(0, 0)); 0482 0483 // Trying move the root at the end of the list, should move it to the end of places section instead 0484 // to keep it grouped 0485 KBookmark last = root.first(); 0486 while (!root.next(last).isNull()) { 0487 last = root.next(last); 0488 } 0489 root.moveBookmark(system_home, last); 0490 bookmarkManager.emitChanged(root); 0491 0492 QStringList urls; 0493 urls << QStringLiteral("trash:/") << QDir::homePath() << initialListOfShared() << initialListOfRecent() << initialListOfDevices() 0494 << initialListOfRemovableDevices(); 0495 0496 CHECK_PLACES_URLS(urls); 0497 QCOMPARE(spy_inserted.count(), 1); 0498 args = spy_inserted.takeFirst(); 0499 QCOMPARE(args.at(0).toModelIndex(), QModelIndex()); 0500 QCOMPARE(args.at(1).toInt(), 1); 0501 QCOMPARE(args.at(2).toInt(), 1); 0502 QCOMPARE(spy_removed.count(), 1); 0503 args = spy_removed.takeFirst(); 0504 QCOMPARE(args.at(0).toModelIndex(), QModelIndex()); 0505 QCOMPARE(args.at(1).toInt(), 0); 0506 QCOMPARE(args.at(2).toInt(), 0); 0507 0508 // Move home at the beginning of the list (at its original place) 0509 root.moveBookmark(system_home, KBookmark()); 0510 bookmarkManager.emitChanged(root); 0511 urls.clear(); 0512 urls << initialListOfPlaces() << initialListOfShared() << initialListOfRecent() << initialListOfDevices() << initialListOfRemovableDevices(); 0513 CHECK_PLACES_URLS(urls); 0514 QCOMPARE(spy_inserted.count(), 1); 0515 args = spy_inserted.takeFirst(); 0516 QCOMPARE(args.at(0).toModelIndex(), QModelIndex()); 0517 QCOMPARE(args.at(1).toInt(), 1); 0518 QCOMPARE(args.at(2).toInt(), 1); 0519 QCOMPARE(spy_removed.count(), 1); 0520 args = spy_removed.takeFirst(); 0521 QCOMPARE(args.at(0).toModelIndex(), QModelIndex()); 0522 QCOMPARE(args.at(1).toInt(), 0); 0523 QCOMPARE(args.at(2).toInt(), 0); 0524 } 0525 0526 void KFilePlacesModelTest::testDragAndDrop() 0527 { 0528 QList<QVariant> args; 0529 QSignalSpy spy_moved(m_places, &QAbstractItemModel::rowsMoved); 0530 0531 // Monitor rowsInserted() and rowsRemoved() to ensure they are never emitted: 0532 // Moving with drag and drop is expected to emit rowsMoved() 0533 QSignalSpy spy_inserted(m_places, &QAbstractItemModel::rowsInserted); 0534 QSignalSpy spy_removed(m_places, &QAbstractItemModel::rowsRemoved); 0535 0536 // Move /home at the end of the places list 0537 QModelIndexList indexes; 0538 indexes << m_places->index(0, 0); 0539 QMimeData *mimeData = m_places->mimeData(indexes); 0540 QVERIFY(m_places->dropMimeData(mimeData, Qt::MoveAction, 2, 0, QModelIndex())); 0541 0542 QStringList urls; 0543 urls << QStringLiteral("trash:/") << QDir::homePath() << initialListOfShared() << initialListOfRecent() << initialListOfDevices() 0544 << initialListOfRemovableDevices(); 0545 CHECK_PLACES_URLS(urls); 0546 QCOMPARE(spy_inserted.count(), 0); 0547 QCOMPARE(spy_removed.count(), 0); 0548 QCOMPARE(spy_moved.count(), 1); 0549 args = spy_moved.takeFirst(); 0550 QCOMPARE(args.at(0).toModelIndex(), QModelIndex()); 0551 QCOMPARE(args.at(1).toInt(), 0); 0552 QCOMPARE(args.at(2).toInt(), 0); 0553 QCOMPARE(args.at(3).toModelIndex(), QModelIndex()); 0554 QCOMPARE(args.at(4).toInt(), 2); 0555 0556 // Move home back at the beginning of the list 0557 indexes.clear(); 0558 indexes << m_places->index(1, 0); 0559 mimeData = m_places->mimeData(indexes); 0560 QVERIFY(m_places->dropMimeData(mimeData, Qt::MoveAction, 0, 0, QModelIndex())); 0561 0562 urls.clear(); 0563 urls << QDir::homePath() << QStringLiteral("trash:/") << initialListOfShared() << initialListOfRecent() << initialListOfDevices() 0564 << initialListOfRemovableDevices(); 0565 CHECK_PLACES_URLS(urls); 0566 QCOMPARE(spy_inserted.count(), 0); 0567 QCOMPARE(spy_removed.count(), 0); 0568 QCOMPARE(spy_moved.count(), 1); 0569 args = spy_moved.takeFirst(); 0570 QCOMPARE(args.at(0).toModelIndex(), QModelIndex()); 0571 QCOMPARE(args.at(1).toInt(), 1); 0572 QCOMPARE(args.at(2).toInt(), 1); 0573 QCOMPARE(args.at(3).toModelIndex(), QModelIndex()); 0574 QCOMPARE(args.at(4).toInt(), 0); 0575 0576 // Dropping on an item is not allowed 0577 indexes.clear(); 0578 indexes << m_places->index(4, 0); 0579 mimeData = m_places->mimeData(indexes); 0580 QVERIFY(!m_places->dropMimeData(mimeData, Qt::MoveAction, -1, 0, m_places->index(2, 0))); 0581 CHECK_PLACES_URLS(urls); 0582 QCOMPARE(spy_inserted.count(), 0); 0583 QCOMPARE(spy_removed.count(), 0); 0584 QCOMPARE(spy_moved.count(), 0); 0585 } 0586 0587 void KFilePlacesModelTest::testPlacesLifecycle() 0588 { 0589 QList<QVariant> args; 0590 QSignalSpy spy_inserted(m_places, &QAbstractItemModel::rowsInserted); 0591 QSignalSpy spy_removed(m_places, &QAbstractItemModel::rowsRemoved); 0592 QSignalSpy spy_changed(m_places, &QAbstractItemModel::dataChanged); 0593 0594 m_places->addPlace(QStringLiteral("Foo"), QUrl::fromLocalFile(QStringLiteral("/home/foo"))); 0595 0596 QStringList urls; 0597 urls << initialListOfPlaces() << QStringLiteral("/home/foo") << initialListOfShared() << initialListOfRecent() << initialListOfDevices() 0598 << initialListOfRemovableDevices(); 0599 CHECK_PLACES_URLS(urls); 0600 QCOMPARE(spy_inserted.count(), 1); 0601 args = spy_inserted.takeFirst(); 0602 QCOMPARE(args.at(0).toModelIndex(), QModelIndex()); 0603 QCOMPARE(args.at(1).toInt(), 2); 0604 QCOMPARE(args.at(2).toInt(), 2); 0605 QCOMPARE(spy_removed.count(), 0); 0606 0607 KBookmarkManager bookmarkManager(bookmarksFile()); 0608 KBookmarkGroup root = bookmarkManager.root(); 0609 KBookmark before_trash = m_places->bookmarkForIndex(m_places->index(0, 0)); 0610 KBookmark foo = m_places->bookmarkForIndex(m_places->index(2, 0)); 0611 0612 root.moveBookmark(foo, before_trash); 0613 bookmarkManager.emitChanged(root); 0614 0615 urls.clear(); 0616 urls << QDir::homePath() << QStringLiteral("/home/foo") << QStringLiteral("trash:/") << initialListOfShared() << initialListOfRecent() 0617 << initialListOfDevices() << initialListOfRemovableDevices(); 0618 CHECK_PLACES_URLS(urls); 0619 QCOMPARE(spy_inserted.count(), 1); 0620 args = spy_inserted.takeFirst(); 0621 QCOMPARE(args.at(0).toModelIndex(), QModelIndex()); 0622 QCOMPARE(args.at(1).toInt(), 2); 0623 QCOMPARE(args.at(2).toInt(), 2); 0624 QCOMPARE(spy_removed.count(), 1); 0625 args = spy_removed.takeFirst(); 0626 QCOMPARE(args.at(0).toModelIndex(), QModelIndex()); 0627 QCOMPARE(args.at(1).toInt(), 1); 0628 QCOMPARE(args.at(2).toInt(), 1); 0629 0630 m_places->editPlace(m_places->index(1, 0), QStringLiteral("Foo"), QUrl::fromLocalFile(QStringLiteral("/mnt/foo"))); 0631 0632 urls.clear(); 0633 urls << QDir::homePath() << QStringLiteral("/mnt/foo") << QStringLiteral("trash:/") << initialListOfShared() << initialListOfRecent() 0634 << initialListOfDevices() << initialListOfRemovableDevices(); 0635 CHECK_PLACES_URLS(urls); 0636 QCOMPARE(spy_inserted.count(), 0); 0637 QCOMPARE(spy_removed.count(), 0); 0638 QCOMPARE(spy_changed.count(), 1); 0639 args = spy_changed.takeFirst(); 0640 QCOMPARE(args.at(0).toModelIndex(), m_places->index(1, 0)); 0641 QCOMPARE(args.at(1).toModelIndex(), m_places->index(1, 0)); 0642 0643 foo = m_places->bookmarkForIndex(m_places->index(1, 0)); 0644 foo.setFullText(QStringLiteral("Bar")); 0645 0646 urls.clear(); 0647 urls << QDir::homePath() << QStringLiteral("/mnt/foo") << QStringLiteral("trash:/") << initialListOfShared() << initialListOfRecent() 0648 << initialListOfDevices() << initialListOfRemovableDevices(); 0649 0650 CHECK_PLACES_URLS(urls); 0651 QCOMPARE(spy_inserted.count(), 0); 0652 QCOMPARE(spy_removed.count(), 0); 0653 QCOMPARE(spy_changed.count(), m_hasRecentlyUsedKio ? 11 : 9); 0654 args = spy_changed[2]; 0655 QCOMPARE(args.at(0).toModelIndex(), m_places->index(2, 0)); 0656 QCOMPARE(args.at(1).toModelIndex(), m_places->index(2, 0)); 0657 spy_changed.clear(); 0658 0659 m_places->removePlace(m_places->index(1, 0)); 0660 0661 urls.clear(); 0662 urls << initialListOfPlaces() << initialListOfShared() << initialListOfRecent() << initialListOfDevices() << initialListOfRemovableDevices(); 0663 CHECK_PLACES_URLS(urls); 0664 QCOMPARE(spy_inserted.count(), 0); 0665 QCOMPARE(spy_removed.count(), 1); 0666 args = spy_removed.takeFirst(); 0667 QCOMPARE(args.at(0).toModelIndex(), QModelIndex()); 0668 QCOMPARE(args.at(1).toInt(), 1); 0669 QCOMPARE(args.at(2).toInt(), 1); 0670 0671 m_places->addPlace(QStringLiteral("Foo"), QUrl::fromLocalFile(QStringLiteral("/home/foo")), QString(), QString(), m_places->index(0, 0)); 0672 0673 urls.clear(); 0674 urls << QDir::homePath() << QStringLiteral("/home/foo") << QStringLiteral("trash:/") << initialListOfShared() << initialListOfRecent() 0675 << initialListOfDevices() << initialListOfRemovableDevices(); 0676 CHECK_PLACES_URLS(urls); 0677 QCOMPARE(spy_inserted.count(), 1); 0678 args = spy_inserted.takeFirst(); 0679 QCOMPARE(args.at(0).toModelIndex(), QModelIndex()); 0680 QCOMPARE(args.at(1).toInt(), 1); 0681 QCOMPARE(args.at(2).toInt(), 1); 0682 QCOMPARE(spy_removed.count(), 0); 0683 0684 m_places->removePlace(m_places->index(1, 0)); 0685 } 0686 0687 void KFilePlacesModelTest::testDevicePlugging() 0688 { 0689 QList<QVariant> args; 0690 QSignalSpy spy_inserted(m_places, &QAbstractItemModel::rowsInserted); 0691 QSignalSpy spy_removed(m_places, &QAbstractItemModel::rowsRemoved); 0692 0693 fakeManager()->call(QStringLiteral("unplug"), "/org/kde/solid/fakehw/volume_part1_size_993284096"); 0694 0695 QStringList urls; 0696 urls << initialListOfPlaces() << initialListOfShared() << initialListOfRecent() << initialListOfDevices() << QStringLiteral("/media/floppy0") 0697 << QStringLiteral("/media/cdrom"); 0698 CHECK_PLACES_URLS(urls); 0699 QCOMPARE(spy_inserted.count(), 0); 0700 QCOMPARE(spy_removed.count(), 1); 0701 args = spy_removed.takeFirst(); 0702 QCOMPARE(args.at(0).toModelIndex(), QModelIndex()); 0703 QCOMPARE(args.at(1).toInt(), m_hasRecentlyUsedKio ? 8 : 6); 0704 QCOMPARE(args.at(2).toInt(), m_hasRecentlyUsedKio ? 8 : 6); 0705 0706 fakeManager()->call(QStringLiteral("plug"), "/org/kde/solid/fakehw/volume_part1_size_993284096"); 0707 0708 urls.clear(); 0709 urls << initialListOfPlaces() << initialListOfShared() << initialListOfRecent() << initialListOfDevices() << initialListOfRemovableDevices(); 0710 CHECK_PLACES_URLS(urls); 0711 QCOMPARE(spy_inserted.count(), 1); 0712 args = spy_inserted.takeFirst(); 0713 QCOMPARE(args.at(0).toModelIndex(), QModelIndex()); 0714 QCOMPARE(args.at(1).toInt(), m_hasRecentlyUsedKio ? 8 : 6); 0715 QCOMPARE(args.at(2).toInt(), m_hasRecentlyUsedKio ? 8 : 6); 0716 QCOMPARE(spy_removed.count(), 0); 0717 0718 // Move the device in the list, and check that it memorizes the position across plug/unplug 0719 0720 KBookmarkManager bookmarkManager(bookmarksFile()); 0721 KBookmarkGroup root = bookmarkManager.root(); 0722 KBookmark before_floppy; 0723 0724 KBookmark device = root.first(); // The device we'll move is the 6th bookmark 0725 const int count = m_hasRecentlyUsedKio ? 7 : 5; 0726 for (int i = 0; i < count; i++) { 0727 if (i == 2) { 0728 // store item before to be able to move it back to original position 0729 device = before_floppy = root.next(device); 0730 } else { 0731 device = root.next(device); 0732 } 0733 } 0734 0735 root.moveBookmark(device, before_floppy); 0736 bookmarkManager.emitChanged(root); 0737 0738 urls.clear(); 0739 urls << initialListOfPlaces() << initialListOfShared() << initialListOfRecent() << initialListOfDevices() << QStringLiteral("/media/XO-Y4") 0740 << QStringLiteral("/media/floppy0") << QStringLiteral("/media/cdrom"); 0741 CHECK_PLACES_URLS(urls); 0742 QCOMPARE(spy_inserted.count(), 1); 0743 args = spy_inserted.takeFirst(); 0744 QCOMPARE(args.at(0).toModelIndex(), QModelIndex()); 0745 QCOMPARE(args.at(1).toInt(), m_hasRecentlyUsedKio ? 8 : 6); 0746 QCOMPARE(args.at(2).toInt(), m_hasRecentlyUsedKio ? 8 : 6); 0747 QCOMPARE(spy_removed.count(), 1); 0748 args = spy_removed.takeFirst(); 0749 QCOMPARE(args.at(0).toModelIndex(), QModelIndex()); 0750 QCOMPARE(args.at(1).toInt(), m_hasRecentlyUsedKio ? 7 : 5); 0751 QCOMPARE(args.at(2).toInt(), m_hasRecentlyUsedKio ? 7 : 5); 0752 0753 fakeManager()->call(QStringLiteral("unplug"), "/org/kde/solid/fakehw/volume_part1_size_993284096"); 0754 0755 urls.clear(); 0756 urls << initialListOfPlaces() << initialListOfShared() << initialListOfRecent() << initialListOfDevices() << QStringLiteral("/media/floppy0") 0757 << QStringLiteral("/media/cdrom"); 0758 CHECK_PLACES_URLS(urls); 0759 QCOMPARE(spy_inserted.count(), 0); 0760 QCOMPARE(spy_removed.count(), 1); 0761 args = spy_removed.takeFirst(); 0762 QCOMPARE(args.at(0).toModelIndex(), QModelIndex()); 0763 QCOMPARE(args.at(1).toInt(), m_hasRecentlyUsedKio ? 7 : 5); 0764 QCOMPARE(args.at(2).toInt(), m_hasRecentlyUsedKio ? 7 : 5); 0765 0766 fakeManager()->call(QStringLiteral("plug"), "/org/kde/solid/fakehw/volume_part1_size_993284096"); 0767 0768 urls.clear(); 0769 urls << initialListOfPlaces() << initialListOfShared() << initialListOfRecent() << initialListOfDevices() << QStringLiteral("/media/XO-Y4") 0770 << QStringLiteral("/media/floppy0") << QStringLiteral("/media/cdrom"); 0771 CHECK_PLACES_URLS(urls); 0772 QCOMPARE(spy_inserted.count(), 1); 0773 args = spy_inserted.takeFirst(); 0774 QCOMPARE(args.at(0).toModelIndex(), QModelIndex()); 0775 QCOMPARE(args.at(1).toInt(), m_hasRecentlyUsedKio ? 7 : 5); 0776 QCOMPARE(args.at(2).toInt(), m_hasRecentlyUsedKio ? 7 : 5); 0777 QCOMPARE(spy_removed.count(), 0); 0778 0779 KBookmark seventh = root.first(); 0780 for (int i = 0; i < count; i++) { 0781 seventh = root.next(seventh); 0782 } 0783 root.moveBookmark(device, seventh); 0784 bookmarkManager.emitChanged(root); 0785 0786 urls.clear(); 0787 urls << initialListOfPlaces() << initialListOfShared() << initialListOfRecent() << initialListOfDevices() << initialListOfRemovableDevices(); 0788 CHECK_PLACES_URLS(urls); 0789 QCOMPARE(spy_inserted.count(), 1); 0790 args = spy_inserted.takeFirst(); 0791 QCOMPARE(args.at(0).toModelIndex(), QModelIndex()); 0792 QCOMPARE(args.at(1).toInt(), m_hasRecentlyUsedKio ? 8 : 6); 0793 QCOMPARE(args.at(2).toInt(), m_hasRecentlyUsedKio ? 8 : 6); 0794 QCOMPARE(spy_removed.count(), 1); 0795 args = spy_removed.takeFirst(); 0796 QCOMPARE(args.at(0).toModelIndex(), QModelIndex()); 0797 QCOMPARE(args.at(1).toInt(), m_hasRecentlyUsedKio ? 7 : 5); 0798 QCOMPARE(args.at(2).toInt(), m_hasRecentlyUsedKio ? 7 : 5); 0799 } 0800 0801 void KFilePlacesModelTest::testDeviceSetupTeardown() 0802 { 0803 QList<QVariant> args; 0804 QSignalSpy spy_changed(m_places, &QAbstractItemModel::dataChanged); 0805 0806 fakeDevice(QStringLiteral("/org/kde/solid/fakehw/volume_part1_size_993284096/StorageAccess"))->call(QStringLiteral("teardown")); 0807 0808 QCOMPARE(spy_changed.count(), 1); 0809 args = spy_changed.takeFirst(); 0810 QCOMPARE(args.at(0).toModelIndex().row(), m_hasRecentlyUsedKio ? 8 : 6); 0811 QCOMPARE(args.at(1).toModelIndex().row(), m_hasRecentlyUsedKio ? 8 : 6); 0812 0813 fakeDevice(QStringLiteral("/org/kde/solid/fakehw/volume_part1_size_993284096/StorageAccess"))->call(QStringLiteral("setup")); 0814 0815 QCOMPARE(spy_changed.count(), 1); 0816 args = spy_changed.takeFirst(); 0817 QCOMPARE(args.at(0).toModelIndex().row(), m_hasRecentlyUsedKio ? 8 : 6); 0818 QCOMPARE(args.at(1).toModelIndex().row(), m_hasRecentlyUsedKio ? 8 : 6); 0819 } 0820 0821 void KFilePlacesModelTest::testEnableBaloo() 0822 { 0823 KConfig config(QStringLiteral("baloofilerc")); 0824 KConfigGroup basicSettings = config.group(QStringLiteral("Basic Settings")); 0825 basicSettings.writeEntry("Indexing-Enabled", true); 0826 config.sync(); 0827 0828 KFilePlacesModel places_with_baloo; 0829 QStringList urls; 0830 for (int row = 0; row < places_with_baloo.rowCount(); ++row) { 0831 QModelIndex index = places_with_baloo.index(row, 0); 0832 urls << places_with_baloo.url(index).toDisplayString(QUrl::PreferLocalFile); 0833 } 0834 0835 if (m_hasRecentlyUsedKio) { 0836 QVERIFY(urls.contains("recentlyused:/files")); 0837 QVERIFY(urls.contains("recentlyused:/locations")); 0838 } 0839 } 0840 0841 void KFilePlacesModelTest::testRemoteUrls_data() 0842 { 0843 QTest::addColumn<QUrl>("url"); 0844 QTest::addColumn<int>("expectedRow"); 0845 QTest::addColumn<QString>("expectedGroup"); 0846 0847 QTest::newRow("Ftp") << QUrl(QStringLiteral("ftp://192.168.1.1/ftp")) << 4 << QStringLiteral("Remote"); 0848 QTest::newRow("Samba") << QUrl(QStringLiteral("smb://192.168.1.1/share")) << 4 << QStringLiteral("Remote"); 0849 QTest::newRow("Sftp") << QUrl(QStringLiteral("sftp://192.168.1.1/share")) << 4 << QStringLiteral("Remote"); 0850 QTest::newRow("Fish") << QUrl(QStringLiteral("fish://192.168.1.1/share")) << 4 << QStringLiteral("Remote"); 0851 QTest::newRow("Webdav") << QUrl(QStringLiteral("webdav://192.168.1.1/share")) << 4 << QStringLiteral("Remote"); 0852 } 0853 0854 void KFilePlacesModelTest::testRemoteUrls() 0855 { 0856 QFETCH(QUrl, url); 0857 QFETCH(int, expectedRow); 0858 QFETCH(QString, expectedGroup); 0859 0860 QList<QVariant> args; 0861 QSignalSpy spy_inserted(m_places, &QAbstractItemModel::rowsInserted); 0862 0863 // insert a new network url 0864 m_places->addPlace(QStringLiteral("My Shared"), url, QString(), QString(), QModelIndex()); 0865 0866 // check if url list is correct after insertion 0867 QStringList urls; 0868 urls << QDir::homePath() << QStringLiteral("trash:/") // places 0869 << QStringLiteral("remote:/") << QStringLiteral("/media/nfs") << url.toString() << initialListOfRecent() << QStringLiteral("/foreign") 0870 << QStringLiteral("/media/floppy0") << QStringLiteral("/media/XO-Y4") << QStringLiteral("/media/cdrom"); 0871 CHECK_PLACES_URLS(urls); 0872 0873 // check if the new url was inserted in the right position (end of "Remote" section) 0874 QTRY_COMPARE(spy_inserted.count(), 1); 0875 args = spy_inserted.takeFirst(); 0876 QCOMPARE(args.at(0).toModelIndex(), QModelIndex()); 0877 QCOMPARE(args.at(1).toInt(), expectedRow); 0878 QCOMPARE(args.at(2).toInt(), expectedRow); 0879 0880 // check if the new url has the right group "Remote" 0881 const QModelIndex index = m_places->index(expectedRow, 0); 0882 QCOMPARE(index.data(KFilePlacesModel::GroupRole).toString(), expectedGroup); 0883 0884 m_places->removePlace(index); 0885 } 0886 0887 void KFilePlacesModelTest::testRefresh() 0888 { 0889 KBookmarkManager bookmarkManager(bookmarksFile()); 0890 KBookmarkGroup root = bookmarkManager.root(); 0891 KBookmark homePlace = root.first(); 0892 const QModelIndex homePlaceIndex = m_places->index(0, 0); 0893 0894 QCOMPARE(m_places->text(homePlaceIndex), homePlace.fullText()); 0895 0896 // modify bookmark 0897 homePlace.setFullText("Test change the text"); 0898 QVERIFY(m_places->text(homePlaceIndex) != homePlace.fullText()); 0899 0900 // reload bookmark data 0901 m_places->refresh(); 0902 QCOMPARE(m_places->text(homePlaceIndex), homePlace.fullText()); 0903 } 0904 0905 void KFilePlacesModelTest::testConvertedUrl_data() 0906 { 0907 QTest::addColumn<QUrl>("url"); 0908 QTest::addColumn<QUrl>("expectedUrl"); 0909 0910 // places 0911 QTest::newRow("Places - Home") << QUrl::fromLocalFile(QDir::homePath()) << QUrl::fromLocalFile(QDir::homePath()); 0912 0913 // baloo -search 0914 QTest::newRow("Baloo - Documents") << QUrl("search:/documents") << QUrl("baloosearch:/documents"); 0915 0916 QTest::newRow("Baloo - Unknown Type") << QUrl("search:/unknown") << QUrl("search:/unknown"); 0917 0918 // baloo - timeline 0919 const QDate lastMonthDate = QDate::currentDate().addMonths(-1); 0920 QTest::newRow("Baloo - Last Month") << QUrl("timeline:/lastmonth") 0921 << QUrl(QString("timeline:/%1-%2").arg(lastMonthDate.year()).arg(lastMonthDate.month(), 2, 10, QLatin1Char('0'))); 0922 0923 // devices 0924 QTest::newRow("Devices - Floppy") << QUrl("file:///media/floppy0") << QUrl("file:///media/floppy0"); 0925 } 0926 0927 void KFilePlacesModelTest::testConvertedUrl() 0928 { 0929 QFETCH(QUrl, url); 0930 QFETCH(QUrl, expectedUrl); 0931 0932 const QUrl convertedUrl = KFilePlacesModel::convertedUrl(url); 0933 0934 QCOMPARE(convertedUrl.scheme(), expectedUrl.scheme()); 0935 QCOMPARE(convertedUrl.path(), expectedUrl.path()); 0936 QCOMPARE(convertedUrl, expectedUrl); 0937 } 0938 0939 void KFilePlacesModelTest::testBookmarkObject() 0940 { 0941 // make sure that all items return a valid bookmark 0942 for (int row = 0; row < m_places->rowCount(); row++) { 0943 const QModelIndex index = m_places->index(row, 0); 0944 const KBookmark bookmark = m_places->bookmarkForIndex(index); 0945 QVERIFY(!bookmark.isNull()); 0946 } 0947 } 0948 0949 void KFilePlacesModelTest::testDataChangedSignal() 0950 { 0951 QSignalSpy dataChangedSpy(m_places, &KFilePlacesModel::dataChanged); 0952 0953 const QModelIndex index = m_places->index(1, 0); 0954 const KBookmark bookmark = m_places->bookmarkForIndex(index); 0955 0956 // call function with the same data 0957 m_places->editPlace(index, bookmark.fullText(), bookmark.url(), bookmark.icon(), bookmark.metaDataItem(QStringLiteral("OnlyInApp"))); 0958 QCOMPARE(dataChangedSpy.count(), 0); 0959 0960 // call function with different data 0961 const QString originalText = bookmark.fullText(); 0962 m_places->editPlace(index, QStringLiteral("My text"), bookmark.url(), bookmark.icon(), bookmark.metaDataItem(QStringLiteral("OnlyInApp"))); 0963 QCOMPARE(dataChangedSpy.count(), 1); 0964 QList<QVariant> args = dataChangedSpy.takeFirst(); 0965 QCOMPARE(args.at(0).toModelIndex().row(), 1); 0966 QCOMPARE(args.at(0).toModelIndex().column(), 0); 0967 QCOMPARE(args.at(1).toModelIndex().row(), 1); 0968 QCOMPARE(args.at(1).toModelIndex().column(), 0); 0969 QCOMPARE(m_places->text(index), QStringLiteral("My text")); 0970 0971 // restore original value 0972 dataChangedSpy.clear(); 0973 m_places->editPlace(index, originalText, bookmark.url(), bookmark.icon(), bookmark.metaDataItem(QStringLiteral("OnlyInApp"))); 0974 QCOMPARE(dataChangedSpy.count(), 1); 0975 } 0976 0977 void KFilePlacesModelTest::testIconRole_data() 0978 { 0979 QTest::addColumn<QModelIndex>("index"); 0980 QTest::addColumn<QString>("expectedIconName"); 0981 0982 // places 0983 int index = 0; 0984 QTest::newRow("Places - Home") << m_places->index(index++, 0) << QStringLiteral("user-home"); 0985 QTest::newRow("Places - Trash") << m_places->index(index++, 0) << QStringLiteral("user-trash"); 0986 0987 QTest::newRow("Remote - Network") << m_places->index(index++, 0) << QStringLiteral("folder-network"); 0988 QTest::newRow("Devices - Nfs") << m_places->index(index++, 0) << QStringLiteral("hwinfo"); 0989 if (m_hasRecentlyUsedKio) { 0990 QTest::newRow("Recent Files") << m_places->index(index++, 0) << QStringLiteral("document-open-recent"); 0991 QTest::newRow("Recent Locations") << m_places->index(index++, 0) << QStringLiteral("folder-open-recent"); 0992 } 0993 QTest::newRow("Devices - foreign") << m_places->index(index++, 0) << QStringLiteral("blockdevice"); 0994 QTest::newRow("Devices - Floppy") << m_places->index(index++, 0) << QStringLiteral("blockdevice"); 0995 QTest::newRow("Devices - cdrom") << m_places->index(index++, 0) << QStringLiteral("blockdevice"); 0996 } 0997 0998 void KFilePlacesModelTest::testIconRole() 0999 { 1000 QFETCH(QModelIndex, index); 1001 QFETCH(QString, expectedIconName); 1002 1003 QVERIFY(index.data(KFilePlacesModel::IconNameRole).toString().startsWith(expectedIconName)); 1004 } 1005 1006 void KFilePlacesModelTest::testMoveFunction() 1007 { 1008 QList<QVariant> args; 1009 QStringList urls = initialListOfUrls(); 1010 QSignalSpy rowsMoved(m_places, &KFilePlacesModel::rowsMoved); 1011 1012 // move item 0 to pos 1 1013 QVERIFY(m_places->movePlace(0, 2)); 1014 urls.move(0, 1); 1015 QTRY_COMPARE(rowsMoved.count(), 1); 1016 args = rowsMoved.takeFirst(); 1017 QCOMPARE(args.at(1).toInt(), 0); // start 1018 QCOMPARE(args.at(2).toInt(), 0); // end 1019 QCOMPARE(args.at(4).toInt(), 2); // row (destination) 1020 QCOMPARE(placesUrls(), urls); 1021 rowsMoved.clear(); 1022 1023 // move it back 1024 QVERIFY(m_places->movePlace(1, 0)); 1025 urls.move(1, 0); 1026 QTRY_COMPARE(rowsMoved.count(), 1); 1027 args = rowsMoved.takeFirst(); 1028 QCOMPARE(args.at(1).toInt(), 1); // start 1029 QCOMPARE(args.at(2).toInt(), 1); // end 1030 QCOMPARE(args.at(4).toInt(), 0); // row (destination) 1031 QCOMPARE(placesUrls(), urls); 1032 rowsMoved.clear(); 1033 1034 // target position is greater than model rows 1035 // will move to the end of the first group 1036 QVERIFY(m_places->movePlace(0, 20)); 1037 urls.move(0, 1); 1038 QTRY_COMPARE(rowsMoved.count(), 1); 1039 args = rowsMoved.takeFirst(); 1040 QCOMPARE(args.at(1).toInt(), 0); // start 1041 QCOMPARE(args.at(2).toInt(), 0); // end 1042 QCOMPARE(args.at(4).toInt(), 2); // row (destination) 1043 QCOMPARE(placesUrls(), urls); 1044 rowsMoved.clear(); 1045 1046 // move it back 1047 QVERIFY(m_places->movePlace(1, 0)); 1048 urls.move(1, 0); 1049 QTRY_COMPARE(rowsMoved.count(), 1); 1050 args = rowsMoved.takeFirst(); 1051 QCOMPARE(args.at(1).toInt(), 1); // start 1052 QCOMPARE(args.at(2).toInt(), 1); // end 1053 QCOMPARE(args.at(4).toInt(), 0); // row (destination) 1054 QCOMPARE(placesUrls(), urls); 1055 rowsMoved.clear(); 1056 1057 QVERIFY(m_places->movePlace(m_hasRecentlyUsedKio ? 8 : 7, m_hasRecentlyUsedKio ? 6 : 5)); 1058 urls.move(m_hasRecentlyUsedKio ? 8 : 7, m_hasRecentlyUsedKio ? 6 : 5); 1059 QTRY_COMPARE(rowsMoved.count(), 1); 1060 args = rowsMoved.takeFirst(); 1061 QCOMPARE(args.at(1).toInt(), m_hasRecentlyUsedKio ? 8 : 7); // start 1062 QCOMPARE(args.at(2).toInt(), m_hasRecentlyUsedKio ? 8 : 7); // end 1063 QCOMPARE(args.at(4).toInt(), m_hasRecentlyUsedKio ? 6 : 5); // row (destination) 1064 QCOMPARE(placesUrls(), urls); 1065 rowsMoved.clear(); 1066 1067 // move it back 1068 QVERIFY(m_places->movePlace(m_hasRecentlyUsedKio ? 6 : 5, m_hasRecentlyUsedKio ? 9 : 8)); 1069 urls.move(m_hasRecentlyUsedKio ? 6 : 5, m_hasRecentlyUsedKio ? 8 : 7); 1070 QTRY_COMPARE(rowsMoved.count(), 1); 1071 args = rowsMoved.takeFirst(); 1072 QCOMPARE(args.at(1).toInt(), m_hasRecentlyUsedKio ? 6 : 5); // start 1073 QCOMPARE(args.at(2).toInt(), m_hasRecentlyUsedKio ? 6 : 5); // end 1074 QCOMPARE(args.at(4).toInt(), m_hasRecentlyUsedKio ? 9 : 8); // row (destination) 1075 QCOMPARE(placesUrls(), urls); 1076 rowsMoved.clear(); 1077 1078 // use a invalid start position 1079 QVERIFY(!m_places->movePlace(100, 20)); 1080 QCOMPARE(rowsMoved.count(), 0); 1081 1082 // use same start and target position 1083 QVERIFY(!m_places->movePlace(1, 1)); 1084 QCOMPARE(rowsMoved.count(), 0); 1085 } 1086 1087 void KFilePlacesModelTest::testPlaceGroupHidden() 1088 { 1089 // GIVEN 1090 QCOMPARE(m_places->hiddenCount(), 0); 1091 1092 QStringList urls; 1093 urls << initialListOfPlaces() << initialListOfShared() << initialListOfRecent() << initialListOfDevices() << initialListOfRemovableDevices(); 1094 CHECK_PLACES_URLS(urls); 1095 QList<QModelIndex> indexesHidden; 1096 1097 // WHEN 1098 m_places->setGroupHidden(KFilePlacesModel::PlacesType, true); 1099 1100 // THEN 1101 for (int row = 0; row < m_places->rowCount(); ++row) { 1102 QModelIndex index = m_places->index(row, 0); 1103 if (m_places->groupType(index) == KFilePlacesModel::PlacesType) { 1104 QVERIFY(m_places->isHidden(index)); 1105 indexesHidden << index; 1106 } 1107 } 1108 QCOMPARE(indexesHidden.count(), initialListOfPlaces().size()); 1109 QCOMPARE(m_places->hiddenCount(), indexesHidden.size()); 1110 1111 // and GIVEN 1112 QList<QModelIndex> indexesShown; 1113 1114 // WHEN 1115 m_places->setGroupHidden(KFilePlacesModel::PlacesType, false); 1116 1117 // THEN 1118 for (int row = 0; row < m_places->rowCount(); ++row) { 1119 QModelIndex index = m_places->index(row, 0); 1120 if (m_places->groupType(index) == KFilePlacesModel::PlacesType) { 1121 QVERIFY(!m_places->isHidden(index)); 1122 indexesShown << index; 1123 } 1124 } 1125 QCOMPARE(m_places->hiddenCount(), 0); 1126 QCOMPARE(indexesShown.count(), initialListOfPlaces().size()); 1127 } 1128 1129 void KFilePlacesModelTest::testPlaceGroupHiddenVsPlaceChildShown() 1130 { 1131 // GIVEN 1132 for (int row = 0; row < m_places->rowCount(); ++row) { 1133 QModelIndex index = m_places->index(row, 0); 1134 QVERIFY(!m_places->isHidden(index)); 1135 } 1136 m_places->setGroupHidden(KFilePlacesModel::PlacesType, true); 1137 1138 QModelIndex firstIndex = m_places->index(0, 0); 1139 const int amountOfPlaces = initialListOfPlaces().size(); 1140 for (int row = 0; row < amountOfPlaces; ++row) { 1141 QModelIndex index = m_places->index(row, 0); 1142 QVERIFY(m_places->isHidden(index)); 1143 } 1144 // WHEN 1145 m_places->setPlaceHidden(firstIndex, false); 1146 1147 // THEN 1148 QVERIFY(m_places->isHidden(firstIndex)); // a child cannot show against its parent state 1149 1150 // leaving in a clean state 1151 m_places->setGroupHidden(KFilePlacesModel::PlacesType, false); 1152 } 1153 1154 void KFilePlacesModelTest::testPlaceGroupHiddenAndShownWithHiddenChild() 1155 { 1156 // GIVEN 1157 QCOMPARE(m_places->hiddenCount(), 0); 1158 1159 QStringList urls; 1160 urls << initialListOfPlaces() << initialListOfShared() << initialListOfRecent() << initialListOfDevices() << initialListOfRemovableDevices(); 1161 CHECK_PLACES_URLS(urls); 1162 1163 QModelIndex firstIndexHidden = m_places->index(0, 0); 1164 m_places->setPlaceHidden(firstIndexHidden, true); // first place index is hidden within an hidden parent 1165 m_places->setGroupHidden(KFilePlacesModel::PlacesType, true); 1166 QCOMPARE(m_places->hiddenCount(), initialListOfPlaces().size()); 1167 1168 // WHEN 1169 m_places->setGroupHidden(KFilePlacesModel::PlacesType, false); 1170 1171 // THEN 1172 QList<QModelIndex> indexesShown; 1173 for (int row = 0; row < m_places->rowCount(); ++row) { 1174 QModelIndex index = m_places->index(row, 0); 1175 if (index == firstIndexHidden) { 1176 QVERIFY(m_places->isHidden(firstIndexHidden)); 1177 continue; 1178 } 1179 if (m_places->groupType(index) == KFilePlacesModel::PlacesType) { 1180 QVERIFY(!m_places->isHidden(index)); 1181 indexesShown << index; 1182 } 1183 } 1184 QCOMPARE(m_places->hiddenCount(), 1); 1185 QCOMPARE(indexesShown.count(), initialListOfPlaces().size() - 1 /*first child remains hidden*/); 1186 1187 // leaving in a clean state 1188 m_places->setPlaceHidden(firstIndexHidden, false); 1189 } 1190 1191 void KFilePlacesModelTest::testPlaceGroupHiddenGroupIndexesIntegrity() 1192 { 1193 // GIVEN 1194 m_places->setGroupHidden(KFilePlacesModel::PlacesType, true); 1195 QVERIFY(m_places->groupIndexes(KFilePlacesModel::UnknownType).isEmpty()); 1196 QVERIFY(m_places->isGroupHidden(KFilePlacesModel::PlacesType)); 1197 QCOMPARE(m_places->groupIndexes(KFilePlacesModel::PlacesType).count(), initialListOfPlaces().count()); 1198 QCOMPARE(m_places->groupIndexes(KFilePlacesModel::RecentlySavedType).count(), m_hasRecentlyUsedKio ? 2 : 0); 1199 QCOMPARE(m_places->groupIndexes(KFilePlacesModel::SearchForType).count(), 0); 1200 QCOMPARE(m_places->groupIndexes(KFilePlacesModel::DevicesType).count(), initialListOfDevices().count()); 1201 QCOMPARE(m_places->groupIndexes(KFilePlacesModel::RemovableDevicesType).count(), initialListOfRemovableDevices().count()); 1202 1203 // WHEN 1204 m_places->setGroupHidden(KFilePlacesModel::PlacesType, false); 1205 1206 // THEN 1207 // Make sure that hidden place group doesn't change model 1208 QVERIFY(!m_places->isGroupHidden(KFilePlacesModel::PlacesType)); 1209 QCOMPARE(m_places->groupIndexes(KFilePlacesModel::PlacesType).count(), initialListOfPlaces().count()); 1210 QCOMPARE(m_places->groupIndexes(KFilePlacesModel::RecentlySavedType).count(), m_hasRecentlyUsedKio ? 2 : 0); 1211 QCOMPARE(m_places->groupIndexes(KFilePlacesModel::SearchForType).count(), 0); 1212 QCOMPARE(m_places->groupIndexes(KFilePlacesModel::DevicesType).count(), initialListOfDevices().count()); 1213 QCOMPARE(m_places->groupIndexes(KFilePlacesModel::RemovableDevicesType).count(), initialListOfRemovableDevices().count()); 1214 } 1215 1216 void KFilePlacesModelTest::testPlaceGroupHiddenSignal() 1217 { 1218 QSignalSpy groupHiddenSignal(m_places, &KFilePlacesModel::groupHiddenChanged); 1219 m_places->setGroupHidden(KFilePlacesModel::SearchForType, true); 1220 1221 // hide SearchForType group 1222 QTRY_COMPARE(groupHiddenSignal.count(), 1); 1223 QList<QVariant> args = groupHiddenSignal.takeFirst(); 1224 QCOMPARE(args.at(0).toInt(), static_cast<int>(KFilePlacesModel::SearchForType)); 1225 QCOMPARE(args.at(1).toBool(), true); 1226 groupHiddenSignal.clear(); 1227 1228 // try hide SearchForType which is already hidden 1229 m_places->setGroupHidden(KFilePlacesModel::SearchForType, true); 1230 QCOMPARE(groupHiddenSignal.count(), 0); 1231 1232 // show SearchForType group 1233 m_places->setGroupHidden(KFilePlacesModel::SearchForType, false); 1234 QTRY_COMPARE(groupHiddenSignal.count(), 1); 1235 args = groupHiddenSignal.takeFirst(); 1236 QCOMPARE(args.at(0).toInt(), static_cast<int>(KFilePlacesModel::SearchForType)); 1237 QCOMPARE(args.at(1).toBool(), false); 1238 } 1239 1240 void KFilePlacesModelTest::testPlaceGroupHiddenRole() 1241 { 1242 // on startup all groups are visible 1243 for (int r = 0, rMax = m_places->rowCount(); r < rMax; r++) { 1244 const QModelIndex index = m_places->index(r, 0); 1245 QCOMPARE(index.data(KFilePlacesModel::GroupHiddenRole).toBool(), false); 1246 } 1247 1248 // set SearchFor group hidden 1249 m_places->setGroupHidden(KFilePlacesModel::SearchForType, true); 1250 for (auto groupType : {KFilePlacesModel::PlacesType, 1251 KFilePlacesModel::RemoteType, 1252 KFilePlacesModel::RecentlySavedType, 1253 KFilePlacesModel::SearchForType, 1254 KFilePlacesModel::DevicesType, 1255 KFilePlacesModel::RemovableDevicesType}) { 1256 const bool groupShouldBeHidden = (groupType == KFilePlacesModel::SearchForType); 1257 const QModelIndexList indexes = m_places->groupIndexes(groupType); 1258 for (const QModelIndex &index : indexes) { 1259 QCOMPARE(index.data(KFilePlacesModel::GroupHiddenRole).toBool(), groupShouldBeHidden); 1260 } 1261 } 1262 1263 // set SearchFor group visible again 1264 m_places->setGroupHidden(KFilePlacesModel::SearchForType, false); 1265 for (int r = 0, rMax = m_places->rowCount(); r < rMax; r++) { 1266 const QModelIndex index = m_places->index(r, 0); 1267 QCOMPARE(index.data(KFilePlacesModel::GroupHiddenRole).toBool(), false); 1268 } 1269 } 1270 1271 void KFilePlacesModelTest::testSupportedSchemes() 1272 { 1273 QCoreApplication::processEvents(); // support running this test on its own 1274 1275 QCOMPARE(m_places->supportedSchemes(), QStringList()); 1276 QCOMPARE(placesUrls(), initialListOfUrls()); 1277 m_places->setSupportedSchemes({"trash"}); 1278 QCOMPARE(m_places->supportedSchemes(), QStringList("trash")); 1279 QCOMPARE(placesUrls(), QStringList("trash:/")); 1280 m_places->setSupportedSchemes({}); 1281 QCOMPARE(m_places->supportedSchemes(), QStringList()); 1282 QCOMPARE(placesUrls(), initialListOfUrls()); 1283 } 1284 1285 QTEST_MAIN(KFilePlacesModelTest) 1286 1287 #include "kfileplacesmodeltest.moc"