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 "panels/places/placesitemmodel.h"
33 #include "panels/places/placesitem.h"
34 #include "views/viewproperties.h"
36 Q_DECLARE_METATYPE(KItemRangeList
)
37 Q_DECLARE_METATYPE(KItemRange
)
40 //c:\ as root for windows
41 #define KDE_ROOT_PATH "C:\\"
43 #define KDE_ROOT_PATH "/"
48 constexpr int TIMEOUT
= 10000;
51 static QString
bookmarksFile()
53 return QStandardPaths::writableLocation(QStandardPaths::GenericDataLocation
) + "/user-places.xbel";
56 class PlacesItemModelTest
: public QObject
65 void cleanupTestCase();
69 void testDeletePlace();
70 void testPlaceItem_data();
72 void testTearDownDevice();
73 void testDefaultViewProperties_data();
74 void testDefaultViewProperties();
77 void testSystemItems();
78 void testEditBookmark();
79 void testEditAfterCreation();
80 void testEditMetadata();
82 void testIcons_data();
84 void testDragAndDrop();
85 void testHideDevices();
86 void testDuplicatedEntries();
87 void renameAfterCreation();
90 PlacesItemModel
* m_model
;
91 QSet
<int> m_tobeRemoved
;
92 QMap
<QString
, QDBusInterface
*> m_interfacesMap
;
93 int m_expectedModelCount
= 15;
94 bool m_hasDesktopFolder
= false;
95 bool m_hasDownloadsFolder
= false;
97 void setBalooEnabled(bool enabled
);
98 int indexOf(const QUrl
&url
);
99 QDBusInterface
*fakeManager();
100 QDBusInterface
*fakeDevice(const QString
&udi
);
101 QStringList
placesUrls(PlacesItemModel
*model
= nullptr) const;
102 QStringList
initialUrls() const;
103 void createPlaceItem(const QString
&text
, const QUrl
&url
, const QString
&icon
);
104 void schedulePlaceRemoval(int index
);
105 void cancelPlaceRemoval(int index
);
106 void removeTestUserData();
107 QMimeData
*createMimeData(const QList
<int> &indexes
) const;
110 #define CHECK_PLACES_URLS(urls) \
112 QStringList places = placesUrls(); \
113 if (places != urls) { \
114 qWarning() << "Expected:" << urls; \
115 qWarning() << "Got:" << places; \
116 QCOMPARE(places, urls); \
120 void PlacesItemModelTest::setBalooEnabled(bool enabled
)
122 KConfig
config(QStringLiteral("baloofilerc"));
123 KConfigGroup basicSettings
= config
.group("Basic Settings");
124 basicSettings
.writeEntry("Indexing-Enabled", enabled
);
128 int PlacesItemModelTest::indexOf(const QUrl
&url
)
130 for (int r
= 0; r
< m_model
->count(); r
++) {
131 if (m_model
->placesItem(r
)->url() == url
) {
138 QDBusInterface
*PlacesItemModelTest::fakeManager()
140 return fakeDevice(QStringLiteral("/org/kde/solid/fakehw"));
143 QDBusInterface
*PlacesItemModelTest::fakeDevice(const QString
&udi
)
145 if (m_interfacesMap
.contains(udi
)) {
146 return m_interfacesMap
[udi
];
149 QDBusInterface
*iface
= new QDBusInterface(QDBusConnection::sessionBus().baseService(), udi
);
150 m_interfacesMap
[udi
] = iface
;
155 QStringList
PlacesItemModelTest::placesUrls(PlacesItemModel
*model
) const
162 for (int row
= 0; row
< model
->count(); ++row
) {
163 urls
<< model
->placesItem(row
)->url().toDisplayString(QUrl::PreferLocalFile
);
168 QStringList
PlacesItemModelTest::initialUrls() const
170 static QStringList urls
;
171 if (urls
.isEmpty()) {
172 urls
<< QDir::homePath();
174 if (m_hasDesktopFolder
) {
175 urls
<< QDir::homePath() + QStringLiteral("/Desktop");
178 if (m_hasDownloadsFolder
) {
179 urls
<< QDir::homePath() + QStringLiteral("/Downloads");
182 urls
<< QStringLiteral(KDE_ROOT_PATH
) << QStringLiteral("trash:/")
183 << QStringLiteral("remote:/")
184 << QStringLiteral("/media/nfs")
185 << QStringLiteral("timeline:/today") << QStringLiteral("timeline:/yesterday")
186 << QStringLiteral("search:/documents") << QStringLiteral("search:/images") << QStringLiteral("search:/audio") << QStringLiteral("search:/videos")
187 << QStringLiteral("/foreign")
188 << QStringLiteral("/media/floppy0") << QStringLiteral("/media/XO-Y4") << QStringLiteral("/media/cdrom");
193 void PlacesItemModelTest::createPlaceItem(const QString
&text
, const QUrl
&url
, const QString
&icon
)
195 m_model
->createPlacesItem(text
, url
, icon
);
198 void PlacesItemModelTest::schedulePlaceRemoval(int index
)
200 m_tobeRemoved
.insert(index
);
203 void PlacesItemModelTest::cancelPlaceRemoval(int index
)
205 m_tobeRemoved
.remove(index
);
208 void PlacesItemModelTest::removeTestUserData()
210 // user hardcoded path to avoid removal of any user personal data
211 QDir
dir(QStringLiteral("/home/renato/.qttest/share/placesitemmodeltest"));
213 QVERIFY(dir
.removeRecursively());
217 QMimeData
*PlacesItemModelTest::createMimeData(const QList
<int> &indexes
) const
220 QDataStream
stream(&itemData
, QIODevice::WriteOnly
);
223 for (int index
: indexes
) {
224 const QUrl itemUrl
= m_model
->placesItem(index
)->url();
225 if (itemUrl
.isValid()) {
231 QMimeData
* mimeData
= new QMimeData();
232 mimeData
->setUrls(urls
);
233 // copied from PlacesItemModel::internalMimeType()
234 const QString internalMimeType
= "application/x-dolphinplacesmodel-" +
235 QString::number((qptrdiff
)m_model
);
236 mimeData
->setData(internalMimeType
, itemData
);
240 void PlacesItemModelTest::init()
242 m_model
= new PlacesItemModel();
243 // WORKAROUND: need to wait for bookmark to load
245 QCOMPARE(m_model
->count(), m_expectedModelCount
);
248 void PlacesItemModelTest::cleanup()
250 const auto tobeRemoved
= m_tobeRemoved
;
251 for (const int i
: tobeRemoved
) {
252 int before
= m_model
->count();
253 m_model
->deleteItem(i
);
254 QTRY_COMPARE(m_model
->count(), before
- 1);
256 m_tobeRemoved
.clear();
259 removeTestUserData();
262 void PlacesItemModelTest::initTestCase()
264 QStandardPaths::setTestModeEnabled(true);
265 // remove test user data
266 removeTestUserData();
268 const QString fakeHw
= QFINDTESTDATA("data/fakecomputer.xml");
269 QVERIFY(!fakeHw
.isEmpty());
270 qputenv("SOLID_FAKEHW", QFile::encodeName(fakeHw
));
272 setBalooEnabled(true);
273 const QString bookmarsFileName
= bookmarksFile();
274 if (QFileInfo::exists(bookmarsFileName
)) {
275 // Ensure we'll have a clean bookmark file to start
276 QVERIFY(QFile::remove(bookmarsFileName
));
279 if (QDir(QStandardPaths::writableLocation(QStandardPaths::DesktopLocation
)).exists()) {
280 m_hasDesktopFolder
= true;
281 m_expectedModelCount
++;
284 if (QDir(QStandardPaths::writableLocation(QStandardPaths::DownloadLocation
)).exists()) {
285 m_hasDownloadsFolder
= true;
286 m_expectedModelCount
++;
289 qRegisterMetaType
<KItemRangeList
>();
290 qRegisterMetaType
<KItemRange
>();
293 void PlacesItemModelTest::cleanupTestCase()
295 qDeleteAll(m_interfacesMap
);
296 QFile::remove(bookmarksFile());
298 // Remove any previous properties file
299 removeTestUserData();
302 void PlacesItemModelTest::testModelSort()
304 CHECK_PLACES_URLS(initialUrls());
307 void PlacesItemModelTest::testGroups()
309 const auto groups
= m_model
->groups();
310 int expectedGroupSize
= 3;
311 if (m_hasDesktopFolder
) {
314 if (m_hasDownloadsFolder
) {
318 QCOMPARE(groups
.size(), 6);
320 QCOMPARE(groups
.at(0).first
, 0);
321 QCOMPARE(groups
.at(0).second
.toString(), QStringLiteral("Places"));
323 QCOMPARE(groups
.at(1).first
, expectedGroupSize
);
324 QCOMPARE(groups
.at(1).second
.toString(), QStringLiteral("Remote"));
326 QCOMPARE(groups
.at(2).first
, expectedGroupSize
+ 2);
327 QCOMPARE(groups
.at(2).second
.toString(), QStringLiteral("Recently Saved"));
329 QCOMPARE(groups
.at(3).first
, expectedGroupSize
+ 4);
330 QCOMPARE(groups
.at(3).second
.toString(), QStringLiteral("Search For"));
332 QCOMPARE(groups
.at(4).first
, expectedGroupSize
+ 8);
333 QCOMPARE(groups
.at(4).second
.toString(), QStringLiteral("Devices"));
335 QCOMPARE(groups
.at(5).first
, expectedGroupSize
+ 9);
336 QCOMPARE(groups
.at(5).second
.toString(), QStringLiteral("Removable Devices"));
339 void PlacesItemModelTest::testPlaceItem_data()
341 QTest::addColumn
<QUrl
>("url");
342 QTest::addColumn
<bool>("expectedIsHidden");
343 QTest::addColumn
<bool>("expectedIsSystemItem");
344 QTest::addColumn
<QString
>("expectedGroup");
345 QTest::addColumn
<bool>("expectedStorageSetupNeeded");
348 QTest::newRow("Places - Home") << QUrl::fromLocalFile(QDir::homePath()) << false << true << QStringLiteral("Places") << false;
351 QTest::newRow("Baloo - Documents") << QUrl("search:/documents") << false << true << QStringLiteral("Search For") << false;
354 QTest::newRow("Baloo - Today") << QUrl("timeline:/today") << false << true << QStringLiteral("Recently Saved") << false;
357 QTest::newRow("Devices - Floppy") << QUrl("file:///media/floppy0") << false << false << QStringLiteral("Removable Devices") << false;
360 void PlacesItemModelTest::testPlaceItem()
363 QFETCH(bool, expectedIsHidden
);
364 QFETCH(bool, expectedIsSystemItem
);
365 QFETCH(QString
, expectedGroup
);
366 QFETCH(bool, expectedStorageSetupNeeded
);
368 const int index
= indexOf(url
);
369 PlacesItem
*item
= m_model
->placesItem(index
);
370 QCOMPARE(item
->url(), url
);
371 QCOMPARE(item
->isHidden(), expectedIsHidden
);
372 QCOMPARE(item
->isSystemItem(), expectedIsSystemItem
);
373 QCOMPARE(item
->group(), expectedGroup
);
374 QCOMPARE(item
->storageSetupNeeded(), expectedStorageSetupNeeded
);
377 void PlacesItemModelTest::testDeletePlace()
379 const QUrl tempUrl
= QUrl::fromLocalFile(QStandardPaths::writableLocation(QStandardPaths::TempLocation
));
380 QStringList urls
= initialUrls();
381 QSignalSpy
itemsInsertedSpy(m_model
, &PlacesItemModel::itemsInserted
);
382 QSignalSpy
itemsRemovedSpy(m_model
, &PlacesItemModel::itemsRemoved
);
384 PlacesItemModel
*model
= new PlacesItemModel();
386 int tempDirIndex
= 3;
387 if (m_hasDesktopFolder
) {
390 if (m_hasDownloadsFolder
) {
394 // create a new place
395 createPlaceItem(QStringLiteral("Temporary Dir"), tempUrl
, QString());
396 urls
.insert(tempDirIndex
, tempUrl
.toLocalFile());
398 // check if the new entry was created
399 QTRY_COMPARE(itemsInsertedSpy
.count(), 1);
400 CHECK_PLACES_URLS(urls
);
401 QTRY_COMPARE(model
->count(), m_model
->count());
404 m_model
->deleteItem(tempDirIndex
);
406 // make sure that the new item is removed
407 QTRY_COMPARE(itemsRemovedSpy
.count(), 1);
408 QTRY_COMPARE(m_model
->count(), m_expectedModelCount
);
409 CHECK_PLACES_URLS(initialUrls());
410 QTRY_COMPARE(model
->count(), m_model
->count());
413 void PlacesItemModelTest::testTearDownDevice()
415 const QUrl mediaUrl
= QUrl::fromLocalFile(QStringLiteral("/media/XO-Y4"));
416 int index
= indexOf(mediaUrl
);
417 QVERIFY(index
!= -1);
419 auto ejectAction
= m_model
->ejectAction(index
);
420 QVERIFY(!ejectAction
);
422 auto teardownAction
= m_model
->teardownAction(index
);
423 QVERIFY(teardownAction
);
425 QCOMPARE(m_model
->count(), m_expectedModelCount
);
427 QSignalSpy
spyItemsRemoved(m_model
, &PlacesItemModel::itemsRemoved
);
428 fakeManager()->call(QStringLiteral("unplug"), "/org/kde/solid/fakehw/volume_part1_size_993284096");
429 QTRY_COMPARE(m_model
->count(), m_expectedModelCount
- 1);
430 QCOMPARE(spyItemsRemoved
.count(), 1);
431 const QList
<QVariant
> spyItemsRemovedArgs
= spyItemsRemoved
.takeFirst();
432 const KItemRangeList removedRange
= spyItemsRemovedArgs
.at(0).value
<KItemRangeList
>();
433 QCOMPARE(removedRange
.size(), 1);
434 QCOMPARE(removedRange
.first().index
, index
);
435 QCOMPARE(removedRange
.first().count
, 1);
437 QCOMPARE(indexOf(mediaUrl
), -1);
439 QSignalSpy
spyItemsInserted(m_model
, &PlacesItemModel::itemsInserted
);
440 fakeManager()->call(QStringLiteral("plug"), "/org/kde/solid/fakehw/volume_part1_size_993284096");
441 QTRY_COMPARE(m_model
->count(), m_expectedModelCount
);
442 QCOMPARE(spyItemsInserted
.count(), 1);
443 index
= indexOf(mediaUrl
);
445 const QList
<QVariant
> args
= spyItemsInserted
.takeFirst();
446 const KItemRangeList insertedRange
= args
.at(0).value
<KItemRangeList
>();
447 QCOMPARE(insertedRange
.size(), 1);
448 QCOMPARE(insertedRange
.first().index
, index
);
449 QCOMPARE(insertedRange
.first().count
, 1);
452 void PlacesItemModelTest::testDefaultViewProperties_data()
454 QTest::addColumn
<QUrl
>("url");
455 QTest::addColumn
<DolphinView::Mode
>("expectedViewMode");
456 QTest::addColumn
<bool>("expectedPreviewShow");
457 QTest::addColumn
<QList
<QByteArray
> >("expectedVisibleRole");
460 QTest::newRow("Places - Home") << QUrl::fromLocalFile(QDir::homePath()) << DolphinView::IconsView
<< true << QList
<QByteArray
>({"text"});
463 QTest::newRow("Baloo - Documents") << QUrl("search:/documents") << DolphinView::DetailsView
<< false << QList
<QByteArray
>({"text", "path"});
466 QTest::newRow("Places - Audio") << QUrl("search:/audio") << DolphinView::DetailsView
<< false << QList
<QByteArray
>({"text", "artist", "album"});
469 QTest::newRow("Baloo - Today") << QUrl("timeline:/today") << DolphinView::DetailsView
<< true << QList
<QByteArray
>({"text", "modificationtime"});
472 QTest::newRow("Devices - Floppy") << QUrl("file:///media/floppy0") << DolphinView::IconsView
<< true << QList
<QByteArray
>({"text"});
476 void PlacesItemModelTest::testDefaultViewProperties()
479 QFETCH(DolphinView::Mode
, expectedViewMode
);
480 QFETCH(bool, expectedPreviewShow
);
481 QFETCH(QList
<QByteArray
>, expectedVisibleRole
);
483 ViewProperties
properties(KFilePlacesModel::convertedUrl(url
));
484 QCOMPARE(properties
.viewMode(), expectedViewMode
);
485 QCOMPARE(properties
.previewsShown(), expectedPreviewShow
);
486 QCOMPARE(properties
.visibleRoles(), expectedVisibleRole
);
489 void PlacesItemModelTest::testClear()
491 QCOMPARE(m_model
->count(), m_expectedModelCount
);
493 QCOMPARE(m_model
->count(), 0);
494 QCOMPARE(m_model
->hiddenCount(), 0);
496 QTRY_COMPARE(m_model
->count(), m_expectedModelCount
);
499 void PlacesItemModelTest::testHideItem()
501 const QUrl mediaUrl
= QUrl::fromLocalFile(QStringLiteral("/media/XO-Y4"));
502 const int index
= indexOf(mediaUrl
);
504 PlacesItem
*item
= m_model
->placesItem(index
);
506 QSignalSpy
spyItemsRemoved(m_model
, &PlacesItemModel::itemsRemoved
);
507 QList
<QVariant
> spyItemsRemovedArgs
;
508 KItemRangeList removedRange
;
510 QSignalSpy
spyItemsInserted(m_model
, &PlacesItemModel::itemsInserted
);
511 QList
<QVariant
> spyItemsInsertedArgs
;
512 KItemRangeList insertedRange
;
516 item
->setHidden(true);
518 // check if items removed was fired
519 QTRY_COMPARE(m_model
->count(), m_expectedModelCount
- 1);
520 QCOMPARE(spyItemsRemoved
.count(), 1);
521 spyItemsRemovedArgs
= spyItemsRemoved
.takeFirst();
522 removedRange
= spyItemsRemovedArgs
.at(0).value
<KItemRangeList
>();
523 QCOMPARE(removedRange
.size(), 1);
524 QCOMPARE(removedRange
.first().index
, index
);
525 QCOMPARE(removedRange
.first().count
, 1);
527 // allow model to show hidden items
528 m_model
->setHiddenItemsShown(true);
530 // check if the items inserted was fired
531 spyItemsInsertedArgs
= spyItemsInserted
.takeFirst();
532 insertedRange
= spyItemsInsertedArgs
.at(0).value
<KItemRangeList
>();
533 QCOMPARE(insertedRange
.size(), 1);
534 QCOMPARE(insertedRange
.first().index
, index
);
535 QCOMPARE(insertedRange
.first().count
, 1);
537 // mark item as visible
538 item
= m_model
->placesItem(index
);
539 item
->setHidden(false);
541 // mark model to hide invisible items
542 m_model
->setHiddenItemsShown(true);
544 QTRY_COMPARE(m_model
->count(), m_expectedModelCount
);
547 void PlacesItemModelTest::testSystemItems()
549 int tempDirIndex
= 3;
550 if (m_hasDesktopFolder
) {
553 if (m_hasDownloadsFolder
) {
557 QCOMPARE(m_model
->count(), m_expectedModelCount
);
558 for (int r
= 0; r
< m_model
->count(); r
++) {
559 QCOMPARE(m_model
->placesItem(r
)->isSystemItem(), !m_model
->placesItem(r
)->device().isValid());
562 QSignalSpy
itemsInsertedSpy(m_model
, &PlacesItemModel::itemsInserted
);
564 // create a new entry (non system item)
565 createPlaceItem(QStringLiteral("Temporary Dir"), QUrl::fromLocalFile(QStandardPaths::writableLocation(QStandardPaths::TempLocation
)), QString());
567 // check if the new entry was created
568 QTRY_COMPARE(itemsInsertedSpy
.count(), 1);
570 // make sure the new place get removed
571 schedulePlaceRemoval(tempDirIndex
);
573 QList
<QVariant
> args
= itemsInsertedSpy
.takeFirst();
574 KItemRangeList range
= args
.at(0).value
<KItemRangeList
>();
575 QCOMPARE(range
.first().index
, tempDirIndex
);
576 QCOMPARE(range
.first().count
, 1);
577 QVERIFY(!m_model
->placesItem(tempDirIndex
)->isSystemItem());
578 QCOMPARE(m_model
->count(), m_expectedModelCount
+ 1);
581 // check if the removal signal is correct
582 QSignalSpy
itemsRemovedSpy(m_model
, &PlacesItemModel::itemsRemoved
);
583 m_model
->deleteItem(tempDirIndex
);
584 QTRY_COMPARE(itemsRemovedSpy
.count(), 1);
585 args
= itemsRemovedSpy
.takeFirst();
586 range
= args
.at(0).value
<KItemRangeList
>();
587 QCOMPARE(range
.first().index
, tempDirIndex
);
588 QCOMPARE(range
.first().count
, 1);
589 QTRY_COMPARE(m_model
->count(), m_expectedModelCount
);
591 //cancel removal (it was removed above)
592 cancelPlaceRemoval(tempDirIndex
);
595 void PlacesItemModelTest::testEditBookmark()
597 int tempDirIndex
= 1;
598 if (m_hasDesktopFolder
) {
601 if (m_hasDownloadsFolder
) {
605 QScopedPointer
<PlacesItemModel
> other(new PlacesItemModel());
607 createPlaceItem(QStringLiteral("Temporary Dir"), QUrl::fromLocalFile(QStandardPaths::writableLocation(QStandardPaths::TempLocation
)), QString());
609 // make sure that the new item will be removed later
610 schedulePlaceRemoval(tempDirIndex
+ 2);
612 QSignalSpy
itemsChangedSply(m_model
, &PlacesItemModel::itemsChanged
);
615 m_model
->item(tempDirIndex
)->setText(QStringLiteral("Renamed place"));
618 // check if the correct signal was fired
619 QTRY_COMPARE(itemsChangedSply
.count(), 1);
620 QList
<QVariant
> args
= itemsChangedSply
.takeFirst();
621 KItemRangeList range
= args
.at(0).value
<KItemRangeList
>();
622 QCOMPARE(range
.first().index
, tempDirIndex
);
623 QCOMPARE(range
.first().count
, 1);
624 QSet
<QByteArray
> roles
= args
.at(1).value
<QSet
<QByteArray
> >();
625 QCOMPARE(roles
.size(), 1);
626 QCOMPARE(*roles
.begin(), QByteArrayLiteral("text"));
627 QCOMPARE(m_model
->item(tempDirIndex
)->text(), QStringLiteral("Renamed place"));
629 // check if the item was updated in the other model
630 QTRY_COMPARE(other
->item(tempDirIndex
)->text(), QStringLiteral("Renamed place"));
633 void PlacesItemModelTest::testEditAfterCreation()
635 int tempDirIndex
= 1;
636 if (m_hasDesktopFolder
) {
639 if (m_hasDownloadsFolder
) {
643 const QUrl tempUrl
= QUrl::fromLocalFile(QStandardPaths::writableLocation(QStandardPaths::TempLocation
));
644 QSignalSpy
itemsInsertedSpy(m_model
, &PlacesItemModel::itemsInserted
);
646 // create a new place
647 createPlaceItem(QStringLiteral("Temporary Dir"), tempUrl
, QString());
648 QTRY_COMPARE(itemsInsertedSpy
.count(), 1);
650 PlacesItemModel
*model
= new PlacesItemModel();
651 QTRY_COMPARE(model
->count(), m_model
->count());
653 // make sure that the new item will be removed later
654 schedulePlaceRemoval(tempDirIndex
+ 2);
657 PlacesItem
*item
= m_model
->placesItem(tempDirIndex
);
658 item
->setText(QStringLiteral("Renamed place"));
661 // check if the second model got the changes
662 QTRY_COMPARE(model
->count(), m_model
->count());
663 QTRY_COMPARE(model
->placesItem(tempDirIndex
)->text(), m_model
->placesItem(tempDirIndex
)->text());
664 QTRY_COMPARE(model
->placesItem(tempDirIndex
)->bookmark().metaDataItem(QStringLiteral("OnlyInApp")),
665 m_model
->placesItem(tempDirIndex
)->bookmark().metaDataItem(QStringLiteral("OnlyInApp")));
666 QTRY_COMPARE(model
->placesItem(tempDirIndex
)->icon(), m_model
->placesItem(tempDirIndex
)->icon());
667 QTRY_COMPARE(model
->placesItem(tempDirIndex
)->url(), m_model
->placesItem(tempDirIndex
)->url());
670 void PlacesItemModelTest::testEditMetadata()
672 int tempDirIndex
= 1;
673 if (m_hasDesktopFolder
) {
676 if (m_hasDownloadsFolder
) {
680 const QUrl tempUrl
= QUrl::fromLocalFile(QStandardPaths::writableLocation(QStandardPaths::TempLocation
));
681 QSignalSpy
itemsInsertedSpy(m_model
, &PlacesItemModel::itemsInserted
);
683 // create a new place
684 createPlaceItem(QStringLiteral("Temporary Dir"), tempUrl
, QString());
685 QTRY_COMPARE(itemsInsertedSpy
.count(), 1);
687 // check if the new entry was created
688 PlacesItemModel
*model
= new PlacesItemModel();
689 QTRY_COMPARE(model
->count(), m_model
->count());
691 // make sure that the new item will be removed later
692 schedulePlaceRemoval(tempDirIndex
+ 2);
694 // modify place metadata
695 PlacesItem
*item
= m_model
->placesItem(tempDirIndex
);
696 item
->bookmark().setMetaDataItem(QStringLiteral("OnlyInApp"), KAboutData::applicationData().componentName());
699 // check if the place was modified in both models
700 QTRY_COMPARE(model
->placesItem(tempDirIndex
)->bookmark().metaDataItem(QStringLiteral("OnlyInApp")),
701 KAboutData::applicationData().componentName());
702 QTRY_COMPARE(model
->placesItem(tempDirIndex
)->text(), m_model
->placesItem(tempDirIndex
)->text());
703 QTRY_COMPARE(model
->placesItem(tempDirIndex
)->bookmark().metaDataItem(QStringLiteral("OnlyInApp")),
704 m_model
->placesItem(tempDirIndex
)->bookmark().metaDataItem(QStringLiteral("OnlyInApp")));
705 QTRY_COMPARE(model
->placesItem(tempDirIndex
)->icon(), m_model
->placesItem(tempDirIndex
)->icon());
706 QTRY_COMPARE(model
->placesItem(tempDirIndex
)->url(), m_model
->placesItem(tempDirIndex
)->url());
709 void PlacesItemModelTest::testRefresh()
711 int tempDirIndex
= 3;
712 if (m_hasDesktopFolder
) {
715 if (m_hasDownloadsFolder
) {
719 const QUrl tempUrl
= QUrl::fromLocalFile(QStandardPaths::writableLocation(QStandardPaths::TempLocation
));
720 QSignalSpy
itemsInsertedSpy(m_model
, &PlacesItemModel::itemsInserted
);
722 // create a new place
723 createPlaceItem(QStringLiteral("Temporary Dir"), tempUrl
, QString());
724 QTRY_COMPARE(itemsInsertedSpy
.count(), 1);
726 PlacesItemModel
*model
= new PlacesItemModel();
727 QTRY_COMPARE(model
->count(), m_model
->count());
729 // make sure that the new item will be removed later
730 schedulePlaceRemoval(tempDirIndex
);
732 PlacesItem
*item
= m_model
->placesItem(tempDirIndex
);
733 PlacesItem
*sameItem
= model
->placesItem(tempDirIndex
);
734 QCOMPARE(item
->text(), sameItem
->text());
737 item
->setText(QStringLiteral("Renamed place"));
739 // item from another model is not affected at the moment
740 QVERIFY(item
->text() != sameItem
->text());
745 // item must be equal
746 QTRY_COMPARE_WITH_TIMEOUT(item
->text(), sameItem
->text(), TIMEOUT
);
749 void PlacesItemModelTest::testIcons_data()
751 QTest::addColumn
<QUrl
>("url");
752 QTest::addColumn
<QString
>("expectedIconName");
755 QTest::newRow("Places - Home") << QUrl::fromLocalFile(QDir::homePath()) << QStringLiteral("user-home");
758 QTest::newRow("Baloo - Documents") << QUrl("search:/documents") << QStringLiteral("folder-text");
761 QTest::newRow("Baloo - Today") << QUrl("timeline:/today") << QStringLiteral("go-jump-today");
764 QTest::newRow("Devices - Floppy") << QUrl("file:///media/floppy0") << QStringLiteral("blockdevice");
767 void PlacesItemModelTest::testIcons()
770 QFETCH(QString
, expectedIconName
);
772 PlacesItem
*item
= m_model
->placesItem(indexOf(url
));
773 QCOMPARE(item
->icon(), expectedIconName
);
775 for (int r
= 0; r
< m_model
->count(); r
++) {
776 QVERIFY(!m_model
->placesItem(r
)->icon().isEmpty());
780 void PlacesItemModelTest::testDragAndDrop()
782 int lastIndex
= 2; // last index of places group
783 if (m_hasDesktopFolder
) {
786 if (m_hasDownloadsFolder
) {
790 QList
<QVariant
> args
;
791 KItemRangeList range
;
792 QStringList urls
= initialUrls();
793 QSignalSpy
itemsInsertedSpy(m_model
, &PlacesItemModel::itemsInserted
);
794 QSignalSpy
itemsRemovedSpy(m_model
, &PlacesItemModel::itemsRemoved
);
796 CHECK_PLACES_URLS(initialUrls());
797 // Move the home directory to the end of the places group
798 QMimeData
*dropData
= createMimeData(QList
<int>() << 0);
799 m_model
->dropMimeDataBefore(m_model
->count() - 1, dropData
);
800 urls
.move(0, lastIndex
);
803 QTRY_COMPARE(itemsInsertedSpy
.count(), 1);
804 QTRY_COMPARE(itemsRemovedSpy
.count(), 1);
806 // remove item from actual position
807 args
= itemsRemovedSpy
.takeFirst();
808 range
= args
.at(0).value
<KItemRangeList
>();
809 QCOMPARE(range
.size(), 1);
810 QCOMPARE(range
.at(0).count
, 1);
811 QCOMPARE(range
.at(0).index
, 0);
813 // insert intem in his group
814 args
= itemsInsertedSpy
.takeFirst();
815 range
= args
.at(0).value
<KItemRangeList
>();
816 QCOMPARE(range
.size(), 1);
817 QCOMPARE(range
.at(0).count
, 1);
818 QCOMPARE(range
.at(0).index
, lastIndex
);
820 CHECK_PLACES_URLS(urls
);
822 itemsInsertedSpy
.clear();
823 itemsRemovedSpy
.clear();
825 // Move home directory item back to its original position
826 dropData
= createMimeData(QList
<int>() << lastIndex
);
827 m_model
->dropMimeDataBefore(0, dropData
);
828 urls
.move(lastIndex
, 0);
831 QTRY_COMPARE(itemsInsertedSpy
.count(), 1);
832 QTRY_COMPARE(itemsRemovedSpy
.count(), 1);
834 // remove item from actual position
835 args
= itemsRemovedSpy
.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 // insert intem in the requested position
842 args
= itemsInsertedSpy
.takeFirst();
843 range
= args
.at(0).value
<KItemRangeList
>();
844 QCOMPARE(range
.size(), 1);
845 QCOMPARE(range
.at(0).count
, 1);
846 QCOMPARE(range
.at(0).index
, 0);
848 CHECK_PLACES_URLS(urls
);
851 void PlacesItemModelTest::testHideDevices()
853 QSignalSpy
itemsRemoved(m_model
, &PlacesItemModel::itemsRemoved
);
854 QStringList urls
= initialUrls();
856 m_model
->setGroupHidden(KFilePlacesModel::RemovableDevicesType
, true);
857 QTRY_VERIFY(m_model
->isGroupHidden(KFilePlacesModel::RemovableDevicesType
));
858 QTRY_COMPARE(itemsRemoved
.count(), 3);
860 // remove removable-devices
861 urls
.removeOne(QStringLiteral("/media/floppy0"));
862 urls
.removeOne(QStringLiteral("/media/XO-Y4"));
863 urls
.removeOne(QStringLiteral("/media/cdrom"));
865 // check if the correct urls was removed
866 CHECK_PLACES_URLS(urls
);
869 m_model
= new PlacesItemModel();
870 QTRY_COMPARE(m_model
->count(), urls
.count());
871 CHECK_PLACES_URLS(urls
);
874 m_model
->setGroupHidden(KFilePlacesModel::RemovableDevicesType
, false);
875 urls
= initialUrls();
876 QTRY_COMPARE(m_model
->count(), urls
.count());
877 CHECK_PLACES_URLS(urls
);
880 void PlacesItemModelTest::testDuplicatedEntries()
882 QStringList urls
= initialUrls();
883 // create a duplicated entry on bookmark
884 KBookmarkManager
*bookmarkManager
= KBookmarkManager::managerForFile(bookmarksFile(), QStringLiteral("kfilePlaces"));
885 KBookmarkGroup root
= bookmarkManager
->root();
886 KBookmark bookmark
= root
.addBookmark(QStringLiteral("Duplicated Search Videos"), QUrl("search:/videos"), {});
888 const QString id
= QUuid::createUuid().toString();
889 bookmark
.setMetaDataItem(QStringLiteral("ID"), id
);
890 bookmark
.setMetaDataItem(QStringLiteral("OnlyInApp"), KAboutData::applicationData().componentName());
891 bookmarkManager
->emitChanged(bookmarkManager
->root());
893 PlacesItemModel
*newModel
= new PlacesItemModel();
894 QTRY_COMPARE(placesUrls(newModel
).count(QStringLiteral("search:/videos")), 1);
895 QTRY_COMPARE(urls
, placesUrls(newModel
));
899 void PlacesItemModelTest::renameAfterCreation()
901 int tempDirIndex
= 1;
902 if (m_hasDesktopFolder
) {
905 if (m_hasDownloadsFolder
) {
909 const QUrl tempUrl
= QUrl::fromLocalFile(QStandardPaths::writableLocation(QStandardPaths::TempLocation
));
910 QStringList urls
= initialUrls();
911 PlacesItemModel
*model
= new PlacesItemModel();
913 CHECK_PLACES_URLS(urls
);
914 QTRY_COMPARE(model
->count(), m_model
->count());
916 // create a new place
917 createPlaceItem(QStringLiteral("Temporary Dir"), tempUrl
, QString());
918 urls
.insert(tempDirIndex
+ 2, tempUrl
.toLocalFile());
920 // make sure that the new item will be removed later
921 schedulePlaceRemoval(tempDirIndex
+ 2);
923 CHECK_PLACES_URLS(urls
);
924 QCOMPARE(model
->count(), m_model
->count());
928 QSignalSpy
changedSpy(m_model
, &PlacesItemModel::itemsChanged
);
930 PlacesItem
*item
= m_model
->placesItem(tempDirIndex
);
931 item
->setText(QStringLiteral("New Temporary Dir"));
932 item
->setUrl(item
->url());
933 item
->setIcon(item
->icon());
936 QTRY_COMPARE(changedSpy
.count(), 1);
938 // check if the place was modified in both models
939 QTRY_COMPARE(m_model
->placesItem(tempDirIndex
)->text(), QStringLiteral("New Temporary Dir"));
940 QTRY_COMPARE(model
->placesItem(tempDirIndex
)->text(), QStringLiteral("New Temporary Dir"));
943 QTEST_MAIN(PlacesItemModelTest
)
945 #include "placesitemmodeltest.moc"