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