2 * SPDX-FileCopyrightText: 2017 Renato Araujo Oliveira <renato.araujo@kdab.com>
4 * SPDX-License-Identifier: GPL-2.0-or-later
9 #include <QStandardPaths>
11 #include <QDBusInterface>
13 #include <KBookmarkManager>
15 #include <KConfigGroup>
17 #include <KFilePlacesModel>
18 #include <KProtocolInfo>
20 #include "dolphin_generalsettings.h"
21 #include "panels/places/placesitemmodel.h"
22 #include "panels/places/placesitem.h"
23 #include "views/viewproperties.h"
25 Q_DECLARE_METATYPE(KItemRangeList
)
26 Q_DECLARE_METATYPE(KItemRange
)
28 static QString
bookmarksFile()
30 return QStandardPaths::writableLocation(QStandardPaths::GenericDataLocation
) + "/user-places.xbel";
33 class PlacesItemModelTest
: public QObject
42 void cleanupTestCase();
46 void testDeletePlace();
47 void testPlaceItem_data();
49 void testTearDownDevice();
50 void testDefaultViewProperties_data();
51 void testDefaultViewProperties();
54 void testSystemItems();
55 void testEditBookmark();
56 void testEditAfterCreation();
57 void testEditMetadata();
59 void testIcons_data();
61 void testDragAndDrop();
62 void testHideDevices();
63 void testDuplicatedEntries();
64 void renameAfterCreation();
67 PlacesItemModel
* m_model
;
68 QSet
<int> m_tobeRemoved
;
69 QMap
<QString
, QDBusInterface
*> m_interfacesMap
;
70 int m_expectedModelCount
= qEnvironmentVariableIsSet("KDE_FULL_SESSION") && KProtocolInfo::isKnownProtocol(QStringLiteral("recentlyused")) ? 14 : 12;
71 bool m_hasDesktopFolder
= false;
72 bool m_hasDocumentsFolder
= false;
73 bool m_hasDownloadsFolder
= false;
74 bool m_hasMusicFolder
= false;
75 bool m_hasPicturesFolder
= false;
76 bool m_hasVideosFolder
= false;
78 void setBalooEnabled(bool enabled
);
79 int indexOf(const QUrl
&url
);
80 QDBusInterface
*fakeManager();
81 QDBusInterface
*fakeDevice(const QString
&udi
);
82 QStringList
placesUrls(PlacesItemModel
*model
= nullptr) const;
83 QStringList
initialUrls() const;
84 void createPlaceItem(const QString
&text
, const QUrl
&url
, const QString
&icon
);
85 void schedulePlaceRemoval(int index
);
86 void cancelPlaceRemoval(int index
);
87 QMimeData
*createMimeData(const QList
<int> &indexes
) const;
88 void increaseIndexIfNeeded(int &index
) const;
89 QTemporaryDir m_tempHomeDir
;
92 #define CHECK_PLACES_URLS(urls) \
94 QStringList places = placesUrls(); \
95 if (places != urls) { \
96 qWarning() << "Expected:" << urls; \
97 qWarning() << "Got:" << places; \
98 QCOMPARE(places, urls); \
102 void PlacesItemModelTest::setBalooEnabled(bool enabled
)
104 KConfig
config(QStringLiteral("baloofilerc"));
105 KConfigGroup basicSettings
= config
.group("Basic Settings");
106 basicSettings
.writeEntry("Indexing-Enabled", enabled
);
110 int PlacesItemModelTest::indexOf(const QUrl
&url
)
112 for (int r
= 0; r
< m_model
->count(); r
++) {
113 if (m_model
->placesItem(r
)->url() == url
) {
120 QDBusInterface
*PlacesItemModelTest::fakeManager()
122 return fakeDevice(QStringLiteral("/org/kde/solid/fakehw"));
125 QDBusInterface
*PlacesItemModelTest::fakeDevice(const QString
&udi
)
127 if (m_interfacesMap
.contains(udi
)) {
128 return m_interfacesMap
[udi
];
131 QDBusInterface
*iface
= new QDBusInterface(QDBusConnection::sessionBus().baseService(), udi
);
132 m_interfacesMap
[udi
] = iface
;
137 QStringList
PlacesItemModelTest::placesUrls(PlacesItemModel
*model
) const
144 for (int row
= 0; row
< model
->count(); ++row
) {
145 urls
<< model
->placesItem(row
)->url().toDisplayString(QUrl::PreferLocalFile
);
150 QStringList
PlacesItemModelTest::initialUrls() const
152 static QStringList urls
;
153 if (urls
.isEmpty()) {
154 urls
<< QDir::homePath();
156 if (m_hasDesktopFolder
) {
157 urls
<< QDir::homePath() + QStringLiteral("/Desktop");
160 if (m_hasDocumentsFolder
) {
161 urls
<< QDir::homePath() + QStringLiteral("/Documents");
164 if (m_hasDownloadsFolder
) {
165 urls
<< QDir::homePath() + QStringLiteral("/Downloads");
168 if (m_hasMusicFolder
) {
169 urls
<< QDir::homePath() + QStringLiteral("/Music");
172 if (m_hasPicturesFolder
) {
173 urls
<< QDir::homePath() + QStringLiteral("/Pictures");
176 if (m_hasVideosFolder
) {
177 urls
<< QDir::homePath() + QStringLiteral("/Videos");
180 urls
<< QStringLiteral("trash:/")
181 << QStringLiteral("remote:/")
182 << QStringLiteral("/media/nfs");
184 if (qEnvironmentVariableIsSet("KDE_FULL_SESSION") && KProtocolInfo::isKnownProtocol(QStringLiteral("recentlyused"))) {
185 urls
<< QStringLiteral("recentlyused:/files");
186 urls
<< QStringLiteral("recentlyused:/locations");
189 urls
<< QStringLiteral("search:/documents") << QStringLiteral("search:/images") << QStringLiteral("search:/audio") << QStringLiteral("search:/videos")
190 << QStringLiteral("/foreign")
191 << QStringLiteral("/media/floppy0") << QStringLiteral("/media/XO-Y4") << QStringLiteral("/media/cdrom");
196 void PlacesItemModelTest::createPlaceItem(const QString
&text
, const QUrl
&url
, const QString
&icon
)
198 m_model
->createPlacesItem(text
, url
, icon
);
201 void PlacesItemModelTest::schedulePlaceRemoval(int index
)
203 m_tobeRemoved
.insert(index
);
206 void PlacesItemModelTest::cancelPlaceRemoval(int index
)
208 m_tobeRemoved
.remove(index
);
211 QMimeData
*PlacesItemModelTest::createMimeData(const QList
<int> &indexes
) const
214 QDataStream
stream(&itemData
, QIODevice::WriteOnly
);
217 for (int index
: indexes
) {
218 const QUrl itemUrl
= m_model
->placesItem(index
)->url();
219 if (itemUrl
.isValid()) {
225 QMimeData
* mimeData
= new QMimeData();
226 mimeData
->setUrls(urls
);
227 // copied from PlacesItemModel::internalMimeType()
228 const QString internalMimeType
= "application/x-dolphinplacesmodel-" +
229 QString::number((qptrdiff
)m_model
);
230 mimeData
->setData(internalMimeType
, itemData
);
234 void PlacesItemModelTest::increaseIndexIfNeeded(int &index
) const
236 if (m_hasDesktopFolder
) {
239 if (m_hasDocumentsFolder
) {
242 if (m_hasDownloadsFolder
) {
245 if (m_hasMusicFolder
) {
248 if (m_hasPicturesFolder
) {
251 if (m_hasVideosFolder
) {
256 void PlacesItemModelTest::init()
258 m_model
= new PlacesItemModel();
259 // WORKAROUND: need to wait for bookmark to load
261 QCOMPARE(m_model
->count(), m_expectedModelCount
);
264 void PlacesItemModelTest::cleanup()
266 const auto tobeRemoved
= m_tobeRemoved
;
267 for (const int i
: tobeRemoved
) {
268 int before
= m_model
->count();
269 m_model
->deleteItem(i
);
270 QTRY_COMPARE(m_model
->count(), before
- 1);
272 m_tobeRemoved
.clear();
277 void PlacesItemModelTest::initTestCase()
279 QVERIFY(m_tempHomeDir
.isValid());
280 QVERIFY(qputenv("HOME", m_tempHomeDir
.path().toUtf8()));
281 QVERIFY(qputenv("KDE_FORK_SLAVES", "yes"));
283 QStandardPaths::setTestModeEnabled(true);
285 const QString fakeHw
= QFINDTESTDATA("data/fakecomputer.xml");
286 QVERIFY(!fakeHw
.isEmpty());
287 qputenv("SOLID_FAKEHW", QFile::encodeName(fakeHw
));
289 setBalooEnabled(true);
290 const QString bookmarsFileName
= bookmarksFile();
291 if (QFileInfo::exists(bookmarsFileName
)) {
292 // Ensure we'll have a clean bookmark file to start
293 QVERIFY(QFile::remove(bookmarsFileName
));
296 if (QDir(QStandardPaths::writableLocation(QStandardPaths::DesktopLocation
)).exists()) {
297 m_hasDesktopFolder
= true;
298 m_expectedModelCount
++;
301 if (QDir(QStandardPaths::writableLocation(QStandardPaths::DocumentsLocation
)).exists()) {
302 m_hasDocumentsFolder
= true;
303 m_expectedModelCount
++;
306 if (QDir(QStandardPaths::writableLocation(QStandardPaths::DownloadLocation
)).exists()) {
307 m_hasDownloadsFolder
= true;
308 m_expectedModelCount
++;
311 if (QDir(QStandardPaths::writableLocation(QStandardPaths::MusicLocation
)).exists()) {
312 m_hasMusicFolder
= true;
313 m_expectedModelCount
++;
316 if (QDir(QStandardPaths::writableLocation(QStandardPaths::PicturesLocation
)).exists()) {
317 m_hasPicturesFolder
= true;
318 m_expectedModelCount
++;
321 if (QDir(QStandardPaths::writableLocation(QStandardPaths::MoviesLocation
)).exists()) {
322 m_hasVideosFolder
= true;
323 m_expectedModelCount
++;
326 qRegisterMetaType
<KItemRangeList
>();
327 qRegisterMetaType
<KItemRange
>();
330 void PlacesItemModelTest::cleanupTestCase()
332 qDeleteAll(m_interfacesMap
);
333 QFile::remove(bookmarksFile());
336 void PlacesItemModelTest::testModelSort()
338 CHECK_PLACES_URLS(initialUrls());
341 void PlacesItemModelTest::testGroups()
343 const auto groups
= m_model
->groups();
344 int expectedRemoteIndex
= 2;
345 increaseIndexIfNeeded(expectedRemoteIndex
);
347 QCOMPARE(groups
.size(), 6);
349 QCOMPARE(groups
.at(0).first
, 0);
350 QCOMPARE(groups
.at(0).second
.toString(), QStringLiteral("Places"));
352 QCOMPARE(groups
.at(1).first
, expectedRemoteIndex
);
353 QCOMPARE(groups
.at(1).second
.toString(), QStringLiteral("Remote"));
355 if (qEnvironmentVariableIsSet("KDE_FULL_SESSION") && KProtocolInfo::isKnownProtocol(QStringLiteral("recentlyused"))) {
356 expectedRemoteIndex
+= 2;
359 QCOMPARE(groups
.at(3).first
, expectedRemoteIndex
+ 2);
360 QCOMPARE(groups
.at(3).second
.toString(), QStringLiteral("Search For"));
362 QCOMPARE(groups
.at(4).first
, expectedRemoteIndex
+ 6);
363 QCOMPARE(groups
.at(4).second
.toString(), QStringLiteral("Devices"));
365 QCOMPARE(groups
.at(5).first
, expectedRemoteIndex
+ 7);
366 QCOMPARE(groups
.at(5).second
.toString(), QStringLiteral("Removable Devices"));
369 void PlacesItemModelTest::testPlaceItem_data()
371 QTest::addColumn
<QUrl
>("url");
372 QTest::addColumn
<bool>("expectedIsHidden");
373 QTest::addColumn
<bool>("expectedIsSystemItem");
374 QTest::addColumn
<QString
>("expectedGroup");
375 QTest::addColumn
<bool>("expectedStorageSetupNeeded");
378 QTest::newRow("Places - Home") << QUrl::fromLocalFile(QDir::homePath()) << false << true << QStringLiteral("Places") << false;
381 QTest::newRow("Baloo - Documents") << QUrl("search:/documents") << false << true << QStringLiteral("Search For") << false;
384 QTest::newRow("Devices - Floppy") << QUrl("file:///media/floppy0") << false << false << QStringLiteral("Removable Devices") << false;
387 void PlacesItemModelTest::testPlaceItem()
390 QFETCH(bool, expectedIsHidden
);
391 QFETCH(bool, expectedIsSystemItem
);
392 QFETCH(QString
, expectedGroup
);
393 QFETCH(bool, expectedStorageSetupNeeded
);
395 const int index
= indexOf(url
);
396 PlacesItem
*item
= m_model
->placesItem(index
);
397 QCOMPARE(item
->url(), url
);
398 QCOMPARE(item
->isHidden(), expectedIsHidden
);
399 QCOMPARE(item
->isSystemItem(), expectedIsSystemItem
);
400 QCOMPARE(item
->group(), expectedGroup
);
401 QCOMPARE(item
->storageSetupNeeded(), expectedStorageSetupNeeded
);
404 void PlacesItemModelTest::testDeletePlace()
406 const QUrl tempUrl
= QUrl::fromLocalFile(QStandardPaths::writableLocation(QStandardPaths::TempLocation
));
407 QStringList urls
= initialUrls();
408 QSignalSpy
itemsInsertedSpy(m_model
, &PlacesItemModel::itemsInserted
);
409 QSignalSpy
itemsRemovedSpy(m_model
, &PlacesItemModel::itemsRemoved
);
411 PlacesItemModel
*model
= new PlacesItemModel();
413 int tempDirIndex
= 2;
414 increaseIndexIfNeeded(tempDirIndex
);
416 // create a new place
417 createPlaceItem(QStringLiteral("Temporary Dir"), tempUrl
, QString());
418 urls
.insert(tempDirIndex
, tempUrl
.toLocalFile());
420 // check if the new entry was created
421 QTRY_COMPARE(itemsInsertedSpy
.count(), 1);
422 CHECK_PLACES_URLS(urls
);
423 QTRY_COMPARE(model
->count(), m_model
->count());
426 m_model
->deleteItem(tempDirIndex
);
428 // make sure that the new item is removed
429 QTRY_COMPARE(itemsRemovedSpy
.count(), 1);
430 QTRY_COMPARE(m_model
->count(), m_expectedModelCount
);
431 CHECK_PLACES_URLS(initialUrls());
432 QTRY_COMPARE(model
->count(), m_model
->count());
435 void PlacesItemModelTest::testTearDownDevice()
437 const QUrl mediaUrl
= QUrl::fromLocalFile(QStringLiteral("/media/XO-Y4"));
438 int index
= indexOf(mediaUrl
);
439 QVERIFY(index
!= -1);
441 auto ejectAction
= m_model
->ejectAction(index
);
442 QVERIFY(!ejectAction
);
444 auto teardownAction
= m_model
->teardownAction(index
);
445 QVERIFY(teardownAction
);
447 QCOMPARE(m_model
->count(), m_expectedModelCount
);
449 QSignalSpy
spyItemsRemoved(m_model
, &PlacesItemModel::itemsRemoved
);
450 fakeManager()->call(QStringLiteral("unplug"), "/org/kde/solid/fakehw/volume_part1_size_993284096");
451 QTRY_COMPARE(m_model
->count(), m_expectedModelCount
- 1);
452 QCOMPARE(spyItemsRemoved
.count(), 1);
453 const QList
<QVariant
> spyItemsRemovedArgs
= spyItemsRemoved
.takeFirst();
454 const KItemRangeList removedRange
= spyItemsRemovedArgs
.at(0).value
<KItemRangeList
>();
455 QCOMPARE(removedRange
.size(), 1);
456 QCOMPARE(removedRange
.first().index
, index
);
457 QCOMPARE(removedRange
.first().count
, 1);
459 QCOMPARE(indexOf(mediaUrl
), -1);
461 QSignalSpy
spyItemsInserted(m_model
, &PlacesItemModel::itemsInserted
);
462 fakeManager()->call(QStringLiteral("plug"), "/org/kde/solid/fakehw/volume_part1_size_993284096");
463 QTRY_COMPARE(m_model
->count(), m_expectedModelCount
);
464 QCOMPARE(spyItemsInserted
.count(), 1);
465 index
= indexOf(mediaUrl
);
467 const QList
<QVariant
> args
= spyItemsInserted
.takeFirst();
468 const KItemRangeList insertedRange
= args
.at(0).value
<KItemRangeList
>();
469 QCOMPARE(insertedRange
.size(), 1);
470 QCOMPARE(insertedRange
.first().index
, index
);
471 QCOMPARE(insertedRange
.first().count
, 1);
474 void PlacesItemModelTest::testDefaultViewProperties_data()
476 QTest::addColumn
<QUrl
>("url");
477 QTest::addColumn
<DolphinView::Mode
>("expectedViewMode");
478 QTest::addColumn
<bool>("expectedPreviewShow");
479 QTest::addColumn
<QList
<QByteArray
> >("expectedVisibleRole");
482 QTest::newRow("Places - Home") << QUrl::fromLocalFile(QDir::homePath()) << DolphinView::IconsView
<< true << QList
<QByteArray
>({"text"});
485 QTest::newRow("Baloo - Documents") << QUrl("search:/documents") << DolphinView::DetailsView
<< false << QList
<QByteArray
>({"text", "path"});
488 QTest::newRow("Places - Audio") << QUrl("search:/audio") << DolphinView::DetailsView
<< false << QList
<QByteArray
>({"text", "artist", "album"});
491 QTest::newRow("Devices - Floppy") << QUrl("file:///media/floppy0") << DolphinView::IconsView
<< true << QList
<QByteArray
>({"text"});
495 void PlacesItemModelTest::testDefaultViewProperties()
498 QFETCH(DolphinView::Mode
, expectedViewMode
);
499 QFETCH(bool, expectedPreviewShow
);
500 QFETCH(QList
<QByteArray
>, expectedVisibleRole
);
502 // In order to test the default view properties, turn off the global view properties and re-init the test to reload the model.
503 GeneralSettings
* settings
= GeneralSettings::self();
504 settings
->setGlobalViewProps(false);
509 ViewProperties
properties(KFilePlacesModel::convertedUrl(url
));
510 QCOMPARE(properties
.viewMode(), expectedViewMode
);
511 QCOMPARE(properties
.previewsShown(), expectedPreviewShow
);
512 QCOMPARE(properties
.visibleRoles(), expectedVisibleRole
);
514 settings
->setGlobalViewProps(true);
518 void PlacesItemModelTest::testClear()
520 QCOMPARE(m_model
->count(), m_expectedModelCount
);
522 QCOMPARE(m_model
->count(), 0);
523 QCOMPARE(m_model
->hiddenCount(), 0);
525 QTRY_COMPARE(m_model
->count(), m_expectedModelCount
);
528 void PlacesItemModelTest::testHideItem()
530 const QUrl mediaUrl
= QUrl::fromLocalFile(QStringLiteral("/media/XO-Y4"));
531 const int index
= indexOf(mediaUrl
);
533 PlacesItem
*item
= m_model
->placesItem(index
);
535 QSignalSpy
spyItemsRemoved(m_model
, &PlacesItemModel::itemsRemoved
);
536 QList
<QVariant
> spyItemsRemovedArgs
;
537 KItemRangeList removedRange
;
539 QSignalSpy
spyItemsInserted(m_model
, &PlacesItemModel::itemsInserted
);
540 QList
<QVariant
> spyItemsInsertedArgs
;
541 KItemRangeList insertedRange
;
545 item
->setHidden(true);
547 // check if items removed was fired
548 QTRY_COMPARE(m_model
->count(), m_expectedModelCount
- 1);
549 QCOMPARE(spyItemsRemoved
.count(), 1);
550 spyItemsRemovedArgs
= spyItemsRemoved
.takeFirst();
551 removedRange
= spyItemsRemovedArgs
.at(0).value
<KItemRangeList
>();
552 QCOMPARE(removedRange
.size(), 1);
553 QCOMPARE(removedRange
.first().index
, index
);
554 QCOMPARE(removedRange
.first().count
, 1);
556 // allow model to show hidden items
557 m_model
->setHiddenItemsShown(true);
559 // check if the items inserted was fired
560 spyItemsInsertedArgs
= spyItemsInserted
.takeFirst();
561 insertedRange
= spyItemsInsertedArgs
.at(0).value
<KItemRangeList
>();
562 QCOMPARE(insertedRange
.size(), 1);
563 QCOMPARE(insertedRange
.first().index
, index
);
564 QCOMPARE(insertedRange
.first().count
, 1);
566 // mark item as visible
567 item
= m_model
->placesItem(index
);
568 item
->setHidden(false);
570 // mark model to hide invisible items
571 m_model
->setHiddenItemsShown(true);
573 QTRY_COMPARE(m_model
->count(), m_expectedModelCount
);
576 void PlacesItemModelTest::testSystemItems()
578 int tempDirIndex
= 2;
579 increaseIndexIfNeeded(tempDirIndex
);
581 QCOMPARE(m_model
->count(), m_expectedModelCount
);
582 for (int r
= 0; r
< m_model
->count(); r
++) {
583 QCOMPARE(m_model
->placesItem(r
)->isSystemItem(), !m_model
->placesItem(r
)->device().isValid());
586 QSignalSpy
itemsInsertedSpy(m_model
, &PlacesItemModel::itemsInserted
);
588 // create a new entry (non system item)
589 createPlaceItem(QStringLiteral("Temporary Dir"), QUrl::fromLocalFile(QStandardPaths::writableLocation(QStandardPaths::TempLocation
)), QString());
591 // check if the new entry was created
592 QTRY_COMPARE(itemsInsertedSpy
.count(), 1);
594 // make sure the new place get removed
595 schedulePlaceRemoval(tempDirIndex
);
597 QList
<QVariant
> args
= itemsInsertedSpy
.takeFirst();
598 KItemRangeList range
= args
.at(0).value
<KItemRangeList
>();
599 QCOMPARE(range
.first().index
, tempDirIndex
);
600 QCOMPARE(range
.first().count
, 1);
601 QVERIFY(!m_model
->placesItem(tempDirIndex
)->isSystemItem());
602 QCOMPARE(m_model
->count(), m_expectedModelCount
+ 1);
605 // check if the removal signal is correct
606 QSignalSpy
itemsRemovedSpy(m_model
, &PlacesItemModel::itemsRemoved
);
607 m_model
->deleteItem(tempDirIndex
);
608 QTRY_COMPARE(itemsRemovedSpy
.count(), 1);
609 args
= itemsRemovedSpy
.takeFirst();
610 range
= args
.at(0).value
<KItemRangeList
>();
611 QCOMPARE(range
.first().index
, tempDirIndex
);
612 QCOMPARE(range
.first().count
, 1);
613 QTRY_COMPARE(m_model
->count(), m_expectedModelCount
);
615 //cancel removal (it was removed above)
616 cancelPlaceRemoval(tempDirIndex
);
619 void PlacesItemModelTest::testEditBookmark()
621 int tempDirIndex
= 2;
622 increaseIndexIfNeeded(tempDirIndex
);
624 QScopedPointer
<PlacesItemModel
> other(new PlacesItemModel());
626 createPlaceItem(QStringLiteral("Temporary Dir"), QUrl::fromLocalFile(QStandardPaths::writableLocation(QStandardPaths::TempLocation
)), QString());
628 // make sure that the new item will be removed later
629 schedulePlaceRemoval(tempDirIndex
);
631 QSignalSpy
itemsChangedSply(m_model
, &PlacesItemModel::itemsChanged
);
634 m_model
->item(tempDirIndex
)->setText(QStringLiteral("Renamed place"));
637 // check if the correct signal was fired
638 QTRY_COMPARE(itemsChangedSply
.count(), 1);
639 QList
<QVariant
> args
= itemsChangedSply
.takeFirst();
640 KItemRangeList range
= args
.at(0).value
<KItemRangeList
>();
641 QCOMPARE(range
.first().index
, tempDirIndex
);
642 QCOMPARE(range
.first().count
, 1);
643 QSet
<QByteArray
> roles
= args
.at(1).value
<QSet
<QByteArray
> >();
644 QCOMPARE(roles
.size(), 1);
645 QCOMPARE(*roles
.begin(), QByteArrayLiteral("text"));
646 QCOMPARE(m_model
->item(tempDirIndex
)->text(), QStringLiteral("Renamed place"));
648 // check if the item was updated in the other model
649 QTRY_COMPARE(other
->item(tempDirIndex
)->text(), QStringLiteral("Renamed place"));
652 void PlacesItemModelTest::testEditAfterCreation()
654 int tempDirIndex
= 2;
655 increaseIndexIfNeeded(tempDirIndex
);
657 const QUrl tempUrl
= QUrl::fromLocalFile(QStandardPaths::writableLocation(QStandardPaths::TempLocation
));
658 QSignalSpy
itemsInsertedSpy(m_model
, &PlacesItemModel::itemsInserted
);
660 // create a new place
661 createPlaceItem(QStringLiteral("Temporary Dir"), tempUrl
, QString());
662 QTRY_COMPARE(itemsInsertedSpy
.count(), 1);
664 PlacesItemModel
*model
= new PlacesItemModel();
665 QTRY_COMPARE(model
->count(), m_model
->count());
667 // make sure that the new item will be removed later
668 schedulePlaceRemoval(tempDirIndex
);
671 PlacesItem
*item
= m_model
->placesItem(tempDirIndex
);
672 item
->setText(QStringLiteral("Renamed place"));
675 // check if the second model got the changes
676 QTRY_COMPARE(model
->count(), m_model
->count());
677 QTRY_COMPARE(model
->placesItem(tempDirIndex
)->text(), m_model
->placesItem(tempDirIndex
)->text());
678 QTRY_COMPARE(model
->placesItem(tempDirIndex
)->bookmark().metaDataItem(QStringLiteral("OnlyInApp")),
679 m_model
->placesItem(tempDirIndex
)->bookmark().metaDataItem(QStringLiteral("OnlyInApp")));
680 QTRY_COMPARE(model
->placesItem(tempDirIndex
)->icon(), m_model
->placesItem(tempDirIndex
)->icon());
681 QTRY_COMPARE(model
->placesItem(tempDirIndex
)->url(), m_model
->placesItem(tempDirIndex
)->url());
684 void PlacesItemModelTest::testEditMetadata()
686 int tempDirIndex
= 2;
687 increaseIndexIfNeeded(tempDirIndex
);
689 const QUrl tempUrl
= QUrl::fromLocalFile(QStandardPaths::writableLocation(QStandardPaths::TempLocation
));
690 QSignalSpy
itemsInsertedSpy(m_model
, &PlacesItemModel::itemsInserted
);
692 // create a new place
693 createPlaceItem(QStringLiteral("Temporary Dir"), tempUrl
, QString());
694 QTRY_COMPARE(itemsInsertedSpy
.count(), 1);
696 // check if the new entry was created
697 PlacesItemModel
*model
= new PlacesItemModel();
698 QTRY_COMPARE(model
->count(), m_model
->count());
700 // make sure that the new item will be removed later
701 schedulePlaceRemoval(tempDirIndex
);
703 // modify place metadata
704 auto bookmark
= m_model
->placesItem(tempDirIndex
)->bookmark();
705 bookmark
.setMetaDataItem(QStringLiteral("OnlyInApp"), KAboutData::applicationData().componentName());
708 // check if the place was modified in both models
709 QTRY_COMPARE(model
->placesItem(tempDirIndex
)->bookmark().metaDataItem(QStringLiteral("OnlyInApp")),
710 KAboutData::applicationData().componentName());
711 QTRY_COMPARE(model
->placesItem(tempDirIndex
)->text(), m_model
->placesItem(tempDirIndex
)->text());
712 QTRY_COMPARE(model
->placesItem(tempDirIndex
)->bookmark().metaDataItem(QStringLiteral("OnlyInApp")),
713 m_model
->placesItem(tempDirIndex
)->bookmark().metaDataItem(QStringLiteral("OnlyInApp")));
714 QTRY_COMPARE(model
->placesItem(tempDirIndex
)->icon(), m_model
->placesItem(tempDirIndex
)->icon());
715 QTRY_COMPARE(model
->placesItem(tempDirIndex
)->url(), m_model
->placesItem(tempDirIndex
)->url());
718 void PlacesItemModelTest::testRefresh()
720 int tempDirIndex
= 2;
721 increaseIndexIfNeeded(tempDirIndex
);
723 const QUrl tempUrl
= QUrl::fromLocalFile(QStandardPaths::writableLocation(QStandardPaths::TempLocation
));
724 QSignalSpy
itemsInsertedSpy(m_model
, &PlacesItemModel::itemsInserted
);
726 // create a new place
727 createPlaceItem(QStringLiteral("Temporary Dir"), tempUrl
, QString());
728 QTRY_COMPARE(itemsInsertedSpy
.count(), 1);
730 PlacesItemModel
*model
= new PlacesItemModel();
731 QTRY_COMPARE(model
->count(), m_model
->count());
733 // make sure that the new item will be removed later
734 schedulePlaceRemoval(tempDirIndex
);
736 PlacesItem
*item
= m_model
->placesItem(tempDirIndex
);
737 PlacesItem
*sameItem
= model
->placesItem(tempDirIndex
);
738 QCOMPARE(item
->text(), sameItem
->text());
741 item
->setText(QStringLiteral("Renamed place"));
743 // item from another model is not affected at the moment
744 QVERIFY(item
->text() != sameItem
->text());
749 // item must be equal
750 QTRY_COMPARE(item
->text(), sameItem
->text());
753 void PlacesItemModelTest::testIcons_data()
755 QTest::addColumn
<QUrl
>("url");
756 QTest::addColumn
<QString
>("expectedIconName");
759 QTest::newRow("Places - Home") << QUrl::fromLocalFile(QDir::homePath()) << QStringLiteral("user-home");
762 QTest::newRow("Baloo - Documents") << QUrl("search:/documents") << QStringLiteral("folder-text");
765 QTest::newRow("Devices - Floppy") << QUrl("file:///media/floppy0") << QStringLiteral("blockdevice");
768 void PlacesItemModelTest::testIcons()
771 QFETCH(QString
, expectedIconName
);
773 PlacesItem
*item
= m_model
->placesItem(indexOf(url
));
774 QCOMPARE(item
->icon(), expectedIconName
);
776 for (int r
= 0; r
< m_model
->count(); r
++) {
777 QVERIFY(!m_model
->placesItem(r
)->icon().isEmpty());
781 void PlacesItemModelTest::testDragAndDrop()
783 int lastIndex
= 1; // last index of places group
784 increaseIndexIfNeeded(lastIndex
);
786 QList
<QVariant
> args
;
787 KItemRangeList range
;
788 QStringList urls
= initialUrls();
790 QSignalSpy
itemsInsertedSpy(m_model
, &PlacesItemModel::itemsInserted
);
791 QSignalSpy
itemsRemovedSpy(m_model
, &PlacesItemModel::itemsRemoved
);
793 CHECK_PLACES_URLS(initialUrls());
794 // Move the home directory to the end of the places group
795 QMimeData
*dropData
= createMimeData(QList
<int>() << 0);
796 m_model
->dropMimeDataBefore(m_model
->count() - 1, dropData
);
797 urls
.move(0, lastIndex
);
800 QTRY_COMPARE(itemsInsertedSpy
.count(), 1);
801 QTRY_COMPARE(itemsRemovedSpy
.count(), 1);
803 // remove item from actual position
804 args
= itemsRemovedSpy
.takeFirst();
805 range
= args
.at(0).value
<KItemRangeList
>();
806 QCOMPARE(range
.size(), 1);
807 QCOMPARE(range
.at(0).count
, 1);
808 QCOMPARE(range
.at(0).index
, 0);
810 // insert intem in his group
811 args
= itemsInsertedSpy
.takeFirst();
812 range
= args
.at(0).value
<KItemRangeList
>();
813 QCOMPARE(range
.size(), 1);
814 QCOMPARE(range
.at(0).count
, 1);
815 QCOMPARE(range
.at(0).index
, lastIndex
);
817 CHECK_PLACES_URLS(urls
);
819 itemsInsertedSpy
.clear();
820 itemsRemovedSpy
.clear();
822 // Move home directory item back to its original position
823 dropData
= createMimeData(QList
<int>() << lastIndex
);
824 m_model
->dropMimeDataBefore(0, dropData
);
825 urls
.move(lastIndex
, 0);
828 QTRY_COMPARE(itemsInsertedSpy
.count(), 1);
829 QTRY_COMPARE(itemsRemovedSpy
.count(), 1);
831 // remove item from actual position
832 args
= itemsRemovedSpy
.takeFirst();
833 range
= args
.at(0).value
<KItemRangeList
>();
834 QCOMPARE(range
.size(), 1);
835 QCOMPARE(range
.at(0).count
, 1);
836 QCOMPARE(range
.at(0).index
, lastIndex
);
838 // insert intem in the requested position
839 args
= itemsInsertedSpy
.takeFirst();
840 range
= args
.at(0).value
<KItemRangeList
>();
841 QCOMPARE(range
.size(), 1);
842 QCOMPARE(range
.at(0).count
, 1);
843 QCOMPARE(range
.at(0).index
, 0);
845 CHECK_PLACES_URLS(urls
);
848 void PlacesItemModelTest::testHideDevices()
850 QSignalSpy
itemsRemoved(m_model
, &PlacesItemModel::itemsRemoved
);
851 QStringList urls
= initialUrls();
853 m_model
->setGroupHidden(KFilePlacesModel::RemovableDevicesType
, true);
854 QTRY_VERIFY(m_model
->isGroupHidden(KFilePlacesModel::RemovableDevicesType
));
855 QTRY_COMPARE(itemsRemoved
.count(), 3);
857 // remove removable-devices
858 urls
.removeOne(QStringLiteral("/media/floppy0"));
859 urls
.removeOne(QStringLiteral("/media/XO-Y4"));
860 urls
.removeOne(QStringLiteral("/media/cdrom"));
862 // check if the correct urls was removed
863 CHECK_PLACES_URLS(urls
);
866 m_model
= new PlacesItemModel();
867 QTRY_COMPARE(m_model
->count(), urls
.count());
868 CHECK_PLACES_URLS(urls
);
871 m_model
->setGroupHidden(KFilePlacesModel::RemovableDevicesType
, false);
872 urls
= initialUrls();
873 QTRY_COMPARE(m_model
->count(), urls
.count());
874 CHECK_PLACES_URLS(urls
);
877 void PlacesItemModelTest::testDuplicatedEntries()
879 QStringList urls
= initialUrls();
880 // create a duplicated entry on bookmark
881 KBookmarkManager
*bookmarkManager
= KBookmarkManager::managerForFile(bookmarksFile(), QStringLiteral("kfilePlaces"));
882 KBookmarkGroup root
= bookmarkManager
->root();
883 KBookmark bookmark
= root
.addBookmark(QStringLiteral("Duplicated Search Videos"), QUrl("search:/videos"), {});
885 const QString id
= QUuid::createUuid().toString();
886 bookmark
.setMetaDataItem(QStringLiteral("ID"), id
);
887 bookmark
.setMetaDataItem(QStringLiteral("OnlyInApp"), KAboutData::applicationData().componentName());
888 bookmarkManager
->emitChanged(bookmarkManager
->root());
890 PlacesItemModel
*newModel
= new PlacesItemModel();
891 QTRY_COMPARE(placesUrls(newModel
).count(QStringLiteral("search:/videos")), 1);
892 QTRY_COMPARE(urls
, placesUrls(newModel
));
896 void PlacesItemModelTest::renameAfterCreation()
898 int tempDirIndex
= 2;
899 increaseIndexIfNeeded(tempDirIndex
);
901 const QUrl tempUrl
= QUrl::fromLocalFile(QStandardPaths::writableLocation(QStandardPaths::TempLocation
));
902 QStringList urls
= initialUrls();
903 PlacesItemModel
*model
= new PlacesItemModel();
905 CHECK_PLACES_URLS(urls
);
906 QTRY_COMPARE(model
->count(), m_model
->count());
908 // create a new place
909 createPlaceItem(QStringLiteral("Temporary Dir"), tempUrl
, QString());
910 urls
.insert(tempDirIndex
, tempUrl
.toLocalFile());
912 // make sure that the new item will be removed later
913 schedulePlaceRemoval(tempDirIndex
);
915 CHECK_PLACES_URLS(urls
);
916 QCOMPARE(model
->count(), m_model
->count());
920 QSignalSpy
changedSpy(m_model
, &PlacesItemModel::itemsChanged
);
922 PlacesItem
*item
= m_model
->placesItem(tempDirIndex
);
923 item
->setText(QStringLiteral("New Temporary Dir"));
924 item
->setUrl(item
->url());
925 item
->setIcon(item
->icon());
928 QTRY_COMPARE(changedSpy
.count(), 1);
930 // check if the place was modified in both models
931 QTRY_COMPARE(m_model
->placesItem(tempDirIndex
)->text(), QStringLiteral("New Temporary Dir"));
932 QTRY_COMPARE(model
->placesItem(tempDirIndex
)->text(), QStringLiteral("New Temporary Dir"));
935 QTEST_MAIN(PlacesItemModelTest
)
937 #include "placesitemmodeltest.moc"