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
)
40 static QString
bookmarksFile()
42 return QStandardPaths::writableLocation(QStandardPaths::GenericDataLocation
) + "/user-places.xbel";
45 class PlacesItemModelTest
: public QObject
54 void cleanupTestCase();
58 void testDeletePlace();
59 void testPlaceItem_data();
61 void testTearDownDevice();
62 void testDefaultViewProperties_data();
63 void testDefaultViewProperties();
66 void testSystemItems();
67 void testEditBookmark();
68 void testEditAfterCreation();
69 void testEditMetadata();
71 void testIcons_data();
73 void testDragAndDrop();
74 void testHideDevices();
75 void testDuplicatedEntries();
76 void renameAfterCreation();
79 PlacesItemModel
* m_model
;
80 QSet
<int> m_tobeRemoved
;
81 QMap
<QString
, QDBusInterface
*> m_interfacesMap
;
82 int m_expectedModelCount
= 14;
83 bool m_hasDesktopFolder
= false;
84 bool m_hasDocumentsFolder
= false;
85 bool m_hasDownloadsFolder
= false;
87 void setBalooEnabled(bool enabled
);
88 int indexOf(const QUrl
&url
);
89 QDBusInterface
*fakeManager();
90 QDBusInterface
*fakeDevice(const QString
&udi
);
91 QStringList
placesUrls(PlacesItemModel
*model
= nullptr) const;
92 QStringList
initialUrls() const;
93 void createPlaceItem(const QString
&text
, const QUrl
&url
, const QString
&icon
);
94 void schedulePlaceRemoval(int index
);
95 void cancelPlaceRemoval(int index
);
96 QMimeData
*createMimeData(const QList
<int> &indexes
) const;
97 QTemporaryDir m_tempHomeDir
;
100 #define CHECK_PLACES_URLS(urls) \
102 QStringList places = placesUrls(); \
103 if (places != urls) { \
104 qWarning() << "Expected:" << urls; \
105 qWarning() << "Got:" << places; \
106 QCOMPARE(places, urls); \
110 void PlacesItemModelTest::setBalooEnabled(bool enabled
)
112 KConfig
config(QStringLiteral("baloofilerc"));
113 KConfigGroup basicSettings
= config
.group("Basic Settings");
114 basicSettings
.writeEntry("Indexing-Enabled", enabled
);
118 int PlacesItemModelTest::indexOf(const QUrl
&url
)
120 for (int r
= 0; r
< m_model
->count(); r
++) {
121 if (m_model
->placesItem(r
)->url() == url
) {
128 QDBusInterface
*PlacesItemModelTest::fakeManager()
130 return fakeDevice(QStringLiteral("/org/kde/solid/fakehw"));
133 QDBusInterface
*PlacesItemModelTest::fakeDevice(const QString
&udi
)
135 if (m_interfacesMap
.contains(udi
)) {
136 return m_interfacesMap
[udi
];
139 QDBusInterface
*iface
= new QDBusInterface(QDBusConnection::sessionBus().baseService(), udi
);
140 m_interfacesMap
[udi
] = iface
;
145 QStringList
PlacesItemModelTest::placesUrls(PlacesItemModel
*model
) const
152 for (int row
= 0; row
< model
->count(); ++row
) {
153 urls
<< model
->placesItem(row
)->url().toDisplayString(QUrl::PreferLocalFile
);
158 QStringList
PlacesItemModelTest::initialUrls() const
160 static QStringList urls
;
161 if (urls
.isEmpty()) {
162 urls
<< QDir::homePath();
164 if (m_hasDesktopFolder
) {
165 urls
<< QDir::homePath() + QStringLiteral("/Desktop");
168 if (m_hasDocumentsFolder
) {
169 urls
<< QDir::homePath() + QStringLiteral("/Documents");
172 if (m_hasDownloadsFolder
) {
173 urls
<< QDir::homePath() + QStringLiteral("/Downloads");
176 urls
<< QStringLiteral("trash:/")
177 << QStringLiteral("remote:/")
178 << QStringLiteral("/media/nfs")
179 << QStringLiteral("timeline:/today") << QStringLiteral("timeline:/yesterday")
180 << QStringLiteral("search:/documents") << QStringLiteral("search:/images") << QStringLiteral("search:/audio") << QStringLiteral("search:/videos")
181 << QStringLiteral("/foreign")
182 << QStringLiteral("/media/floppy0") << QStringLiteral("/media/XO-Y4") << QStringLiteral("/media/cdrom");
187 void PlacesItemModelTest::createPlaceItem(const QString
&text
, const QUrl
&url
, const QString
&icon
)
189 m_model
->createPlacesItem(text
, url
, icon
);
192 void PlacesItemModelTest::schedulePlaceRemoval(int index
)
194 m_tobeRemoved
.insert(index
);
197 void PlacesItemModelTest::cancelPlaceRemoval(int index
)
199 m_tobeRemoved
.remove(index
);
202 QMimeData
*PlacesItemModelTest::createMimeData(const QList
<int> &indexes
) const
205 QDataStream
stream(&itemData
, QIODevice::WriteOnly
);
208 for (int index
: indexes
) {
209 const QUrl itemUrl
= m_model
->placesItem(index
)->url();
210 if (itemUrl
.isValid()) {
216 QMimeData
* mimeData
= new QMimeData();
217 mimeData
->setUrls(urls
);
218 // copied from PlacesItemModel::internalMimeType()
219 const QString internalMimeType
= "application/x-dolphinplacesmodel-" +
220 QString::number((qptrdiff
)m_model
);
221 mimeData
->setData(internalMimeType
, itemData
);
225 void PlacesItemModelTest::init()
227 m_model
= new PlacesItemModel();
228 // WORKAROUND: need to wait for bookmark to load
230 QCOMPARE(m_model
->count(), m_expectedModelCount
);
233 void PlacesItemModelTest::cleanup()
235 const auto tobeRemoved
= m_tobeRemoved
;
236 for (const int i
: tobeRemoved
) {
237 int before
= m_model
->count();
238 m_model
->deleteItem(i
);
239 QTRY_COMPARE(m_model
->count(), before
- 1);
241 m_tobeRemoved
.clear();
246 void PlacesItemModelTest::initTestCase()
248 QVERIFY(m_tempHomeDir
.isValid());
249 QVERIFY(qputenv("HOME", m_tempHomeDir
.path().toUtf8()));
250 QVERIFY(qputenv("KDE_FORK_SLAVES", "yes"));
252 QStandardPaths::setTestModeEnabled(true);
254 const QString fakeHw
= QFINDTESTDATA("data/fakecomputer.xml");
255 QVERIFY(!fakeHw
.isEmpty());
256 qputenv("SOLID_FAKEHW", QFile::encodeName(fakeHw
));
258 setBalooEnabled(true);
259 const QString bookmarsFileName
= bookmarksFile();
260 if (QFileInfo::exists(bookmarsFileName
)) {
261 // Ensure we'll have a clean bookmark file to start
262 QVERIFY(QFile::remove(bookmarsFileName
));
265 if (QDir(QStandardPaths::writableLocation(QStandardPaths::DesktopLocation
)).exists()) {
266 m_hasDesktopFolder
= true;
267 m_expectedModelCount
++;
270 if (QDir(QStandardPaths::writableLocation(QStandardPaths::DocumentsLocation
)).exists()) {
271 m_hasDocumentsFolder
= true;
272 m_expectedModelCount
++;
275 if (QDir(QStandardPaths::writableLocation(QStandardPaths::DownloadLocation
)).exists()) {
276 m_hasDownloadsFolder
= true;
277 m_expectedModelCount
++;
280 qRegisterMetaType
<KItemRangeList
>();
281 qRegisterMetaType
<KItemRange
>();
284 void PlacesItemModelTest::cleanupTestCase()
286 qDeleteAll(m_interfacesMap
);
287 QFile::remove(bookmarksFile());
290 void PlacesItemModelTest::testModelSort()
292 CHECK_PLACES_URLS(initialUrls());
295 void PlacesItemModelTest::testGroups()
297 const auto groups
= m_model
->groups();
298 int expectedRemoteIndex
= 2;
299 if (m_hasDesktopFolder
) {
300 expectedRemoteIndex
++;
302 if (m_hasDocumentsFolder
) {
303 expectedRemoteIndex
++;
305 if (m_hasDownloadsFolder
) {
306 expectedRemoteIndex
++;
309 QCOMPARE(groups
.size(), 6);
311 QCOMPARE(groups
.at(0).first
, 0);
312 QCOMPARE(groups
.at(0).second
.toString(), QStringLiteral("Places"));
314 QCOMPARE(groups
.at(1).first
, expectedRemoteIndex
);
315 QCOMPARE(groups
.at(1).second
.toString(), QStringLiteral("Remote"));
317 QCOMPARE(groups
.at(2).first
, expectedRemoteIndex
+ 2);
318 QCOMPARE(groups
.at(2).second
.toString(), QStringLiteral("Recently Saved"));
320 QCOMPARE(groups
.at(3).first
, expectedRemoteIndex
+ 4);
321 QCOMPARE(groups
.at(3).second
.toString(), QStringLiteral("Search For"));
323 QCOMPARE(groups
.at(4).first
, expectedRemoteIndex
+ 8);
324 QCOMPARE(groups
.at(4).second
.toString(), QStringLiteral("Devices"));
326 QCOMPARE(groups
.at(5).first
, expectedRemoteIndex
+ 9);
327 QCOMPARE(groups
.at(5).second
.toString(), QStringLiteral("Removable Devices"));
330 void PlacesItemModelTest::testPlaceItem_data()
332 QTest::addColumn
<QUrl
>("url");
333 QTest::addColumn
<bool>("expectedIsHidden");
334 QTest::addColumn
<bool>("expectedIsSystemItem");
335 QTest::addColumn
<QString
>("expectedGroup");
336 QTest::addColumn
<bool>("expectedStorageSetupNeeded");
339 QTest::newRow("Places - Home") << QUrl::fromLocalFile(QDir::homePath()) << false << true << QStringLiteral("Places") << false;
342 QTest::newRow("Baloo - Documents") << QUrl("search:/documents") << false << true << QStringLiteral("Search For") << false;
345 QTest::newRow("Baloo - Today") << QUrl("timeline:/today") << false << true << QStringLiteral("Recently Saved") << false;
348 QTest::newRow("Devices - Floppy") << QUrl("file:///media/floppy0") << false << false << QStringLiteral("Removable Devices") << false;
351 void PlacesItemModelTest::testPlaceItem()
354 QFETCH(bool, expectedIsHidden
);
355 QFETCH(bool, expectedIsSystemItem
);
356 QFETCH(QString
, expectedGroup
);
357 QFETCH(bool, expectedStorageSetupNeeded
);
359 const int index
= indexOf(url
);
360 PlacesItem
*item
= m_model
->placesItem(index
);
361 QCOMPARE(item
->url(), url
);
362 QCOMPARE(item
->isHidden(), expectedIsHidden
);
363 QCOMPARE(item
->isSystemItem(), expectedIsSystemItem
);
364 QCOMPARE(item
->group(), expectedGroup
);
365 QCOMPARE(item
->storageSetupNeeded(), expectedStorageSetupNeeded
);
368 void PlacesItemModelTest::testDeletePlace()
370 const QUrl tempUrl
= QUrl::fromLocalFile(QStandardPaths::writableLocation(QStandardPaths::TempLocation
));
371 QStringList urls
= initialUrls();
372 QSignalSpy
itemsInsertedSpy(m_model
, &PlacesItemModel::itemsInserted
);
373 QSignalSpy
itemsRemovedSpy(m_model
, &PlacesItemModel::itemsRemoved
);
375 PlacesItemModel
*model
= new PlacesItemModel();
377 int tempDirIndex
= 2;
378 if (m_hasDesktopFolder
) {
381 if (m_hasDocumentsFolder
) {
384 if (m_hasDownloadsFolder
) {
388 // create a new place
389 createPlaceItem(QStringLiteral("Temporary Dir"), tempUrl
, QString());
390 urls
.insert(tempDirIndex
, tempUrl
.toLocalFile());
392 // check if the new entry was created
393 QTRY_COMPARE(itemsInsertedSpy
.count(), 1);
394 CHECK_PLACES_URLS(urls
);
395 QTRY_COMPARE(model
->count(), m_model
->count());
398 m_model
->deleteItem(tempDirIndex
);
400 // make sure that the new item is removed
401 QTRY_COMPARE(itemsRemovedSpy
.count(), 1);
402 QTRY_COMPARE(m_model
->count(), m_expectedModelCount
);
403 CHECK_PLACES_URLS(initialUrls());
404 QTRY_COMPARE(model
->count(), m_model
->count());
407 void PlacesItemModelTest::testTearDownDevice()
409 const QUrl mediaUrl
= QUrl::fromLocalFile(QStringLiteral("/media/XO-Y4"));
410 int index
= indexOf(mediaUrl
);
411 QVERIFY(index
!= -1);
413 auto ejectAction
= m_model
->ejectAction(index
);
414 QVERIFY(!ejectAction
);
416 auto teardownAction
= m_model
->teardownAction(index
);
417 QVERIFY(teardownAction
);
419 QCOMPARE(m_model
->count(), m_expectedModelCount
);
421 QSignalSpy
spyItemsRemoved(m_model
, &PlacesItemModel::itemsRemoved
);
422 fakeManager()->call(QStringLiteral("unplug"), "/org/kde/solid/fakehw/volume_part1_size_993284096");
423 QTRY_COMPARE(m_model
->count(), m_expectedModelCount
- 1);
424 QCOMPARE(spyItemsRemoved
.count(), 1);
425 const QList
<QVariant
> spyItemsRemovedArgs
= spyItemsRemoved
.takeFirst();
426 const KItemRangeList removedRange
= spyItemsRemovedArgs
.at(0).value
<KItemRangeList
>();
427 QCOMPARE(removedRange
.size(), 1);
428 QCOMPARE(removedRange
.first().index
, index
);
429 QCOMPARE(removedRange
.first().count
, 1);
431 QCOMPARE(indexOf(mediaUrl
), -1);
433 QSignalSpy
spyItemsInserted(m_model
, &PlacesItemModel::itemsInserted
);
434 fakeManager()->call(QStringLiteral("plug"), "/org/kde/solid/fakehw/volume_part1_size_993284096");
435 QTRY_COMPARE(m_model
->count(), m_expectedModelCount
);
436 QCOMPARE(spyItemsInserted
.count(), 1);
437 index
= indexOf(mediaUrl
);
439 const QList
<QVariant
> args
= spyItemsInserted
.takeFirst();
440 const KItemRangeList insertedRange
= args
.at(0).value
<KItemRangeList
>();
441 QCOMPARE(insertedRange
.size(), 1);
442 QCOMPARE(insertedRange
.first().index
, index
);
443 QCOMPARE(insertedRange
.first().count
, 1);
446 void PlacesItemModelTest::testDefaultViewProperties_data()
448 QTest::addColumn
<QUrl
>("url");
449 QTest::addColumn
<DolphinView::Mode
>("expectedViewMode");
450 QTest::addColumn
<bool>("expectedPreviewShow");
451 QTest::addColumn
<QList
<QByteArray
> >("expectedVisibleRole");
454 QTest::newRow("Places - Home") << QUrl::fromLocalFile(QDir::homePath()) << DolphinView::IconsView
<< true << QList
<QByteArray
>({"text"});
457 QTest::newRow("Baloo - Documents") << QUrl("search:/documents") << DolphinView::DetailsView
<< false << QList
<QByteArray
>({"text", "path"});
460 QTest::newRow("Places - Audio") << QUrl("search:/audio") << DolphinView::DetailsView
<< false << QList
<QByteArray
>({"text", "artist", "album"});
463 QTest::newRow("Baloo - Today") << QUrl("timeline:/today") << DolphinView::DetailsView
<< true << QList
<QByteArray
>({"text", "modificationtime"});
466 QTest::newRow("Devices - Floppy") << QUrl("file:///media/floppy0") << DolphinView::IconsView
<< true << QList
<QByteArray
>({"text"});
470 void PlacesItemModelTest::testDefaultViewProperties()
473 QFETCH(DolphinView::Mode
, expectedViewMode
);
474 QFETCH(bool, expectedPreviewShow
);
475 QFETCH(QList
<QByteArray
>, expectedVisibleRole
);
477 // In order to test the default view properties, turn off the global view properties and re-init the test to reload the model.
478 GeneralSettings
* settings
= GeneralSettings::self();
479 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
= 2;
554 if (m_hasDesktopFolder
) {
557 if (m_hasDocumentsFolder
) {
560 if (m_hasDownloadsFolder
) {
564 QCOMPARE(m_model
->count(), m_expectedModelCount
);
565 for (int r
= 0; r
< m_model
->count(); r
++) {
566 QCOMPARE(m_model
->placesItem(r
)->isSystemItem(), !m_model
->placesItem(r
)->device().isValid());
569 QSignalSpy
itemsInsertedSpy(m_model
, &PlacesItemModel::itemsInserted
);
571 // create a new entry (non system item)
572 createPlaceItem(QStringLiteral("Temporary Dir"), QUrl::fromLocalFile(QStandardPaths::writableLocation(QStandardPaths::TempLocation
)), QString());
574 // check if the new entry was created
575 QTRY_COMPARE(itemsInsertedSpy
.count(), 1);
577 // make sure the new place get removed
578 schedulePlaceRemoval(tempDirIndex
);
580 QList
<QVariant
> args
= itemsInsertedSpy
.takeFirst();
581 KItemRangeList range
= args
.at(0).value
<KItemRangeList
>();
582 QCOMPARE(range
.first().index
, tempDirIndex
);
583 QCOMPARE(range
.first().count
, 1);
584 QVERIFY(!m_model
->placesItem(tempDirIndex
)->isSystemItem());
585 QCOMPARE(m_model
->count(), m_expectedModelCount
+ 1);
588 // check if the removal signal is correct
589 QSignalSpy
itemsRemovedSpy(m_model
, &PlacesItemModel::itemsRemoved
);
590 m_model
->deleteItem(tempDirIndex
);
591 QTRY_COMPARE(itemsRemovedSpy
.count(), 1);
592 args
= itemsRemovedSpy
.takeFirst();
593 range
= args
.at(0).value
<KItemRangeList
>();
594 QCOMPARE(range
.first().index
, tempDirIndex
);
595 QCOMPARE(range
.first().count
, 1);
596 QTRY_COMPARE(m_model
->count(), m_expectedModelCount
);
598 //cancel removal (it was removed above)
599 cancelPlaceRemoval(tempDirIndex
);
602 void PlacesItemModelTest::testEditBookmark()
604 int tempDirIndex
= 2;
605 if (m_hasDesktopFolder
) {
608 if (m_hasDocumentsFolder
) {
611 if (m_hasDownloadsFolder
) {
615 QScopedPointer
<PlacesItemModel
> other(new PlacesItemModel());
617 createPlaceItem(QStringLiteral("Temporary Dir"), QUrl::fromLocalFile(QStandardPaths::writableLocation(QStandardPaths::TempLocation
)), QString());
619 // make sure that the new item will be removed later
620 schedulePlaceRemoval(tempDirIndex
);
622 QSignalSpy
itemsChangedSply(m_model
, &PlacesItemModel::itemsChanged
);
625 m_model
->item(tempDirIndex
)->setText(QStringLiteral("Renamed place"));
628 // check if the correct signal was fired
629 QTRY_COMPARE(itemsChangedSply
.count(), 1);
630 QList
<QVariant
> args
= itemsChangedSply
.takeFirst();
631 KItemRangeList range
= args
.at(0).value
<KItemRangeList
>();
632 QCOMPARE(range
.first().index
, tempDirIndex
);
633 QCOMPARE(range
.first().count
, 1);
634 QSet
<QByteArray
> roles
= args
.at(1).value
<QSet
<QByteArray
> >();
635 QCOMPARE(roles
.size(), 1);
636 QCOMPARE(*roles
.begin(), QByteArrayLiteral("text"));
637 QCOMPARE(m_model
->item(tempDirIndex
)->text(), QStringLiteral("Renamed place"));
639 // check if the item was updated in the other model
640 QTRY_COMPARE(other
->item(tempDirIndex
)->text(), QStringLiteral("Renamed place"));
643 void PlacesItemModelTest::testEditAfterCreation()
645 int tempDirIndex
= 2;
646 if (m_hasDesktopFolder
) {
649 if (m_hasDocumentsFolder
) {
652 if (m_hasDownloadsFolder
) {
656 const QUrl tempUrl
= QUrl::fromLocalFile(QStandardPaths::writableLocation(QStandardPaths::TempLocation
));
657 QSignalSpy
itemsInsertedSpy(m_model
, &PlacesItemModel::itemsInserted
);
659 // create a new place
660 createPlaceItem(QStringLiteral("Temporary Dir"), tempUrl
, QString());
661 QTRY_COMPARE(itemsInsertedSpy
.count(), 1);
663 PlacesItemModel
*model
= new PlacesItemModel();
664 QTRY_COMPARE(model
->count(), m_model
->count());
666 // make sure that the new item will be removed later
667 schedulePlaceRemoval(tempDirIndex
);
670 PlacesItem
*item
= m_model
->placesItem(tempDirIndex
);
671 item
->setText(QStringLiteral("Renamed place"));
674 // check if the second model got the changes
675 QTRY_COMPARE(model
->count(), m_model
->count());
676 QTRY_COMPARE(model
->placesItem(tempDirIndex
)->text(), m_model
->placesItem(tempDirIndex
)->text());
677 QTRY_COMPARE(model
->placesItem(tempDirIndex
)->bookmark().metaDataItem(QStringLiteral("OnlyInApp")),
678 m_model
->placesItem(tempDirIndex
)->bookmark().metaDataItem(QStringLiteral("OnlyInApp")));
679 QTRY_COMPARE(model
->placesItem(tempDirIndex
)->icon(), m_model
->placesItem(tempDirIndex
)->icon());
680 QTRY_COMPARE(model
->placesItem(tempDirIndex
)->url(), m_model
->placesItem(tempDirIndex
)->url());
683 void PlacesItemModelTest::testEditMetadata()
685 int tempDirIndex
= 2;
686 if (m_hasDesktopFolder
) {
689 if (m_hasDocumentsFolder
) {
692 if (m_hasDownloadsFolder
) {
696 const QUrl tempUrl
= QUrl::fromLocalFile(QStandardPaths::writableLocation(QStandardPaths::TempLocation
));
697 QSignalSpy
itemsInsertedSpy(m_model
, &PlacesItemModel::itemsInserted
);
699 // create a new place
700 createPlaceItem(QStringLiteral("Temporary Dir"), tempUrl
, QString());
701 QTRY_COMPARE(itemsInsertedSpy
.count(), 1);
703 // check if the new entry was created
704 PlacesItemModel
*model
= new PlacesItemModel();
705 QTRY_COMPARE(model
->count(), m_model
->count());
707 // make sure that the new item will be removed later
708 schedulePlaceRemoval(tempDirIndex
);
710 // modify place metadata
711 PlacesItem
*item
= m_model
->placesItem(tempDirIndex
);
712 item
->bookmark().setMetaDataItem(QStringLiteral("OnlyInApp"), KAboutData::applicationData().componentName());
715 // check if the place was modified in both models
716 QTRY_COMPARE(model
->placesItem(tempDirIndex
)->bookmark().metaDataItem(QStringLiteral("OnlyInApp")),
717 KAboutData::applicationData().componentName());
718 QTRY_COMPARE(model
->placesItem(tempDirIndex
)->text(), m_model
->placesItem(tempDirIndex
)->text());
719 QTRY_COMPARE(model
->placesItem(tempDirIndex
)->bookmark().metaDataItem(QStringLiteral("OnlyInApp")),
720 m_model
->placesItem(tempDirIndex
)->bookmark().metaDataItem(QStringLiteral("OnlyInApp")));
721 QTRY_COMPARE(model
->placesItem(tempDirIndex
)->icon(), m_model
->placesItem(tempDirIndex
)->icon());
722 QTRY_COMPARE(model
->placesItem(tempDirIndex
)->url(), m_model
->placesItem(tempDirIndex
)->url());
725 void PlacesItemModelTest::testRefresh()
727 int tempDirIndex
= 2;
728 if (m_hasDesktopFolder
) {
731 if (m_hasDocumentsFolder
) {
734 if (m_hasDownloadsFolder
) {
738 const QUrl tempUrl
= QUrl::fromLocalFile(QStandardPaths::writableLocation(QStandardPaths::TempLocation
));
739 QSignalSpy
itemsInsertedSpy(m_model
, &PlacesItemModel::itemsInserted
);
741 // create a new place
742 createPlaceItem(QStringLiteral("Temporary Dir"), tempUrl
, QString());
743 QTRY_COMPARE(itemsInsertedSpy
.count(), 1);
745 PlacesItemModel
*model
= new PlacesItemModel();
746 QTRY_COMPARE(model
->count(), m_model
->count());
748 // make sure that the new item will be removed later
749 schedulePlaceRemoval(tempDirIndex
);
751 PlacesItem
*item
= m_model
->placesItem(tempDirIndex
);
752 PlacesItem
*sameItem
= model
->placesItem(tempDirIndex
);
753 QCOMPARE(item
->text(), sameItem
->text());
756 item
->setText(QStringLiteral("Renamed place"));
758 // item from another model is not affected at the moment
759 QVERIFY(item
->text() != sameItem
->text());
764 // item must be equal
765 QTRY_COMPARE(item
->text(), sameItem
->text());
768 void PlacesItemModelTest::testIcons_data()
770 QTest::addColumn
<QUrl
>("url");
771 QTest::addColumn
<QString
>("expectedIconName");
774 QTest::newRow("Places - Home") << QUrl::fromLocalFile(QDir::homePath()) << QStringLiteral("user-home");
777 QTest::newRow("Baloo - Documents") << QUrl("search:/documents") << QStringLiteral("folder-text");
780 QTest::newRow("Baloo - Today") << QUrl("timeline:/today") << QStringLiteral("go-jump-today");
783 QTest::newRow("Devices - Floppy") << QUrl("file:///media/floppy0") << QStringLiteral("blockdevice");
786 void PlacesItemModelTest::testIcons()
789 QFETCH(QString
, expectedIconName
);
791 PlacesItem
*item
= m_model
->placesItem(indexOf(url
));
792 QCOMPARE(item
->icon(), expectedIconName
);
794 for (int r
= 0; r
< m_model
->count(); r
++) {
795 QVERIFY(!m_model
->placesItem(r
)->icon().isEmpty());
799 void PlacesItemModelTest::testDragAndDrop()
801 int lastIndex
= 1; // last index of places group
802 if (m_hasDesktopFolder
) {
805 if (m_hasDocumentsFolder
) {
808 if (m_hasDownloadsFolder
) {
812 QList
<QVariant
> args
;
813 KItemRangeList range
;
814 QStringList urls
= initialUrls();
816 QSignalSpy
itemsInsertedSpy(m_model
, &PlacesItemModel::itemsInserted
);
817 QSignalSpy
itemsRemovedSpy(m_model
, &PlacesItemModel::itemsRemoved
);
819 CHECK_PLACES_URLS(initialUrls());
820 // Move the home directory to the end of the places group
821 QMimeData
*dropData
= createMimeData(QList
<int>() << 0);
822 m_model
->dropMimeDataBefore(m_model
->count() - 1, dropData
);
823 urls
.move(0, lastIndex
);
826 QTRY_COMPARE(itemsInsertedSpy
.count(), 1);
827 QTRY_COMPARE(itemsRemovedSpy
.count(), 1);
829 // remove item from actual position
830 args
= itemsRemovedSpy
.takeFirst();
831 range
= args
.at(0).value
<KItemRangeList
>();
832 QCOMPARE(range
.size(), 1);
833 QCOMPARE(range
.at(0).count
, 1);
834 QCOMPARE(range
.at(0).index
, 0);
836 // insert intem in his group
837 args
= itemsInsertedSpy
.takeFirst();
838 range
= args
.at(0).value
<KItemRangeList
>();
839 QCOMPARE(range
.size(), 1);
840 QCOMPARE(range
.at(0).count
, 1);
841 QCOMPARE(range
.at(0).index
, lastIndex
);
843 CHECK_PLACES_URLS(urls
);
845 itemsInsertedSpy
.clear();
846 itemsRemovedSpy
.clear();
848 // Move home directory item back to its original position
849 dropData
= createMimeData(QList
<int>() << lastIndex
);
850 m_model
->dropMimeDataBefore(0, dropData
);
851 urls
.move(lastIndex
, 0);
854 QTRY_COMPARE(itemsInsertedSpy
.count(), 1);
855 QTRY_COMPARE(itemsRemovedSpy
.count(), 1);
857 // remove item from actual position
858 args
= itemsRemovedSpy
.takeFirst();
859 range
= args
.at(0).value
<KItemRangeList
>();
860 QCOMPARE(range
.size(), 1);
861 QCOMPARE(range
.at(0).count
, 1);
862 QCOMPARE(range
.at(0).index
, lastIndex
);
864 // insert intem in the requested position
865 args
= itemsInsertedSpy
.takeFirst();
866 range
= args
.at(0).value
<KItemRangeList
>();
867 QCOMPARE(range
.size(), 1);
868 QCOMPARE(range
.at(0).count
, 1);
869 QCOMPARE(range
.at(0).index
, 0);
871 CHECK_PLACES_URLS(urls
);
874 void PlacesItemModelTest::testHideDevices()
876 QSignalSpy
itemsRemoved(m_model
, &PlacesItemModel::itemsRemoved
);
877 QStringList urls
= initialUrls();
879 m_model
->setGroupHidden(KFilePlacesModel::RemovableDevicesType
, true);
880 QTRY_VERIFY(m_model
->isGroupHidden(KFilePlacesModel::RemovableDevicesType
));
881 QTRY_COMPARE(itemsRemoved
.count(), 3);
883 // remove removable-devices
884 urls
.removeOne(QStringLiteral("/media/floppy0"));
885 urls
.removeOne(QStringLiteral("/media/XO-Y4"));
886 urls
.removeOne(QStringLiteral("/media/cdrom"));
888 // check if the correct urls was removed
889 CHECK_PLACES_URLS(urls
);
892 m_model
= new PlacesItemModel();
893 QTRY_COMPARE(m_model
->count(), urls
.count());
894 CHECK_PLACES_URLS(urls
);
897 m_model
->setGroupHidden(KFilePlacesModel::RemovableDevicesType
, false);
898 urls
= initialUrls();
899 QTRY_COMPARE(m_model
->count(), urls
.count());
900 CHECK_PLACES_URLS(urls
);
903 void PlacesItemModelTest::testDuplicatedEntries()
905 QStringList urls
= initialUrls();
906 // create a duplicated entry on bookmark
907 KBookmarkManager
*bookmarkManager
= KBookmarkManager::managerForFile(bookmarksFile(), QStringLiteral("kfilePlaces"));
908 KBookmarkGroup root
= bookmarkManager
->root();
909 KBookmark bookmark
= root
.addBookmark(QStringLiteral("Duplicated Search Videos"), QUrl("search:/videos"), {});
911 const QString id
= QUuid::createUuid().toString();
912 bookmark
.setMetaDataItem(QStringLiteral("ID"), id
);
913 bookmark
.setMetaDataItem(QStringLiteral("OnlyInApp"), KAboutData::applicationData().componentName());
914 bookmarkManager
->emitChanged(bookmarkManager
->root());
916 PlacesItemModel
*newModel
= new PlacesItemModel();
917 QTRY_COMPARE(placesUrls(newModel
).count(QStringLiteral("search:/videos")), 1);
918 QTRY_COMPARE(urls
, placesUrls(newModel
));
922 void PlacesItemModelTest::renameAfterCreation()
924 int tempDirIndex
= 2;
925 if (m_hasDesktopFolder
) {
928 if (m_hasDocumentsFolder
) {
931 if (m_hasDownloadsFolder
) {
935 const QUrl tempUrl
= QUrl::fromLocalFile(QStandardPaths::writableLocation(QStandardPaths::TempLocation
));
936 QStringList urls
= initialUrls();
937 PlacesItemModel
*model
= new PlacesItemModel();
939 CHECK_PLACES_URLS(urls
);
940 QTRY_COMPARE(model
->count(), m_model
->count());
942 // create a new place
943 createPlaceItem(QStringLiteral("Temporary Dir"), tempUrl
, QString());
944 urls
.insert(tempDirIndex
, tempUrl
.toLocalFile());
946 // make sure that the new item will be removed later
947 schedulePlaceRemoval(tempDirIndex
);
949 CHECK_PLACES_URLS(urls
);
950 QCOMPARE(model
->count(), m_model
->count());
954 QSignalSpy
changedSpy(m_model
, &PlacesItemModel::itemsChanged
);
956 PlacesItem
*item
= m_model
->placesItem(tempDirIndex
);
957 item
->setText(QStringLiteral("New Temporary Dir"));
958 item
->setUrl(item
->url());
959 item
->setIcon(item
->icon());
962 QTRY_COMPARE(changedSpy
.count(), 1);
964 // check if the place was modified in both models
965 QTRY_COMPARE(m_model
->placesItem(tempDirIndex
)->text(), QStringLiteral("New Temporary Dir"));
966 QTRY_COMPARE(model
->placesItem(tempDirIndex
)->text(), QStringLiteral("New Temporary Dir"));
969 QTEST_MAIN(PlacesItemModelTest
)
971 #include "placesitemmodeltest.moc"