1 /***************************************************************************
2 * Copyright (C) 2017 by Renato Araujo Oliveira <renato.araujo@kdab.com> *
4 * This program is free software; you can redistribute it and/or modify *
5 * it under the terms of the GNU General Public License as published by *
6 * the Free Software Foundation; either version 2 of the License, or *
7 * (at your option) any later version. *
9 * This program is distributed in the hope that it will be useful, *
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
12 * GNU General Public License for more details. *
14 * You should have received a copy of the GNU General Public License *
15 * along with this program; if not, write to the *
16 * Free Software Foundation, Inc., *
17 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA *
18 ***************************************************************************/
22 #include <QStandardPaths>
24 #include <QDBusInterface>
26 #include <KBookmarkManager>
28 #include <KConfigGroup>
30 #include <KFilePlacesModel>
32 #include "dolphin_generalsettings.h"
33 #include "panels/places/placesitemmodel.h"
34 #include "panels/places/placesitem.h"
35 #include "views/viewproperties.h"
37 Q_DECLARE_METATYPE(KItemRangeList
)
38 Q_DECLARE_METATYPE(KItemRange
)
41 //c:\ as root for windows
42 #define KDE_ROOT_PATH "C:\\"
44 #define KDE_ROOT_PATH "/"
47 static QString
bookmarksFile()
49 return QStandardPaths::writableLocation(QStandardPaths::GenericDataLocation
) + "/user-places.xbel";
52 class PlacesItemModelTest
: public QObject
61 void cleanupTestCase();
65 void testDeletePlace();
66 void testPlaceItem_data();
68 void testTearDownDevice();
69 void testDefaultViewProperties_data();
70 void testDefaultViewProperties();
73 void testSystemItems();
74 void testEditBookmark();
75 void testEditAfterCreation();
76 void testEditMetadata();
78 void testIcons_data();
80 void testDragAndDrop();
81 void testHideDevices();
82 void testDuplicatedEntries();
83 void renameAfterCreation();
86 PlacesItemModel
* m_model
;
87 QSet
<int> m_tobeRemoved
;
88 QMap
<QString
, QDBusInterface
*> m_interfacesMap
;
89 int m_expectedModelCount
= 15;
90 bool m_hasDesktopFolder
= false;
91 bool m_hasDownloadsFolder
= false;
93 void setBalooEnabled(bool enabled
);
94 int indexOf(const QUrl
&url
);
95 QDBusInterface
*fakeManager();
96 QDBusInterface
*fakeDevice(const QString
&udi
);
97 QStringList
placesUrls(PlacesItemModel
*model
= nullptr) const;
98 QStringList
initialUrls() const;
99 void createPlaceItem(const QString
&text
, const QUrl
&url
, const QString
&icon
);
100 void schedulePlaceRemoval(int index
);
101 void cancelPlaceRemoval(int index
);
102 void removeTestUserData();
103 QMimeData
*createMimeData(const QList
<int> &indexes
) const;
106 #define CHECK_PLACES_URLS(urls) \
108 QStringList places = placesUrls(); \
109 if (places != urls) { \
110 qWarning() << "Expected:" << urls; \
111 qWarning() << "Got:" << places; \
112 QCOMPARE(places, urls); \
116 void PlacesItemModelTest::setBalooEnabled(bool enabled
)
118 KConfig
config(QStringLiteral("baloofilerc"));
119 KConfigGroup basicSettings
= config
.group("Basic Settings");
120 basicSettings
.writeEntry("Indexing-Enabled", enabled
);
124 int PlacesItemModelTest::indexOf(const QUrl
&url
)
126 for (int r
= 0; r
< m_model
->count(); r
++) {
127 if (m_model
->placesItem(r
)->url() == url
) {
134 QDBusInterface
*PlacesItemModelTest::fakeManager()
136 return fakeDevice(QStringLiteral("/org/kde/solid/fakehw"));
139 QDBusInterface
*PlacesItemModelTest::fakeDevice(const QString
&udi
)
141 if (m_interfacesMap
.contains(udi
)) {
142 return m_interfacesMap
[udi
];
145 QDBusInterface
*iface
= new QDBusInterface(QDBusConnection::sessionBus().baseService(), udi
);
146 m_interfacesMap
[udi
] = iface
;
151 QStringList
PlacesItemModelTest::placesUrls(PlacesItemModel
*model
) const
158 for (int row
= 0; row
< model
->count(); ++row
) {
159 urls
<< model
->placesItem(row
)->url().toDisplayString(QUrl::PreferLocalFile
);
164 QStringList
PlacesItemModelTest::initialUrls() const
166 static QStringList urls
;
167 if (urls
.isEmpty()) {
168 urls
<< QDir::homePath();
170 if (m_hasDesktopFolder
) {
171 urls
<< QDir::homePath() + QStringLiteral("/Desktop");
174 if (m_hasDownloadsFolder
) {
175 urls
<< QDir::homePath() + QStringLiteral("/Downloads");
178 urls
<< QStringLiteral(KDE_ROOT_PATH
) << QStringLiteral("trash:/")
179 << QStringLiteral("remote:/")
180 << QStringLiteral("/media/nfs")
181 << QStringLiteral("timeline:/today") << QStringLiteral("timeline:/yesterday")
182 << QStringLiteral("search:/documents") << QStringLiteral("search:/images") << QStringLiteral("search:/audio") << QStringLiteral("search:/videos")
183 << QStringLiteral("/foreign")
184 << QStringLiteral("/media/floppy0") << QStringLiteral("/media/XO-Y4") << QStringLiteral("/media/cdrom");
189 void PlacesItemModelTest::createPlaceItem(const QString
&text
, const QUrl
&url
, const QString
&icon
)
191 m_model
->createPlacesItem(text
, url
, icon
);
194 void PlacesItemModelTest::schedulePlaceRemoval(int index
)
196 m_tobeRemoved
.insert(index
);
199 void PlacesItemModelTest::cancelPlaceRemoval(int index
)
201 m_tobeRemoved
.remove(index
);
204 void PlacesItemModelTest::removeTestUserData()
206 // user hardcoded path to avoid removal of any user personal data
207 QDir
dir(QStringLiteral("/home/renato/.qttest/share/placesitemmodeltest"));
209 QVERIFY(dir
.removeRecursively());
213 QMimeData
*PlacesItemModelTest::createMimeData(const QList
<int> &indexes
) const
216 QDataStream
stream(&itemData
, QIODevice::WriteOnly
);
219 for (int index
: indexes
) {
220 const QUrl itemUrl
= m_model
->placesItem(index
)->url();
221 if (itemUrl
.isValid()) {
227 QMimeData
* mimeData
= new QMimeData();
228 mimeData
->setUrls(urls
);
229 // copied from PlacesItemModel::internalMimeType()
230 const QString internalMimeType
= "application/x-dolphinplacesmodel-" +
231 QString::number((qptrdiff
)m_model
);
232 mimeData
->setData(internalMimeType
, itemData
);
236 void PlacesItemModelTest::init()
238 m_model
= new PlacesItemModel();
239 // WORKAROUND: need to wait for bookmark to load
241 QCOMPARE(m_model
->count(), m_expectedModelCount
);
244 void PlacesItemModelTest::cleanup()
246 const auto tobeRemoved
= m_tobeRemoved
;
247 for (const int i
: tobeRemoved
) {
248 int before
= m_model
->count();
249 m_model
->deleteItem(i
);
250 QTRY_COMPARE(m_model
->count(), before
- 1);
252 m_tobeRemoved
.clear();
255 removeTestUserData();
258 void PlacesItemModelTest::initTestCase()
260 QStandardPaths::setTestModeEnabled(true);
261 // remove test user data
262 removeTestUserData();
264 const QString fakeHw
= QFINDTESTDATA("data/fakecomputer.xml");
265 QVERIFY(!fakeHw
.isEmpty());
266 qputenv("SOLID_FAKEHW", QFile::encodeName(fakeHw
));
268 setBalooEnabled(true);
269 const QString bookmarsFileName
= bookmarksFile();
270 if (QFileInfo::exists(bookmarsFileName
)) {
271 // Ensure we'll have a clean bookmark file to start
272 QVERIFY(QFile::remove(bookmarsFileName
));
275 if (QDir(QStandardPaths::writableLocation(QStandardPaths::DesktopLocation
)).exists()) {
276 m_hasDesktopFolder
= true;
277 m_expectedModelCount
++;
280 if (QDir(QStandardPaths::writableLocation(QStandardPaths::DownloadLocation
)).exists()) {
281 m_hasDownloadsFolder
= true;
282 m_expectedModelCount
++;
285 qRegisterMetaType
<KItemRangeList
>();
286 qRegisterMetaType
<KItemRange
>();
289 void PlacesItemModelTest::cleanupTestCase()
291 qDeleteAll(m_interfacesMap
);
292 QFile::remove(bookmarksFile());
294 // Remove any previous properties file
295 removeTestUserData();
298 void PlacesItemModelTest::testModelSort()
300 CHECK_PLACES_URLS(initialUrls());
303 void PlacesItemModelTest::testGroups()
305 const auto groups
= m_model
->groups();
306 int expectedGroupSize
= 3;
307 if (m_hasDesktopFolder
) {
310 if (m_hasDownloadsFolder
) {
314 QCOMPARE(groups
.size(), 6);
316 QCOMPARE(groups
.at(0).first
, 0);
317 QCOMPARE(groups
.at(0).second
.toString(), QStringLiteral("Places"));
319 QCOMPARE(groups
.at(1).first
, expectedGroupSize
);
320 QCOMPARE(groups
.at(1).second
.toString(), QStringLiteral("Remote"));
322 QCOMPARE(groups
.at(2).first
, expectedGroupSize
+ 2);
323 QCOMPARE(groups
.at(2).second
.toString(), QStringLiteral("Recently Saved"));
325 QCOMPARE(groups
.at(3).first
, expectedGroupSize
+ 4);
326 QCOMPARE(groups
.at(3).second
.toString(), QStringLiteral("Search For"));
328 QCOMPARE(groups
.at(4).first
, expectedGroupSize
+ 8);
329 QCOMPARE(groups
.at(4).second
.toString(), QStringLiteral("Devices"));
331 QCOMPARE(groups
.at(5).first
, expectedGroupSize
+ 9);
332 QCOMPARE(groups
.at(5).second
.toString(), QStringLiteral("Removable Devices"));
335 void PlacesItemModelTest::testPlaceItem_data()
337 QTest::addColumn
<QUrl
>("url");
338 QTest::addColumn
<bool>("expectedIsHidden");
339 QTest::addColumn
<bool>("expectedIsSystemItem");
340 QTest::addColumn
<QString
>("expectedGroup");
341 QTest::addColumn
<bool>("expectedStorageSetupNeeded");
344 QTest::newRow("Places - Home") << QUrl::fromLocalFile(QDir::homePath()) << false << true << QStringLiteral("Places") << false;
347 QTest::newRow("Baloo - Documents") << QUrl("search:/documents") << false << true << QStringLiteral("Search For") << false;
350 QTest::newRow("Baloo - Today") << QUrl("timeline:/today") << false << true << QStringLiteral("Recently Saved") << false;
353 QTest::newRow("Devices - Floppy") << QUrl("file:///media/floppy0") << false << false << QStringLiteral("Removable Devices") << false;
356 void PlacesItemModelTest::testPlaceItem()
359 QFETCH(bool, expectedIsHidden
);
360 QFETCH(bool, expectedIsSystemItem
);
361 QFETCH(QString
, expectedGroup
);
362 QFETCH(bool, expectedStorageSetupNeeded
);
364 const int index
= indexOf(url
);
365 PlacesItem
*item
= m_model
->placesItem(index
);
366 QCOMPARE(item
->url(), url
);
367 QCOMPARE(item
->isHidden(), expectedIsHidden
);
368 QCOMPARE(item
->isSystemItem(), expectedIsSystemItem
);
369 QCOMPARE(item
->group(), expectedGroup
);
370 QCOMPARE(item
->storageSetupNeeded(), expectedStorageSetupNeeded
);
373 void PlacesItemModelTest::testDeletePlace()
375 const QUrl tempUrl
= QUrl::fromLocalFile(QStandardPaths::writableLocation(QStandardPaths::TempLocation
));
376 QStringList urls
= initialUrls();
377 QSignalSpy
itemsInsertedSpy(m_model
, &PlacesItemModel::itemsInserted
);
378 QSignalSpy
itemsRemovedSpy(m_model
, &PlacesItemModel::itemsRemoved
);
380 PlacesItemModel
*model
= new PlacesItemModel();
382 int tempDirIndex
= 3;
383 if (m_hasDesktopFolder
) {
386 if (m_hasDownloadsFolder
) {
390 // create a new place
391 createPlaceItem(QStringLiteral("Temporary Dir"), tempUrl
, QString());
392 urls
.insert(tempDirIndex
, tempUrl
.toLocalFile());
394 // check if the new entry was created
395 QTRY_COMPARE(itemsInsertedSpy
.count(), 1);
396 CHECK_PLACES_URLS(urls
);
397 QTRY_COMPARE(model
->count(), m_model
->count());
400 m_model
->deleteItem(tempDirIndex
);
402 // make sure that the new item is removed
403 QTRY_COMPARE(itemsRemovedSpy
.count(), 1);
404 QTRY_COMPARE(m_model
->count(), m_expectedModelCount
);
405 CHECK_PLACES_URLS(initialUrls());
406 QTRY_COMPARE(model
->count(), m_model
->count());
409 void PlacesItemModelTest::testTearDownDevice()
411 const QUrl mediaUrl
= QUrl::fromLocalFile(QStringLiteral("/media/XO-Y4"));
412 int index
= indexOf(mediaUrl
);
413 QVERIFY(index
!= -1);
415 auto ejectAction
= m_model
->ejectAction(index
);
416 QVERIFY(!ejectAction
);
418 auto teardownAction
= m_model
->teardownAction(index
);
419 QVERIFY(teardownAction
);
421 QCOMPARE(m_model
->count(), m_expectedModelCount
);
423 QSignalSpy
spyItemsRemoved(m_model
, &PlacesItemModel::itemsRemoved
);
424 fakeManager()->call(QStringLiteral("unplug"), "/org/kde/solid/fakehw/volume_part1_size_993284096");
425 QTRY_COMPARE(m_model
->count(), m_expectedModelCount
- 1);
426 QCOMPARE(spyItemsRemoved
.count(), 1);
427 const QList
<QVariant
> spyItemsRemovedArgs
= spyItemsRemoved
.takeFirst();
428 const KItemRangeList removedRange
= spyItemsRemovedArgs
.at(0).value
<KItemRangeList
>();
429 QCOMPARE(removedRange
.size(), 1);
430 QCOMPARE(removedRange
.first().index
, index
);
431 QCOMPARE(removedRange
.first().count
, 1);
433 QCOMPARE(indexOf(mediaUrl
), -1);
435 QSignalSpy
spyItemsInserted(m_model
, &PlacesItemModel::itemsInserted
);
436 fakeManager()->call(QStringLiteral("plug"), "/org/kde/solid/fakehw/volume_part1_size_993284096");
437 QTRY_COMPARE(m_model
->count(), m_expectedModelCount
);
438 QCOMPARE(spyItemsInserted
.count(), 1);
439 index
= indexOf(mediaUrl
);
441 const QList
<QVariant
> args
= spyItemsInserted
.takeFirst();
442 const KItemRangeList insertedRange
= args
.at(0).value
<KItemRangeList
>();
443 QCOMPARE(insertedRange
.size(), 1);
444 QCOMPARE(insertedRange
.first().index
, index
);
445 QCOMPARE(insertedRange
.first().count
, 1);
448 void PlacesItemModelTest::testDefaultViewProperties_data()
450 QTest::addColumn
<QUrl
>("url");
451 QTest::addColumn
<DolphinView::Mode
>("expectedViewMode");
452 QTest::addColumn
<bool>("expectedPreviewShow");
453 QTest::addColumn
<QList
<QByteArray
> >("expectedVisibleRole");
456 QTest::newRow("Places - Home") << QUrl::fromLocalFile(QDir::homePath()) << DolphinView::IconsView
<< true << QList
<QByteArray
>({"text"});
459 QTest::newRow("Baloo - Documents") << QUrl("search:/documents") << DolphinView::DetailsView
<< false << QList
<QByteArray
>({"text", "path"});
462 QTest::newRow("Places - Audio") << QUrl("search:/audio") << DolphinView::DetailsView
<< false << QList
<QByteArray
>({"text", "artist", "album"});
465 QTest::newRow("Baloo - Today") << QUrl("timeline:/today") << DolphinView::DetailsView
<< true << QList
<QByteArray
>({"text", "modificationtime"});
468 QTest::newRow("Devices - Floppy") << QUrl("file:///media/floppy0") << DolphinView::IconsView
<< true << QList
<QByteArray
>({"text"});
472 void PlacesItemModelTest::testDefaultViewProperties()
475 QFETCH(DolphinView::Mode
, expectedViewMode
);
476 QFETCH(bool, expectedPreviewShow
);
477 QFETCH(QList
<QByteArray
>, expectedVisibleRole
);
479 // In order to test the default view properties, turn off the global view properties.
480 GeneralSettings
* settings
= GeneralSettings::self();
481 settings
->setGlobalViewProps(false);
484 ViewProperties
properties(KFilePlacesModel::convertedUrl(url
));
485 QCOMPARE(properties
.viewMode(), expectedViewMode
);
486 QCOMPARE(properties
.previewsShown(), expectedPreviewShow
);
487 QCOMPARE(properties
.visibleRoles(), expectedVisibleRole
);
489 settings
->setGlobalViewProps(true);
493 void PlacesItemModelTest::testClear()
495 QCOMPARE(m_model
->count(), m_expectedModelCount
);
497 QCOMPARE(m_model
->count(), 0);
498 QCOMPARE(m_model
->hiddenCount(), 0);
500 QTRY_COMPARE(m_model
->count(), m_expectedModelCount
);
503 void PlacesItemModelTest::testHideItem()
505 const QUrl mediaUrl
= QUrl::fromLocalFile(QStringLiteral("/media/XO-Y4"));
506 const int index
= indexOf(mediaUrl
);
508 PlacesItem
*item
= m_model
->placesItem(index
);
510 QSignalSpy
spyItemsRemoved(m_model
, &PlacesItemModel::itemsRemoved
);
511 QList
<QVariant
> spyItemsRemovedArgs
;
512 KItemRangeList removedRange
;
514 QSignalSpy
spyItemsInserted(m_model
, &PlacesItemModel::itemsInserted
);
515 QList
<QVariant
> spyItemsInsertedArgs
;
516 KItemRangeList insertedRange
;
520 item
->setHidden(true);
522 // check if items removed was fired
523 QTRY_COMPARE(m_model
->count(), m_expectedModelCount
- 1);
524 QCOMPARE(spyItemsRemoved
.count(), 1);
525 spyItemsRemovedArgs
= spyItemsRemoved
.takeFirst();
526 removedRange
= spyItemsRemovedArgs
.at(0).value
<KItemRangeList
>();
527 QCOMPARE(removedRange
.size(), 1);
528 QCOMPARE(removedRange
.first().index
, index
);
529 QCOMPARE(removedRange
.first().count
, 1);
531 // allow model to show hidden items
532 m_model
->setHiddenItemsShown(true);
534 // check if the items inserted was fired
535 spyItemsInsertedArgs
= spyItemsInserted
.takeFirst();
536 insertedRange
= spyItemsInsertedArgs
.at(0).value
<KItemRangeList
>();
537 QCOMPARE(insertedRange
.size(), 1);
538 QCOMPARE(insertedRange
.first().index
, index
);
539 QCOMPARE(insertedRange
.first().count
, 1);
541 // mark item as visible
542 item
= m_model
->placesItem(index
);
543 item
->setHidden(false);
545 // mark model to hide invisible items
546 m_model
->setHiddenItemsShown(true);
548 QTRY_COMPARE(m_model
->count(), m_expectedModelCount
);
551 void PlacesItemModelTest::testSystemItems()
553 int tempDirIndex
= 3;
554 if (m_hasDesktopFolder
) {
557 if (m_hasDownloadsFolder
) {
561 QCOMPARE(m_model
->count(), m_expectedModelCount
);
562 for (int r
= 0; r
< m_model
->count(); r
++) {
563 QCOMPARE(m_model
->placesItem(r
)->isSystemItem(), !m_model
->placesItem(r
)->device().isValid());
566 QSignalSpy
itemsInsertedSpy(m_model
, &PlacesItemModel::itemsInserted
);
568 // create a new entry (non system item)
569 createPlaceItem(QStringLiteral("Temporary Dir"), QUrl::fromLocalFile(QStandardPaths::writableLocation(QStandardPaths::TempLocation
)), QString());
571 // check if the new entry was created
572 QTRY_COMPARE(itemsInsertedSpy
.count(), 1);
574 // make sure the new place get removed
575 schedulePlaceRemoval(tempDirIndex
);
577 QList
<QVariant
> args
= itemsInsertedSpy
.takeFirst();
578 KItemRangeList range
= args
.at(0).value
<KItemRangeList
>();
579 QCOMPARE(range
.first().index
, tempDirIndex
);
580 QCOMPARE(range
.first().count
, 1);
581 QVERIFY(!m_model
->placesItem(tempDirIndex
)->isSystemItem());
582 QCOMPARE(m_model
->count(), m_expectedModelCount
+ 1);
585 // check if the removal signal is correct
586 QSignalSpy
itemsRemovedSpy(m_model
, &PlacesItemModel::itemsRemoved
);
587 m_model
->deleteItem(tempDirIndex
);
588 QTRY_COMPARE(itemsRemovedSpy
.count(), 1);
589 args
= itemsRemovedSpy
.takeFirst();
590 range
= args
.at(0).value
<KItemRangeList
>();
591 QCOMPARE(range
.first().index
, tempDirIndex
);
592 QCOMPARE(range
.first().count
, 1);
593 QTRY_COMPARE(m_model
->count(), m_expectedModelCount
);
595 //cancel removal (it was removed above)
596 cancelPlaceRemoval(tempDirIndex
);
599 void PlacesItemModelTest::testEditBookmark()
601 int tempDirIndex
= 1;
602 if (m_hasDesktopFolder
) {
605 if (m_hasDownloadsFolder
) {
609 QScopedPointer
<PlacesItemModel
> other(new PlacesItemModel());
611 createPlaceItem(QStringLiteral("Temporary Dir"), QUrl::fromLocalFile(QStandardPaths::writableLocation(QStandardPaths::TempLocation
)), QString());
613 // make sure that the new item will be removed later
614 schedulePlaceRemoval(tempDirIndex
+ 2);
616 QSignalSpy
itemsChangedSply(m_model
, &PlacesItemModel::itemsChanged
);
619 m_model
->item(tempDirIndex
)->setText(QStringLiteral("Renamed place"));
622 // check if the correct signal was fired
623 QTRY_COMPARE(itemsChangedSply
.count(), 1);
624 QList
<QVariant
> args
= itemsChangedSply
.takeFirst();
625 KItemRangeList range
= args
.at(0).value
<KItemRangeList
>();
626 QCOMPARE(range
.first().index
, tempDirIndex
);
627 QCOMPARE(range
.first().count
, 1);
628 QSet
<QByteArray
> roles
= args
.at(1).value
<QSet
<QByteArray
> >();
629 QCOMPARE(roles
.size(), 1);
630 QCOMPARE(*roles
.begin(), QByteArrayLiteral("text"));
631 QCOMPARE(m_model
->item(tempDirIndex
)->text(), QStringLiteral("Renamed place"));
633 // check if the item was updated in the other model
634 QTRY_COMPARE(other
->item(tempDirIndex
)->text(), QStringLiteral("Renamed place"));
637 void PlacesItemModelTest::testEditAfterCreation()
639 int tempDirIndex
= 1;
640 if (m_hasDesktopFolder
) {
643 if (m_hasDownloadsFolder
) {
647 const QUrl tempUrl
= QUrl::fromLocalFile(QStandardPaths::writableLocation(QStandardPaths::TempLocation
));
648 QSignalSpy
itemsInsertedSpy(m_model
, &PlacesItemModel::itemsInserted
);
650 // create a new place
651 createPlaceItem(QStringLiteral("Temporary Dir"), tempUrl
, QString());
652 QTRY_COMPARE(itemsInsertedSpy
.count(), 1);
654 PlacesItemModel
*model
= new PlacesItemModel();
655 QTRY_COMPARE(model
->count(), m_model
->count());
657 // make sure that the new item will be removed later
658 schedulePlaceRemoval(tempDirIndex
+ 2);
661 PlacesItem
*item
= m_model
->placesItem(tempDirIndex
);
662 item
->setText(QStringLiteral("Renamed place"));
665 // check if the second model got the changes
666 QTRY_COMPARE(model
->count(), m_model
->count());
667 QTRY_COMPARE(model
->placesItem(tempDirIndex
)->text(), m_model
->placesItem(tempDirIndex
)->text());
668 QTRY_COMPARE(model
->placesItem(tempDirIndex
)->bookmark().metaDataItem(QStringLiteral("OnlyInApp")),
669 m_model
->placesItem(tempDirIndex
)->bookmark().metaDataItem(QStringLiteral("OnlyInApp")));
670 QTRY_COMPARE(model
->placesItem(tempDirIndex
)->icon(), m_model
->placesItem(tempDirIndex
)->icon());
671 QTRY_COMPARE(model
->placesItem(tempDirIndex
)->url(), m_model
->placesItem(tempDirIndex
)->url());
674 void PlacesItemModelTest::testEditMetadata()
676 int tempDirIndex
= 1;
677 if (m_hasDesktopFolder
) {
680 if (m_hasDownloadsFolder
) {
684 const QUrl tempUrl
= QUrl::fromLocalFile(QStandardPaths::writableLocation(QStandardPaths::TempLocation
));
685 QSignalSpy
itemsInsertedSpy(m_model
, &PlacesItemModel::itemsInserted
);
687 // create a new place
688 createPlaceItem(QStringLiteral("Temporary Dir"), tempUrl
, QString());
689 QTRY_COMPARE(itemsInsertedSpy
.count(), 1);
691 // check if the new entry was created
692 PlacesItemModel
*model
= new PlacesItemModel();
693 QTRY_COMPARE(model
->count(), m_model
->count());
695 // make sure that the new item will be removed later
696 schedulePlaceRemoval(tempDirIndex
+ 2);
698 // modify place metadata
699 PlacesItem
*item
= m_model
->placesItem(tempDirIndex
);
700 item
->bookmark().setMetaDataItem(QStringLiteral("OnlyInApp"), KAboutData::applicationData().componentName());
703 // check if the place was modified in both models
704 QTRY_COMPARE(model
->placesItem(tempDirIndex
)->bookmark().metaDataItem(QStringLiteral("OnlyInApp")),
705 KAboutData::applicationData().componentName());
706 QTRY_COMPARE(model
->placesItem(tempDirIndex
)->text(), m_model
->placesItem(tempDirIndex
)->text());
707 QTRY_COMPARE(model
->placesItem(tempDirIndex
)->bookmark().metaDataItem(QStringLiteral("OnlyInApp")),
708 m_model
->placesItem(tempDirIndex
)->bookmark().metaDataItem(QStringLiteral("OnlyInApp")));
709 QTRY_COMPARE(model
->placesItem(tempDirIndex
)->icon(), m_model
->placesItem(tempDirIndex
)->icon());
710 QTRY_COMPARE(model
->placesItem(tempDirIndex
)->url(), m_model
->placesItem(tempDirIndex
)->url());
713 void PlacesItemModelTest::testRefresh()
715 int tempDirIndex
= 3;
716 if (m_hasDesktopFolder
) {
719 if (m_hasDownloadsFolder
) {
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("Baloo - Today") << QUrl("timeline:/today") << QStringLiteral("go-jump-today");
768 QTest::newRow("Devices - Floppy") << QUrl("file:///media/floppy0") << QStringLiteral("blockdevice");
771 void PlacesItemModelTest::testIcons()
774 QFETCH(QString
, expectedIconName
);
776 PlacesItem
*item
= m_model
->placesItem(indexOf(url
));
777 QCOMPARE(item
->icon(), expectedIconName
);
779 for (int r
= 0; r
< m_model
->count(); r
++) {
780 QVERIFY(!m_model
->placesItem(r
)->icon().isEmpty());
784 void PlacesItemModelTest::testDragAndDrop()
786 int lastIndex
= 2; // last index of places group
787 if (m_hasDesktopFolder
) {
790 if (m_hasDownloadsFolder
) {
794 QList
<QVariant
> args
;
795 KItemRangeList range
;
796 QStringList urls
= initialUrls();
797 QSignalSpy
itemsInsertedSpy(m_model
, &PlacesItemModel::itemsInserted
);
798 QSignalSpy
itemsRemovedSpy(m_model
, &PlacesItemModel::itemsRemoved
);
800 CHECK_PLACES_URLS(initialUrls());
801 // Move the home directory to the end of the places group
802 QMimeData
*dropData
= createMimeData(QList
<int>() << 0);
803 m_model
->dropMimeDataBefore(m_model
->count() - 1, dropData
);
804 urls
.move(0, lastIndex
);
807 QTRY_COMPARE(itemsInsertedSpy
.count(), 1);
808 QTRY_COMPARE(itemsRemovedSpy
.count(), 1);
810 // remove item from actual position
811 args
= itemsRemovedSpy
.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
, 0);
817 // insert intem in his group
818 args
= itemsInsertedSpy
.takeFirst();
819 range
= args
.at(0).value
<KItemRangeList
>();
820 QCOMPARE(range
.size(), 1);
821 QCOMPARE(range
.at(0).count
, 1);
822 QCOMPARE(range
.at(0).index
, lastIndex
);
824 CHECK_PLACES_URLS(urls
);
826 itemsInsertedSpy
.clear();
827 itemsRemovedSpy
.clear();
829 // Move home directory item back to its original position
830 dropData
= createMimeData(QList
<int>() << lastIndex
);
831 m_model
->dropMimeDataBefore(0, dropData
);
832 urls
.move(lastIndex
, 0);
835 QTRY_COMPARE(itemsInsertedSpy
.count(), 1);
836 QTRY_COMPARE(itemsRemovedSpy
.count(), 1);
838 // remove item from actual position
839 args
= itemsRemovedSpy
.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
, lastIndex
);
845 // insert intem in the requested position
846 args
= itemsInsertedSpy
.takeFirst();
847 range
= args
.at(0).value
<KItemRangeList
>();
848 QCOMPARE(range
.size(), 1);
849 QCOMPARE(range
.at(0).count
, 1);
850 QCOMPARE(range
.at(0).index
, 0);
852 CHECK_PLACES_URLS(urls
);
855 void PlacesItemModelTest::testHideDevices()
857 QSignalSpy
itemsRemoved(m_model
, &PlacesItemModel::itemsRemoved
);
858 QStringList urls
= initialUrls();
860 m_model
->setGroupHidden(KFilePlacesModel::RemovableDevicesType
, true);
861 QTRY_VERIFY(m_model
->isGroupHidden(KFilePlacesModel::RemovableDevicesType
));
862 QTRY_COMPARE(itemsRemoved
.count(), 3);
864 // remove removable-devices
865 urls
.removeOne(QStringLiteral("/media/floppy0"));
866 urls
.removeOne(QStringLiteral("/media/XO-Y4"));
867 urls
.removeOne(QStringLiteral("/media/cdrom"));
869 // check if the correct urls was removed
870 CHECK_PLACES_URLS(urls
);
873 m_model
= new PlacesItemModel();
874 QTRY_COMPARE(m_model
->count(), urls
.count());
875 CHECK_PLACES_URLS(urls
);
878 m_model
->setGroupHidden(KFilePlacesModel::RemovableDevicesType
, false);
879 urls
= initialUrls();
880 QTRY_COMPARE(m_model
->count(), urls
.count());
881 CHECK_PLACES_URLS(urls
);
884 void PlacesItemModelTest::testDuplicatedEntries()
886 QStringList urls
= initialUrls();
887 // create a duplicated entry on bookmark
888 KBookmarkManager
*bookmarkManager
= KBookmarkManager::managerForFile(bookmarksFile(), QStringLiteral("kfilePlaces"));
889 KBookmarkGroup root
= bookmarkManager
->root();
890 KBookmark bookmark
= root
.addBookmark(QStringLiteral("Duplicated Search Videos"), QUrl("search:/videos"), {});
892 const QString id
= QUuid::createUuid().toString();
893 bookmark
.setMetaDataItem(QStringLiteral("ID"), id
);
894 bookmark
.setMetaDataItem(QStringLiteral("OnlyInApp"), KAboutData::applicationData().componentName());
895 bookmarkManager
->emitChanged(bookmarkManager
->root());
897 PlacesItemModel
*newModel
= new PlacesItemModel();
898 QTRY_COMPARE(placesUrls(newModel
).count(QStringLiteral("search:/videos")), 1);
899 QTRY_COMPARE(urls
, placesUrls(newModel
));
903 void PlacesItemModelTest::renameAfterCreation()
905 int tempDirIndex
= 1;
906 if (m_hasDesktopFolder
) {
909 if (m_hasDownloadsFolder
) {
913 const QUrl tempUrl
= QUrl::fromLocalFile(QStandardPaths::writableLocation(QStandardPaths::TempLocation
));
914 QStringList urls
= initialUrls();
915 PlacesItemModel
*model
= new PlacesItemModel();
917 CHECK_PLACES_URLS(urls
);
918 QTRY_COMPARE(model
->count(), m_model
->count());
920 // create a new place
921 createPlaceItem(QStringLiteral("Temporary Dir"), tempUrl
, QString());
922 urls
.insert(tempDirIndex
+ 2, tempUrl
.toLocalFile());
924 // make sure that the new item will be removed later
925 schedulePlaceRemoval(tempDirIndex
+ 2);
927 CHECK_PLACES_URLS(urls
);
928 QCOMPARE(model
->count(), m_model
->count());
932 QSignalSpy
changedSpy(m_model
, &PlacesItemModel::itemsChanged
);
934 PlacesItem
*item
= m_model
->placesItem(tempDirIndex
);
935 item
->setText(QStringLiteral("New Temporary Dir"));
936 item
->setUrl(item
->url());
937 item
->setIcon(item
->icon());
940 QTRY_COMPARE(changedSpy
.count(), 1);
942 // check if the place was modified in both models
943 QTRY_COMPARE(m_model
->placesItem(tempDirIndex
)->text(), QStringLiteral("New Temporary Dir"));
944 QTRY_COMPARE(model
->placesItem(tempDirIndex
)->text(), QStringLiteral("New Temporary Dir"));
947 QTEST_MAIN(PlacesItemModelTest
)
949 #include "placesitemmodeltest.moc"