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")) ? 16 : 14;
71 bool m_hasDesktopFolder
= false;
72 bool m_hasDocumentsFolder
= false;
73 bool m_hasDownloadsFolder
= false;
75 void setBalooEnabled(bool enabled
);
76 int indexOf(const QUrl
&url
);
77 QDBusInterface
*fakeManager();
78 QDBusInterface
*fakeDevice(const QString
&udi
);
79 QStringList
placesUrls(PlacesItemModel
*model
= nullptr) const;
80 QStringList
initialUrls() const;
81 void createPlaceItem(const QString
&text
, const QUrl
&url
, const QString
&icon
);
82 void schedulePlaceRemoval(int index
);
83 void cancelPlaceRemoval(int index
);
84 QMimeData
*createMimeData(const QList
<int> &indexes
) const;
85 QTemporaryDir m_tempHomeDir
;
88 #define CHECK_PLACES_URLS(urls) \
90 QStringList places = placesUrls(); \
91 if (places != urls) { \
92 qWarning() << "Expected:" << urls; \
93 qWarning() << "Got:" << places; \
94 QCOMPARE(places, urls); \
98 void PlacesItemModelTest::setBalooEnabled(bool enabled
)
100 KConfig
config(QStringLiteral("baloofilerc"));
101 KConfigGroup basicSettings
= config
.group("Basic Settings");
102 basicSettings
.writeEntry("Indexing-Enabled", enabled
);
106 int PlacesItemModelTest::indexOf(const QUrl
&url
)
108 for (int r
= 0; r
< m_model
->count(); r
++) {
109 if (m_model
->placesItem(r
)->url() == url
) {
116 QDBusInterface
*PlacesItemModelTest::fakeManager()
118 return fakeDevice(QStringLiteral("/org/kde/solid/fakehw"));
121 QDBusInterface
*PlacesItemModelTest::fakeDevice(const QString
&udi
)
123 if (m_interfacesMap
.contains(udi
)) {
124 return m_interfacesMap
[udi
];
127 QDBusInterface
*iface
= new QDBusInterface(QDBusConnection::sessionBus().baseService(), udi
);
128 m_interfacesMap
[udi
] = iface
;
133 QStringList
PlacesItemModelTest::placesUrls(PlacesItemModel
*model
) const
140 for (int row
= 0; row
< model
->count(); ++row
) {
141 urls
<< model
->placesItem(row
)->url().toDisplayString(QUrl::PreferLocalFile
);
146 QStringList
PlacesItemModelTest::initialUrls() const
148 static QStringList urls
;
149 if (urls
.isEmpty()) {
150 urls
<< QDir::homePath();
152 if (m_hasDesktopFolder
) {
153 urls
<< QDir::homePath() + QStringLiteral("/Desktop");
156 if (m_hasDocumentsFolder
) {
157 urls
<< QDir::homePath() + QStringLiteral("/Documents");
160 if (m_hasDownloadsFolder
) {
161 urls
<< QDir::homePath() + QStringLiteral("/Downloads");
164 urls
<< QStringLiteral("trash:/")
165 << QStringLiteral("remote:/")
166 << QStringLiteral("/media/nfs");
168 if (qEnvironmentVariableIsSet("KDE_FULL_SESSION") && KProtocolInfo::isKnownProtocol(QStringLiteral("recentlyused"))) {
169 urls
<< QStringLiteral("recentlyused:/files");
170 urls
<< QStringLiteral("recentlyused:/locations");
173 urls
<< QStringLiteral("timeline:/today") << QStringLiteral("timeline:/yesterday")
174 << QStringLiteral("search:/documents") << QStringLiteral("search:/images") << QStringLiteral("search:/audio") << QStringLiteral("search:/videos")
175 << QStringLiteral("/foreign")
176 << QStringLiteral("/media/floppy0") << QStringLiteral("/media/XO-Y4") << QStringLiteral("/media/cdrom");
181 void PlacesItemModelTest::createPlaceItem(const QString
&text
, const QUrl
&url
, const QString
&icon
)
183 m_model
->createPlacesItem(text
, url
, icon
);
186 void PlacesItemModelTest::schedulePlaceRemoval(int index
)
188 m_tobeRemoved
.insert(index
);
191 void PlacesItemModelTest::cancelPlaceRemoval(int index
)
193 m_tobeRemoved
.remove(index
);
196 QMimeData
*PlacesItemModelTest::createMimeData(const QList
<int> &indexes
) const
199 QDataStream
stream(&itemData
, QIODevice::WriteOnly
);
202 for (int index
: indexes
) {
203 const QUrl itemUrl
= m_model
->placesItem(index
)->url();
204 if (itemUrl
.isValid()) {
210 QMimeData
* mimeData
= new QMimeData();
211 mimeData
->setUrls(urls
);
212 // copied from PlacesItemModel::internalMimeType()
213 const QString internalMimeType
= "application/x-dolphinplacesmodel-" +
214 QString::number((qptrdiff
)m_model
);
215 mimeData
->setData(internalMimeType
, itemData
);
219 void PlacesItemModelTest::init()
221 m_model
= new PlacesItemModel();
222 // WORKAROUND: need to wait for bookmark to load
224 QCOMPARE(m_model
->count(), m_expectedModelCount
);
227 void PlacesItemModelTest::cleanup()
229 const auto tobeRemoved
= m_tobeRemoved
;
230 for (const int i
: tobeRemoved
) {
231 int before
= m_model
->count();
232 m_model
->deleteItem(i
);
233 QTRY_COMPARE(m_model
->count(), before
- 1);
235 m_tobeRemoved
.clear();
240 void PlacesItemModelTest::initTestCase()
242 QVERIFY(m_tempHomeDir
.isValid());
243 QVERIFY(qputenv("HOME", m_tempHomeDir
.path().toUtf8()));
244 QVERIFY(qputenv("KDE_FORK_SLAVES", "yes"));
246 QStandardPaths::setTestModeEnabled(true);
248 const QString fakeHw
= QFINDTESTDATA("data/fakecomputer.xml");
249 QVERIFY(!fakeHw
.isEmpty());
250 qputenv("SOLID_FAKEHW", QFile::encodeName(fakeHw
));
252 setBalooEnabled(true);
253 const QString bookmarsFileName
= bookmarksFile();
254 if (QFileInfo::exists(bookmarsFileName
)) {
255 // Ensure we'll have a clean bookmark file to start
256 QVERIFY(QFile::remove(bookmarsFileName
));
259 if (QDir(QStandardPaths::writableLocation(QStandardPaths::DesktopLocation
)).exists()) {
260 m_hasDesktopFolder
= true;
261 m_expectedModelCount
++;
264 if (QDir(QStandardPaths::writableLocation(QStandardPaths::DocumentsLocation
)).exists()) {
265 m_hasDocumentsFolder
= true;
266 m_expectedModelCount
++;
269 if (QDir(QStandardPaths::writableLocation(QStandardPaths::DownloadLocation
)).exists()) {
270 m_hasDownloadsFolder
= true;
271 m_expectedModelCount
++;
274 qRegisterMetaType
<KItemRangeList
>();
275 qRegisterMetaType
<KItemRange
>();
278 void PlacesItemModelTest::cleanupTestCase()
280 qDeleteAll(m_interfacesMap
);
281 QFile::remove(bookmarksFile());
284 void PlacesItemModelTest::testModelSort()
286 CHECK_PLACES_URLS(initialUrls());
289 void PlacesItemModelTest::testGroups()
291 const auto groups
= m_model
->groups();
292 int expectedRemoteIndex
= 2;
293 if (m_hasDesktopFolder
) {
294 expectedRemoteIndex
++;
296 if (m_hasDocumentsFolder
) {
297 expectedRemoteIndex
++;
299 if (m_hasDownloadsFolder
) {
300 expectedRemoteIndex
++;
303 QCOMPARE(groups
.size(), 6);
305 QCOMPARE(groups
.at(0).first
, 0);
306 QCOMPARE(groups
.at(0).second
.toString(), QStringLiteral("Places"));
308 QCOMPARE(groups
.at(1).first
, expectedRemoteIndex
);
309 QCOMPARE(groups
.at(1).second
.toString(), QStringLiteral("Remote"));
311 QCOMPARE(groups
.at(2).first
, expectedRemoteIndex
+ 2);
312 QCOMPARE(groups
.at(2).second
.toString(), QStringLiteral("Recent"));
314 if (qEnvironmentVariableIsSet("KDE_FULL_SESSION") && KProtocolInfo::isKnownProtocol(QStringLiteral("recentlyused"))) {
315 expectedRemoteIndex
+= 2;
318 QCOMPARE(groups
.at(3).first
, expectedRemoteIndex
+ 4);
319 QCOMPARE(groups
.at(3).second
.toString(), QStringLiteral("Search For"));
321 QCOMPARE(groups
.at(4).first
, expectedRemoteIndex
+ 8);
322 QCOMPARE(groups
.at(4).second
.toString(), QStringLiteral("Devices"));
324 QCOMPARE(groups
.at(5).first
, expectedRemoteIndex
+ 9);
325 QCOMPARE(groups
.at(5).second
.toString(), QStringLiteral("Removable Devices"));
328 void PlacesItemModelTest::testPlaceItem_data()
330 QTest::addColumn
<QUrl
>("url");
331 QTest::addColumn
<bool>("expectedIsHidden");
332 QTest::addColumn
<bool>("expectedIsSystemItem");
333 QTest::addColumn
<QString
>("expectedGroup");
334 QTest::addColumn
<bool>("expectedStorageSetupNeeded");
337 QTest::newRow("Places - Home") << QUrl::fromLocalFile(QDir::homePath()) << false << true << QStringLiteral("Places") << false;
340 QTest::newRow("Baloo - Documents") << QUrl("search:/documents") << false << true << QStringLiteral("Search For") << false;
343 QTest::newRow("Baloo - Today") << QUrl("timeline:/today") << false << true << QStringLiteral("Recent") << false;
346 QTest::newRow("Devices - Floppy") << QUrl("file:///media/floppy0") << false << false << QStringLiteral("Removable Devices") << false;
349 void PlacesItemModelTest::testPlaceItem()
352 QFETCH(bool, expectedIsHidden
);
353 QFETCH(bool, expectedIsSystemItem
);
354 QFETCH(QString
, expectedGroup
);
355 QFETCH(bool, expectedStorageSetupNeeded
);
357 const int index
= indexOf(url
);
358 PlacesItem
*item
= m_model
->placesItem(index
);
359 QCOMPARE(item
->url(), url
);
360 QCOMPARE(item
->isHidden(), expectedIsHidden
);
361 QCOMPARE(item
->isSystemItem(), expectedIsSystemItem
);
362 QCOMPARE(item
->group(), expectedGroup
);
363 QCOMPARE(item
->storageSetupNeeded(), expectedStorageSetupNeeded
);
366 void PlacesItemModelTest::testDeletePlace()
368 const QUrl tempUrl
= QUrl::fromLocalFile(QStandardPaths::writableLocation(QStandardPaths::TempLocation
));
369 QStringList urls
= initialUrls();
370 QSignalSpy
itemsInsertedSpy(m_model
, &PlacesItemModel::itemsInserted
);
371 QSignalSpy
itemsRemovedSpy(m_model
, &PlacesItemModel::itemsRemoved
);
373 PlacesItemModel
*model
= new PlacesItemModel();
375 int tempDirIndex
= 2;
376 if (m_hasDesktopFolder
) {
379 if (m_hasDocumentsFolder
) {
382 if (m_hasDownloadsFolder
) {
386 // create a new place
387 createPlaceItem(QStringLiteral("Temporary Dir"), tempUrl
, QString());
388 urls
.insert(tempDirIndex
, tempUrl
.toLocalFile());
390 // check if the new entry was created
391 QTRY_COMPARE(itemsInsertedSpy
.count(), 1);
392 CHECK_PLACES_URLS(urls
);
393 QTRY_COMPARE(model
->count(), m_model
->count());
396 m_model
->deleteItem(tempDirIndex
);
398 // make sure that the new item is removed
399 QTRY_COMPARE(itemsRemovedSpy
.count(), 1);
400 QTRY_COMPARE(m_model
->count(), m_expectedModelCount
);
401 CHECK_PLACES_URLS(initialUrls());
402 QTRY_COMPARE(model
->count(), m_model
->count());
405 void PlacesItemModelTest::testTearDownDevice()
407 const QUrl mediaUrl
= QUrl::fromLocalFile(QStringLiteral("/media/XO-Y4"));
408 int index
= indexOf(mediaUrl
);
409 QVERIFY(index
!= -1);
411 auto ejectAction
= m_model
->ejectAction(index
);
412 QVERIFY(!ejectAction
);
414 auto teardownAction
= m_model
->teardownAction(index
);
415 QVERIFY(teardownAction
);
417 QCOMPARE(m_model
->count(), m_expectedModelCount
);
419 QSignalSpy
spyItemsRemoved(m_model
, &PlacesItemModel::itemsRemoved
);
420 fakeManager()->call(QStringLiteral("unplug"), "/org/kde/solid/fakehw/volume_part1_size_993284096");
421 QTRY_COMPARE(m_model
->count(), m_expectedModelCount
- 1);
422 QCOMPARE(spyItemsRemoved
.count(), 1);
423 const QList
<QVariant
> spyItemsRemovedArgs
= spyItemsRemoved
.takeFirst();
424 const KItemRangeList removedRange
= spyItemsRemovedArgs
.at(0).value
<KItemRangeList
>();
425 QCOMPARE(removedRange
.size(), 1);
426 QCOMPARE(removedRange
.first().index
, index
);
427 QCOMPARE(removedRange
.first().count
, 1);
429 QCOMPARE(indexOf(mediaUrl
), -1);
431 QSignalSpy
spyItemsInserted(m_model
, &PlacesItemModel::itemsInserted
);
432 fakeManager()->call(QStringLiteral("plug"), "/org/kde/solid/fakehw/volume_part1_size_993284096");
433 QTRY_COMPARE(m_model
->count(), m_expectedModelCount
);
434 QCOMPARE(spyItemsInserted
.count(), 1);
435 index
= indexOf(mediaUrl
);
437 const QList
<QVariant
> args
= spyItemsInserted
.takeFirst();
438 const KItemRangeList insertedRange
= args
.at(0).value
<KItemRangeList
>();
439 QCOMPARE(insertedRange
.size(), 1);
440 QCOMPARE(insertedRange
.first().index
, index
);
441 QCOMPARE(insertedRange
.first().count
, 1);
444 void PlacesItemModelTest::testDefaultViewProperties_data()
446 QTest::addColumn
<QUrl
>("url");
447 QTest::addColumn
<DolphinView::Mode
>("expectedViewMode");
448 QTest::addColumn
<bool>("expectedPreviewShow");
449 QTest::addColumn
<QList
<QByteArray
> >("expectedVisibleRole");
452 QTest::newRow("Places - Home") << QUrl::fromLocalFile(QDir::homePath()) << DolphinView::IconsView
<< true << QList
<QByteArray
>({"text"});
455 QTest::newRow("Baloo - Documents") << QUrl("search:/documents") << DolphinView::DetailsView
<< false << QList
<QByteArray
>({"text", "path"});
458 QTest::newRow("Places - Audio") << QUrl("search:/audio") << DolphinView::DetailsView
<< false << QList
<QByteArray
>({"text", "artist", "album"});
461 QTest::newRow("Baloo - Today") << QUrl("timeline:/today") << DolphinView::DetailsView
<< true << QList
<QByteArray
>({"text", "modificationtime"});
464 QTest::newRow("Devices - Floppy") << QUrl("file:///media/floppy0") << DolphinView::IconsView
<< true << QList
<QByteArray
>({"text"});
468 void PlacesItemModelTest::testDefaultViewProperties()
471 QFETCH(DolphinView::Mode
, expectedViewMode
);
472 QFETCH(bool, expectedPreviewShow
);
473 QFETCH(QList
<QByteArray
>, expectedVisibleRole
);
475 // In order to test the default view properties, turn off the global view properties and re-init the test to reload the model.
476 GeneralSettings
* settings
= GeneralSettings::self();
477 settings
->setGlobalViewProps(false);
482 ViewProperties
properties(KFilePlacesModel::convertedUrl(url
));
483 QCOMPARE(properties
.viewMode(), expectedViewMode
);
484 QCOMPARE(properties
.previewsShown(), expectedPreviewShow
);
485 QCOMPARE(properties
.visibleRoles(), expectedVisibleRole
);
487 settings
->setGlobalViewProps(true);
491 void PlacesItemModelTest::testClear()
493 QCOMPARE(m_model
->count(), m_expectedModelCount
);
495 QCOMPARE(m_model
->count(), 0);
496 QCOMPARE(m_model
->hiddenCount(), 0);
498 QTRY_COMPARE(m_model
->count(), m_expectedModelCount
);
501 void PlacesItemModelTest::testHideItem()
503 const QUrl mediaUrl
= QUrl::fromLocalFile(QStringLiteral("/media/XO-Y4"));
504 const int index
= indexOf(mediaUrl
);
506 PlacesItem
*item
= m_model
->placesItem(index
);
508 QSignalSpy
spyItemsRemoved(m_model
, &PlacesItemModel::itemsRemoved
);
509 QList
<QVariant
> spyItemsRemovedArgs
;
510 KItemRangeList removedRange
;
512 QSignalSpy
spyItemsInserted(m_model
, &PlacesItemModel::itemsInserted
);
513 QList
<QVariant
> spyItemsInsertedArgs
;
514 KItemRangeList insertedRange
;
518 item
->setHidden(true);
520 // check if items removed was fired
521 QTRY_COMPARE(m_model
->count(), m_expectedModelCount
- 1);
522 QCOMPARE(spyItemsRemoved
.count(), 1);
523 spyItemsRemovedArgs
= spyItemsRemoved
.takeFirst();
524 removedRange
= spyItemsRemovedArgs
.at(0).value
<KItemRangeList
>();
525 QCOMPARE(removedRange
.size(), 1);
526 QCOMPARE(removedRange
.first().index
, index
);
527 QCOMPARE(removedRange
.first().count
, 1);
529 // allow model to show hidden items
530 m_model
->setHiddenItemsShown(true);
532 // check if the items inserted was fired
533 spyItemsInsertedArgs
= spyItemsInserted
.takeFirst();
534 insertedRange
= spyItemsInsertedArgs
.at(0).value
<KItemRangeList
>();
535 QCOMPARE(insertedRange
.size(), 1);
536 QCOMPARE(insertedRange
.first().index
, index
);
537 QCOMPARE(insertedRange
.first().count
, 1);
539 // mark item as visible
540 item
= m_model
->placesItem(index
);
541 item
->setHidden(false);
543 // mark model to hide invisible items
544 m_model
->setHiddenItemsShown(true);
546 QTRY_COMPARE(m_model
->count(), m_expectedModelCount
);
549 void PlacesItemModelTest::testSystemItems()
551 int tempDirIndex
= 2;
552 if (m_hasDesktopFolder
) {
555 if (m_hasDocumentsFolder
) {
558 if (m_hasDownloadsFolder
) {
562 QCOMPARE(m_model
->count(), m_expectedModelCount
);
563 for (int r
= 0; r
< m_model
->count(); r
++) {
564 QCOMPARE(m_model
->placesItem(r
)->isSystemItem(), !m_model
->placesItem(r
)->device().isValid());
567 QSignalSpy
itemsInsertedSpy(m_model
, &PlacesItemModel::itemsInserted
);
569 // create a new entry (non system item)
570 createPlaceItem(QStringLiteral("Temporary Dir"), QUrl::fromLocalFile(QStandardPaths::writableLocation(QStandardPaths::TempLocation
)), QString());
572 // check if the new entry was created
573 QTRY_COMPARE(itemsInsertedSpy
.count(), 1);
575 // make sure the new place get removed
576 schedulePlaceRemoval(tempDirIndex
);
578 QList
<QVariant
> args
= itemsInsertedSpy
.takeFirst();
579 KItemRangeList range
= args
.at(0).value
<KItemRangeList
>();
580 QCOMPARE(range
.first().index
, tempDirIndex
);
581 QCOMPARE(range
.first().count
, 1);
582 QVERIFY(!m_model
->placesItem(tempDirIndex
)->isSystemItem());
583 QCOMPARE(m_model
->count(), m_expectedModelCount
+ 1);
586 // check if the removal signal is correct
587 QSignalSpy
itemsRemovedSpy(m_model
, &PlacesItemModel::itemsRemoved
);
588 m_model
->deleteItem(tempDirIndex
);
589 QTRY_COMPARE(itemsRemovedSpy
.count(), 1);
590 args
= itemsRemovedSpy
.takeFirst();
591 range
= args
.at(0).value
<KItemRangeList
>();
592 QCOMPARE(range
.first().index
, tempDirIndex
);
593 QCOMPARE(range
.first().count
, 1);
594 QTRY_COMPARE(m_model
->count(), m_expectedModelCount
);
596 //cancel removal (it was removed above)
597 cancelPlaceRemoval(tempDirIndex
);
600 void PlacesItemModelTest::testEditBookmark()
602 int tempDirIndex
= 2;
603 if (m_hasDesktopFolder
) {
606 if (m_hasDocumentsFolder
) {
609 if (m_hasDownloadsFolder
) {
613 QScopedPointer
<PlacesItemModel
> other(new PlacesItemModel());
615 createPlaceItem(QStringLiteral("Temporary Dir"), QUrl::fromLocalFile(QStandardPaths::writableLocation(QStandardPaths::TempLocation
)), QString());
617 // make sure that the new item will be removed later
618 schedulePlaceRemoval(tempDirIndex
);
620 QSignalSpy
itemsChangedSply(m_model
, &PlacesItemModel::itemsChanged
);
623 m_model
->item(tempDirIndex
)->setText(QStringLiteral("Renamed place"));
626 // check if the correct signal was fired
627 QTRY_COMPARE(itemsChangedSply
.count(), 1);
628 QList
<QVariant
> args
= itemsChangedSply
.takeFirst();
629 KItemRangeList range
= args
.at(0).value
<KItemRangeList
>();
630 QCOMPARE(range
.first().index
, tempDirIndex
);
631 QCOMPARE(range
.first().count
, 1);
632 QSet
<QByteArray
> roles
= args
.at(1).value
<QSet
<QByteArray
> >();
633 QCOMPARE(roles
.size(), 1);
634 QCOMPARE(*roles
.begin(), QByteArrayLiteral("text"));
635 QCOMPARE(m_model
->item(tempDirIndex
)->text(), QStringLiteral("Renamed place"));
637 // check if the item was updated in the other model
638 QTRY_COMPARE(other
->item(tempDirIndex
)->text(), QStringLiteral("Renamed place"));
641 void PlacesItemModelTest::testEditAfterCreation()
643 int tempDirIndex
= 2;
644 if (m_hasDesktopFolder
) {
647 if (m_hasDocumentsFolder
) {
650 if (m_hasDownloadsFolder
) {
654 const QUrl tempUrl
= QUrl::fromLocalFile(QStandardPaths::writableLocation(QStandardPaths::TempLocation
));
655 QSignalSpy
itemsInsertedSpy(m_model
, &PlacesItemModel::itemsInserted
);
657 // create a new place
658 createPlaceItem(QStringLiteral("Temporary Dir"), tempUrl
, QString());
659 QTRY_COMPARE(itemsInsertedSpy
.count(), 1);
661 PlacesItemModel
*model
= new PlacesItemModel();
662 QTRY_COMPARE(model
->count(), m_model
->count());
664 // make sure that the new item will be removed later
665 schedulePlaceRemoval(tempDirIndex
);
668 PlacesItem
*item
= m_model
->placesItem(tempDirIndex
);
669 item
->setText(QStringLiteral("Renamed place"));
672 // check if the second model got the changes
673 QTRY_COMPARE(model
->count(), m_model
->count());
674 QTRY_COMPARE(model
->placesItem(tempDirIndex
)->text(), m_model
->placesItem(tempDirIndex
)->text());
675 QTRY_COMPARE(model
->placesItem(tempDirIndex
)->bookmark().metaDataItem(QStringLiteral("OnlyInApp")),
676 m_model
->placesItem(tempDirIndex
)->bookmark().metaDataItem(QStringLiteral("OnlyInApp")));
677 QTRY_COMPARE(model
->placesItem(tempDirIndex
)->icon(), m_model
->placesItem(tempDirIndex
)->icon());
678 QTRY_COMPARE(model
->placesItem(tempDirIndex
)->url(), m_model
->placesItem(tempDirIndex
)->url());
681 void PlacesItemModelTest::testEditMetadata()
683 int tempDirIndex
= 2;
684 if (m_hasDesktopFolder
) {
687 if (m_hasDocumentsFolder
) {
690 if (m_hasDownloadsFolder
) {
694 const QUrl tempUrl
= QUrl::fromLocalFile(QStandardPaths::writableLocation(QStandardPaths::TempLocation
));
695 QSignalSpy
itemsInsertedSpy(m_model
, &PlacesItemModel::itemsInserted
);
697 // create a new place
698 createPlaceItem(QStringLiteral("Temporary Dir"), tempUrl
, QString());
699 QTRY_COMPARE(itemsInsertedSpy
.count(), 1);
701 // check if the new entry was created
702 PlacesItemModel
*model
= new PlacesItemModel();
703 QTRY_COMPARE(model
->count(), m_model
->count());
705 // make sure that the new item will be removed later
706 schedulePlaceRemoval(tempDirIndex
);
708 // modify place metadata
709 auto bookmark
= m_model
->placesItem(tempDirIndex
)->bookmark();
710 bookmark
.setMetaDataItem(QStringLiteral("OnlyInApp"), KAboutData::applicationData().componentName());
713 // check if the place was modified in both models
714 QTRY_COMPARE(model
->placesItem(tempDirIndex
)->bookmark().metaDataItem(QStringLiteral("OnlyInApp")),
715 KAboutData::applicationData().componentName());
716 QTRY_COMPARE(model
->placesItem(tempDirIndex
)->text(), m_model
->placesItem(tempDirIndex
)->text());
717 QTRY_COMPARE(model
->placesItem(tempDirIndex
)->bookmark().metaDataItem(QStringLiteral("OnlyInApp")),
718 m_model
->placesItem(tempDirIndex
)->bookmark().metaDataItem(QStringLiteral("OnlyInApp")));
719 QTRY_COMPARE(model
->placesItem(tempDirIndex
)->icon(), m_model
->placesItem(tempDirIndex
)->icon());
720 QTRY_COMPARE(model
->placesItem(tempDirIndex
)->url(), m_model
->placesItem(tempDirIndex
)->url());
723 void PlacesItemModelTest::testRefresh()
725 int tempDirIndex
= 2;
726 if (m_hasDesktopFolder
) {
729 if (m_hasDocumentsFolder
) {
732 if (m_hasDownloadsFolder
) {
736 const QUrl tempUrl
= QUrl::fromLocalFile(QStandardPaths::writableLocation(QStandardPaths::TempLocation
));
737 QSignalSpy
itemsInsertedSpy(m_model
, &PlacesItemModel::itemsInserted
);
739 // create a new place
740 createPlaceItem(QStringLiteral("Temporary Dir"), tempUrl
, QString());
741 QTRY_COMPARE(itemsInsertedSpy
.count(), 1);
743 PlacesItemModel
*model
= new PlacesItemModel();
744 QTRY_COMPARE(model
->count(), m_model
->count());
746 // make sure that the new item will be removed later
747 schedulePlaceRemoval(tempDirIndex
);
749 PlacesItem
*item
= m_model
->placesItem(tempDirIndex
);
750 PlacesItem
*sameItem
= model
->placesItem(tempDirIndex
);
751 QCOMPARE(item
->text(), sameItem
->text());
754 item
->setText(QStringLiteral("Renamed place"));
756 // item from another model is not affected at the moment
757 QVERIFY(item
->text() != sameItem
->text());
762 // item must be equal
763 QTRY_COMPARE(item
->text(), sameItem
->text());
766 void PlacesItemModelTest::testIcons_data()
768 QTest::addColumn
<QUrl
>("url");
769 QTest::addColumn
<QString
>("expectedIconName");
772 QTest::newRow("Places - Home") << QUrl::fromLocalFile(QDir::homePath()) << QStringLiteral("user-home");
775 QTest::newRow("Baloo - Documents") << QUrl("search:/documents") << QStringLiteral("folder-text");
778 QTest::newRow("Baloo - Today") << QUrl("timeline:/today") << QStringLiteral("go-jump-today");
781 QTest::newRow("Devices - Floppy") << QUrl("file:///media/floppy0") << QStringLiteral("blockdevice");
784 void PlacesItemModelTest::testIcons()
787 QFETCH(QString
, expectedIconName
);
789 PlacesItem
*item
= m_model
->placesItem(indexOf(url
));
790 QCOMPARE(item
->icon(), expectedIconName
);
792 for (int r
= 0; r
< m_model
->count(); r
++) {
793 QVERIFY(!m_model
->placesItem(r
)->icon().isEmpty());
797 void PlacesItemModelTest::testDragAndDrop()
799 int lastIndex
= 1; // last index of places group
800 if (m_hasDesktopFolder
) {
803 if (m_hasDocumentsFolder
) {
806 if (m_hasDownloadsFolder
) {
810 QList
<QVariant
> args
;
811 KItemRangeList range
;
812 QStringList urls
= initialUrls();
814 QSignalSpy
itemsInsertedSpy(m_model
, &PlacesItemModel::itemsInserted
);
815 QSignalSpy
itemsRemovedSpy(m_model
, &PlacesItemModel::itemsRemoved
);
817 CHECK_PLACES_URLS(initialUrls());
818 // Move the home directory to the end of the places group
819 QMimeData
*dropData
= createMimeData(QList
<int>() << 0);
820 m_model
->dropMimeDataBefore(m_model
->count() - 1, dropData
);
821 urls
.move(0, lastIndex
);
824 QTRY_COMPARE(itemsInsertedSpy
.count(), 1);
825 QTRY_COMPARE(itemsRemovedSpy
.count(), 1);
827 // remove item from actual position
828 args
= itemsRemovedSpy
.takeFirst();
829 range
= args
.at(0).value
<KItemRangeList
>();
830 QCOMPARE(range
.size(), 1);
831 QCOMPARE(range
.at(0).count
, 1);
832 QCOMPARE(range
.at(0).index
, 0);
834 // insert intem in his group
835 args
= itemsInsertedSpy
.takeFirst();
836 range
= args
.at(0).value
<KItemRangeList
>();
837 QCOMPARE(range
.size(), 1);
838 QCOMPARE(range
.at(0).count
, 1);
839 QCOMPARE(range
.at(0).index
, lastIndex
);
841 CHECK_PLACES_URLS(urls
);
843 itemsInsertedSpy
.clear();
844 itemsRemovedSpy
.clear();
846 // Move home directory item back to its original position
847 dropData
= createMimeData(QList
<int>() << lastIndex
);
848 m_model
->dropMimeDataBefore(0, dropData
);
849 urls
.move(lastIndex
, 0);
852 QTRY_COMPARE(itemsInsertedSpy
.count(), 1);
853 QTRY_COMPARE(itemsRemovedSpy
.count(), 1);
855 // remove item from actual position
856 args
= itemsRemovedSpy
.takeFirst();
857 range
= args
.at(0).value
<KItemRangeList
>();
858 QCOMPARE(range
.size(), 1);
859 QCOMPARE(range
.at(0).count
, 1);
860 QCOMPARE(range
.at(0).index
, lastIndex
);
862 // insert intem in the requested position
863 args
= itemsInsertedSpy
.takeFirst();
864 range
= args
.at(0).value
<KItemRangeList
>();
865 QCOMPARE(range
.size(), 1);
866 QCOMPARE(range
.at(0).count
, 1);
867 QCOMPARE(range
.at(0).index
, 0);
869 CHECK_PLACES_URLS(urls
);
872 void PlacesItemModelTest::testHideDevices()
874 QSignalSpy
itemsRemoved(m_model
, &PlacesItemModel::itemsRemoved
);
875 QStringList urls
= initialUrls();
877 m_model
->setGroupHidden(KFilePlacesModel::RemovableDevicesType
, true);
878 QTRY_VERIFY(m_model
->isGroupHidden(KFilePlacesModel::RemovableDevicesType
));
879 QTRY_COMPARE(itemsRemoved
.count(), 3);
881 // remove removable-devices
882 urls
.removeOne(QStringLiteral("/media/floppy0"));
883 urls
.removeOne(QStringLiteral("/media/XO-Y4"));
884 urls
.removeOne(QStringLiteral("/media/cdrom"));
886 // check if the correct urls was removed
887 CHECK_PLACES_URLS(urls
);
890 m_model
= new PlacesItemModel();
891 QTRY_COMPARE(m_model
->count(), urls
.count());
892 CHECK_PLACES_URLS(urls
);
895 m_model
->setGroupHidden(KFilePlacesModel::RemovableDevicesType
, false);
896 urls
= initialUrls();
897 QTRY_COMPARE(m_model
->count(), urls
.count());
898 CHECK_PLACES_URLS(urls
);
901 void PlacesItemModelTest::testDuplicatedEntries()
903 QStringList urls
= initialUrls();
904 // create a duplicated entry on bookmark
905 KBookmarkManager
*bookmarkManager
= KBookmarkManager::managerForFile(bookmarksFile(), QStringLiteral("kfilePlaces"));
906 KBookmarkGroup root
= bookmarkManager
->root();
907 KBookmark bookmark
= root
.addBookmark(QStringLiteral("Duplicated Search Videos"), QUrl("search:/videos"), {});
909 const QString id
= QUuid::createUuid().toString();
910 bookmark
.setMetaDataItem(QStringLiteral("ID"), id
);
911 bookmark
.setMetaDataItem(QStringLiteral("OnlyInApp"), KAboutData::applicationData().componentName());
912 bookmarkManager
->emitChanged(bookmarkManager
->root());
914 PlacesItemModel
*newModel
= new PlacesItemModel();
915 QTRY_COMPARE(placesUrls(newModel
).count(QStringLiteral("search:/videos")), 1);
916 QTRY_COMPARE(urls
, placesUrls(newModel
));
920 void PlacesItemModelTest::renameAfterCreation()
922 int tempDirIndex
= 2;
923 if (m_hasDesktopFolder
) {
926 if (m_hasDocumentsFolder
) {
929 if (m_hasDownloadsFolder
) {
933 const QUrl tempUrl
= QUrl::fromLocalFile(QStandardPaths::writableLocation(QStandardPaths::TempLocation
));
934 QStringList urls
= initialUrls();
935 PlacesItemModel
*model
= new PlacesItemModel();
937 CHECK_PLACES_URLS(urls
);
938 QTRY_COMPARE(model
->count(), m_model
->count());
940 // create a new place
941 createPlaceItem(QStringLiteral("Temporary Dir"), tempUrl
, QString());
942 urls
.insert(tempDirIndex
, tempUrl
.toLocalFile());
944 // make sure that the new item will be removed later
945 schedulePlaceRemoval(tempDirIndex
);
947 CHECK_PLACES_URLS(urls
);
948 QCOMPARE(model
->count(), m_model
->count());
952 QSignalSpy
changedSpy(m_model
, &PlacesItemModel::itemsChanged
);
954 PlacesItem
*item
= m_model
->placesItem(tempDirIndex
);
955 item
->setText(QStringLiteral("New Temporary Dir"));
956 item
->setUrl(item
->url());
957 item
->setIcon(item
->icon());
960 QTRY_COMPARE(changedSpy
.count(), 1);
962 // check if the place was modified in both models
963 QTRY_COMPARE(m_model
->placesItem(tempDirIndex
)->text(), QStringLiteral("New Temporary Dir"));
964 QTRY_COMPARE(model
->placesItem(tempDirIndex
)->text(), QStringLiteral("New Temporary Dir"));
967 QTEST_MAIN(PlacesItemModelTest
)
969 #include "placesitemmodeltest.moc"