]> cloud.milkyroute.net Git - dolphin.git/blob - src/tests/placesitemmodeltest.cpp
Merge branch 'Applications/18.04'
[dolphin.git] / src / tests / placesitemmodeltest.cpp
1 /***************************************************************************
2 * Copyright (C) 2017 by Renato Araujo Oliveira <renato.araujo@kdab.com> *
3 * *
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. *
8 * *
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. *
13 * *
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 ***************************************************************************/
19
20 #include <QTest>
21 #include <QSignalSpy>
22 #include <QStandardPaths>
23 #include <QAction>
24 #include <QDBusInterface>
25
26 #include <KBookmarkManager>
27 #include <KConfig>
28 #include <KConfigGroup>
29 #include <KAboutData>
30 #include <KFilePlacesModel>
31
32 #include "panels/places/placesitemmodel.h"
33 #include "panels/places/placesitem.h"
34 #include "views/viewproperties.h"
35
36 Q_DECLARE_METATYPE(KItemRangeList)
37 Q_DECLARE_METATYPE(KItemRange)
38
39 #ifdef Q_OS_WIN
40 //c:\ as root for windows
41 #define KDE_ROOT_PATH "C:\\"
42 #else
43 #define KDE_ROOT_PATH "/"
44 #endif
45
46 static QString bookmarksFile()
47 {
48 return QStandardPaths::writableLocation(QStandardPaths::GenericDataLocation) + "/user-places.xbel";
49 }
50
51 class PlacesItemModelTest : public QObject
52 {
53 Q_OBJECT
54
55 private slots:
56 void init();
57 void cleanup();
58
59 void initTestCase();
60 void cleanupTestCase();
61
62 void testModelSort();
63 void testGroups();
64 void testDeletePlace();
65 void testPlaceItem_data();
66 void testPlaceItem();
67 void testTearDownDevice();
68 void testDefaultViewProperties_data();
69 void testDefaultViewProperties();
70 void testClear();
71 void testHideItem();
72 void testSystemItems();
73 void testEditBookmark();
74 void testEditAfterCreation();
75 void testEditMetadata();
76 void testRefresh();
77 void testIcons_data();
78 void testIcons();
79 void testDragAndDrop();
80 void testHideDevices();
81 void testDuplicatedEntries();
82 void renameAfterCreation();
83
84 private:
85 PlacesItemModel* m_model;
86 QSet<int> m_tobeRemoved;
87 QMap<QString, QDBusInterface *> m_interfacesMap;
88
89 void setBalooEnabled(bool enabled);
90 int indexOf(const QUrl &url);
91 QDBusInterface *fakeManager();
92 QDBusInterface *fakeDevice(const QString &udi);
93 QStringList placesUrls(PlacesItemModel *model = nullptr) const;
94 QStringList initialUrls() const;
95 void createPlaceItem(const QString &text, const QUrl &url, const QString &icon);
96 void removePlaceAfter(int index);
97 void cancelPlaceRemoval(int index);
98 void removeTestUserData();
99 QMimeData *createMimeData(const QList<int> &indexes) const;
100 };
101
102 #define CHECK_PLACES_URLS(urls) \
103 { \
104 QStringList places = placesUrls(); \
105 if (places != urls) { \
106 qWarning() << "Expected:" << urls; \
107 qWarning() << "Got:" << places; \
108 QCOMPARE(places, urls); \
109 } \
110 }
111
112 void PlacesItemModelTest::setBalooEnabled(bool enabled)
113 {
114 KConfig config(QStringLiteral("baloofilerc"));
115 KConfigGroup basicSettings = config.group("Basic Settings");
116 basicSettings.writeEntry("Indexing-Enabled", enabled);
117 config.sync();
118 }
119
120 int PlacesItemModelTest::indexOf(const QUrl &url)
121 {
122 for (int r = 0; r < m_model->count(); r++) {
123 if (m_model->placesItem(r)->url() == url) {
124 return r;
125 }
126 }
127 return -1;
128 }
129
130 QDBusInterface *PlacesItemModelTest::fakeManager()
131 {
132 return fakeDevice(QStringLiteral("/org/kde/solid/fakehw"));
133 }
134
135 QDBusInterface *PlacesItemModelTest::fakeDevice(const QString &udi)
136 {
137 if (m_interfacesMap.contains(udi)) {
138 return m_interfacesMap[udi];
139 }
140
141 QDBusInterface *iface = new QDBusInterface(QDBusConnection::sessionBus().baseService(), udi);
142 m_interfacesMap[udi] = iface;
143
144 return iface;
145 }
146
147 QStringList PlacesItemModelTest::placesUrls(PlacesItemModel *model) const
148 {
149 QStringList urls;
150 if (!model) {
151 model = m_model;
152 }
153
154 for (int row = 0; row < model->count(); ++row) {
155 urls << model->placesItem(row)->url().toDisplayString(QUrl::PreferLocalFile);
156 }
157 return urls;
158 }
159
160 QStringList PlacesItemModelTest::initialUrls() const
161 {
162 static QStringList urls;
163 if (urls.isEmpty()) {
164 urls << QDir::homePath() << QStringLiteral(KDE_ROOT_PATH) << QStringLiteral("trash:/")
165 << QStringLiteral("remote:/")
166 << QStringLiteral("timeline:/today") << QStringLiteral("timeline:/yesterday") << QStringLiteral("timeline:/thismonth") << QStringLiteral("timeline:/lastmonth")
167 << QStringLiteral("search:/documents") << QStringLiteral("search:/images") << QStringLiteral("search:/audio") << QStringLiteral("search:/videos")
168 << QStringLiteral("/media/nfs") << QStringLiteral("/foreign")
169 << QStringLiteral("/media/floppy0") << QStringLiteral("/media/XO-Y4") << QStringLiteral("/media/cdrom");
170 }
171 return urls;
172 }
173
174 void PlacesItemModelTest::createPlaceItem(const QString &text, const QUrl &url, const QString &icon)
175 {
176 m_model->createPlacesItem(text, url, icon);
177 }
178
179 void PlacesItemModelTest::removePlaceAfter(int index)
180 {
181 m_tobeRemoved.insert(index);
182 }
183
184 void PlacesItemModelTest::cancelPlaceRemoval(int index)
185 {
186 m_tobeRemoved.remove(index);
187 }
188
189 void PlacesItemModelTest::removeTestUserData()
190 {
191 // user hardcoded path to avoid removal of any user personal data
192 QDir dir(QStringLiteral("/home/renato/.qttest/share/placesitemmodeltest"));
193 if (dir.exists()) {
194 QVERIFY(dir.removeRecursively());
195 }
196 }
197
198 QMimeData *PlacesItemModelTest::createMimeData(const QList<int> &indexes) const
199 {
200 QByteArray itemData;
201 QDataStream stream(&itemData, QIODevice::WriteOnly);
202 QList<QUrl> urls;
203
204 for (int index : indexes) {
205 const QUrl itemUrl = m_model->placesItem(index)->url();
206 if (itemUrl.isValid()) {
207 urls << itemUrl;
208 }
209 stream << index;
210 }
211
212 QMimeData* mimeData = new QMimeData();
213 mimeData->setUrls(urls);
214 // copied from PlacesItemModel::internalMimeType()
215 const QString internalMimeType = "application/x-dolphinplacesmodel-" +
216 QString::number((qptrdiff)m_model);
217 mimeData->setData(internalMimeType, itemData);
218 return mimeData;
219 }
220
221 void PlacesItemModelTest::init()
222 {
223 m_model = new PlacesItemModel();
224 // WORKAROUND: need to wait for bookmark to load, check: PlacesItemModel::updateBookmarks
225 QTest::qWait(300);
226 QCOMPARE(m_model->count(), 17);
227 }
228
229 void PlacesItemModelTest::cleanup()
230 {
231 const auto tobeRemoved = m_tobeRemoved;
232 for (const int i : tobeRemoved) {
233 int before = m_model->count();
234 m_model->deleteItem(i);
235 QTRY_COMPARE(m_model->count(), before - 1);
236 }
237 m_tobeRemoved.clear();
238 delete m_model;
239 m_model = nullptr;
240 removeTestUserData();
241 }
242
243 void PlacesItemModelTest::initTestCase()
244 {
245 QStandardPaths::setTestModeEnabled(true);
246 // remove test user data
247 removeTestUserData();
248
249 const QString fakeHw = QFINDTESTDATA("data/fakecomputer.xml");
250 QVERIFY(!fakeHw.isEmpty());
251 qputenv("SOLID_FAKEHW", QFile::encodeName(fakeHw));
252
253 setBalooEnabled(true);
254 const QString bookmarsFileName = bookmarksFile();
255 if (QFileInfo::exists(bookmarsFileName)) {
256 // Ensure we'll have a clean bookmark file to start
257 QVERIFY(QFile::remove(bookmarsFileName));
258 }
259
260 qRegisterMetaType<KItemRangeList>();
261 qRegisterMetaType<KItemRange>();
262 }
263
264 void PlacesItemModelTest::cleanupTestCase()
265 {
266 qDeleteAll(m_interfacesMap);
267 QFile::remove(bookmarksFile());
268
269 // Remove any previous properties file
270 removeTestUserData();
271 }
272
273 void PlacesItemModelTest::testModelSort()
274 {
275 CHECK_PLACES_URLS(initialUrls());
276 }
277
278 void PlacesItemModelTest::testGroups()
279 {
280 const auto groups = m_model->groups();
281
282 QCOMPARE(groups.size(), 6);
283
284 QCOMPARE(groups.at(0).first, 0);
285 QCOMPARE(groups.at(0).second.toString(), QStringLiteral("Places"));
286
287 QCOMPARE(groups.at(1).first, 3);
288 QCOMPARE(groups.at(1).second.toString(), QStringLiteral("Remote"));
289
290 QCOMPARE(groups.at(2).first, 4);
291 QCOMPARE(groups.at(2).second.toString(), QStringLiteral("Recently Saved"));
292
293 QCOMPARE(groups.at(3).first, 8);
294 QCOMPARE(groups.at(3).second.toString(), QStringLiteral("Search For"));
295
296 QCOMPARE(groups.at(4).first, 12);
297 QCOMPARE(groups.at(4).second.toString(), QStringLiteral("Devices"));
298
299 QCOMPARE(groups.at(5).first, 14);
300 QCOMPARE(groups.at(5).second.toString(), QStringLiteral("Removable Devices"));
301 }
302
303 void PlacesItemModelTest::testPlaceItem_data()
304 {
305 QTest::addColumn<QUrl>("url");
306 QTest::addColumn<bool>("expectedIsHidden");
307 QTest::addColumn<bool>("expectedIsSystemItem");
308 QTest::addColumn<QString>("expectedGroup");
309 QTest::addColumn<bool>("expectedStorageSetupNeeded");
310
311 // places
312 QTest::newRow("Places - Home") << QUrl::fromLocalFile(QDir::homePath()) << false << true << QStringLiteral("Places") << false;
313
314 // baloo -search
315 QTest::newRow("Baloo - Documents") << QUrl("search:/documents") << false << true << QStringLiteral("Search For") << false;
316
317 // baloo - timeline
318 QTest::newRow("Baloo - Last Month") << QUrl("timeline:/lastmonth") << false << true << QStringLiteral("Recently Saved") << false;
319
320 // devices
321 QTest::newRow("Devices - Floppy") << QUrl("file:///media/floppy0") << false << false << QStringLiteral("Removable Devices") << false;
322 }
323
324 void PlacesItemModelTest::testPlaceItem()
325 {
326 QFETCH(QUrl, url);
327 QFETCH(bool, expectedIsHidden);
328 QFETCH(bool, expectedIsSystemItem);
329 QFETCH(QString, expectedGroup);
330 QFETCH(bool, expectedStorageSetupNeeded);
331
332 const int index = indexOf(url);
333 PlacesItem *item = m_model->placesItem(index);
334 QCOMPARE(item->url(), url);
335 QCOMPARE(item->isHidden(), expectedIsHidden);
336 QCOMPARE(item->isSystemItem(), expectedIsSystemItem);
337 QCOMPARE(item->group(), expectedGroup);
338 QCOMPARE(item->storageSetupNeeded(), expectedStorageSetupNeeded);
339 }
340
341 void PlacesItemModelTest::testDeletePlace()
342 {
343 const QUrl tempUrl = QUrl::fromLocalFile(QStandardPaths::writableLocation(QStandardPaths::TempLocation));
344 QStringList urls = initialUrls();
345 QSignalSpy itemsInsertedSpy(m_model, &PlacesItemModel::itemsInserted);
346 QSignalSpy itemsRemovedSpy(m_model, &PlacesItemModel::itemsRemoved);
347
348 PlacesItemModel *model = new PlacesItemModel();
349
350 // create a new place
351 createPlaceItem(QStringLiteral("Temporary Dir"), tempUrl, QString());
352 urls.insert(3, tempUrl.toLocalFile());
353
354 // check if the new entry was created
355 QTRY_COMPARE(itemsInsertedSpy.count(), 1);
356 CHECK_PLACES_URLS(urls);
357 QTRY_COMPARE(model->count(), m_model->count());
358
359 // delete item
360 m_model->deleteItem(3);
361
362 // make sure that the new item is removed
363 QTRY_COMPARE(itemsRemovedSpy.count(), 1);
364 QTRY_COMPARE(m_model->count(), 17);
365 CHECK_PLACES_URLS(initialUrls());
366 QTRY_COMPARE(model->count(), m_model->count());
367 }
368
369 void PlacesItemModelTest::testTearDownDevice()
370 {
371 const QUrl mediaUrl = QUrl::fromLocalFile(QStringLiteral("/media/XO-Y4"));
372 int index = indexOf(mediaUrl);
373 QVERIFY(index != -1);
374
375 auto ejectAction = m_model->ejectAction(index);
376 QVERIFY(!ejectAction);
377
378 auto teardownAction = m_model->teardownAction(index);
379 QVERIFY(teardownAction);
380
381 QCOMPARE(m_model->count(), 17);
382
383 QSignalSpy spyItemsRemoved(m_model, &PlacesItemModel::itemsRemoved);
384 fakeManager()->call(QStringLiteral("unplug"), "/org/kde/solid/fakehw/volume_part1_size_993284096");
385 QTRY_COMPARE(m_model->count(), 16);
386 QCOMPARE(spyItemsRemoved.count(), 1);
387 const QList<QVariant> spyItemsRemovedArgs = spyItemsRemoved.takeFirst();
388 const KItemRangeList removedRange = spyItemsRemovedArgs.at(0).value<KItemRangeList>();
389 QCOMPARE(removedRange.size(), 1);
390 QCOMPARE(removedRange.first().index, index);
391 QCOMPARE(removedRange.first().count, 1);
392
393 QCOMPARE(indexOf(mediaUrl), -1);
394
395 QSignalSpy spyItemsInserted(m_model, &PlacesItemModel::itemsInserted);
396 fakeManager()->call(QStringLiteral("plug"), "/org/kde/solid/fakehw/volume_part1_size_993284096");
397 QTRY_COMPARE(m_model->count(), 17);
398 QCOMPARE(spyItemsInserted.count(), 1);
399 index = indexOf(mediaUrl);
400
401 const QList<QVariant> args = spyItemsInserted.takeFirst();
402 const KItemRangeList insertedRange = args.at(0).value<KItemRangeList>();
403 QCOMPARE(insertedRange.size(), 1);
404 QCOMPARE(insertedRange.first().index, index);
405 QCOMPARE(insertedRange.first().count, 1);
406 }
407
408 void PlacesItemModelTest::testDefaultViewProperties_data()
409 {
410 QTest::addColumn<QUrl>("url");
411 QTest::addColumn<DolphinView::Mode>("expectedViewMode");
412 QTest::addColumn<bool>("expectedPreviewShow");
413 QTest::addColumn<QList<QByteArray> >("expectedVisibleRole");
414
415 // places
416 QTest::newRow("Places - Home") << QUrl::fromLocalFile(QDir::homePath()) << DolphinView::IconsView << true << QList<QByteArray>({"text"});
417
418 // baloo -search
419 QTest::newRow("Baloo - Documents") << QUrl("search:/documents") << DolphinView::DetailsView << false << QList<QByteArray>({"text", "path"});
420
421 // audio files
422 QTest::newRow("Places - Audio") << QUrl("search:/audio") << DolphinView::DetailsView << false << QList<QByteArray>({"text", "artist", "album"});
423
424 // baloo - timeline
425 QTest::newRow("Baloo - Last Month") << QUrl("timeline:/lastmonth") << DolphinView::DetailsView << true << QList<QByteArray>({"text", "modificationtime"});
426
427 // devices
428 QTest::newRow("Devices - Floppy") << QUrl("file:///media/floppy0") << DolphinView::IconsView << true << QList<QByteArray>({"text"});
429
430 }
431
432 void PlacesItemModelTest::testDefaultViewProperties()
433 {
434 QFETCH(QUrl, url);
435 QFETCH(DolphinView::Mode, expectedViewMode);
436 QFETCH(bool, expectedPreviewShow);
437 QFETCH(QList<QByteArray>, expectedVisibleRole);
438
439 ViewProperties properties(KFilePlacesModel::convertedUrl(url));
440 QCOMPARE(properties.viewMode(), expectedViewMode);
441 QCOMPARE(properties.previewsShown(), expectedPreviewShow);
442 QCOMPARE(properties.visibleRoles(), expectedVisibleRole);
443 }
444
445 void PlacesItemModelTest::testClear()
446 {
447 QCOMPARE(m_model->count(), 17);
448 m_model->clear();
449 QCOMPARE(m_model->count(), 0);
450 QCOMPARE(m_model->hiddenCount(), 0);
451 m_model->refresh();
452 QTRY_COMPARE(m_model->count(), 17);
453 }
454
455 void PlacesItemModelTest::testHideItem()
456 {
457 const QUrl mediaUrl = QUrl::fromLocalFile(QStringLiteral("/media/XO-Y4"));
458 const int index = indexOf(mediaUrl);
459
460 PlacesItem *item = m_model->placesItem(index);
461
462 QSignalSpy spyItemsRemoved(m_model, &PlacesItemModel::itemsRemoved);
463 QList<QVariant> spyItemsRemovedArgs;
464 KItemRangeList removedRange;
465
466 QSignalSpy spyItemsInserted(m_model, &PlacesItemModel::itemsInserted);
467 QList<QVariant> spyItemsInsertedArgs;
468 KItemRangeList insertedRange;
469 QVERIFY(item);
470
471 // hide an item
472 item->setHidden(true);
473
474 // check if items removed was fired
475 QTRY_COMPARE(m_model->count(), 16);
476 QCOMPARE(spyItemsRemoved.count(), 1);
477 spyItemsRemovedArgs = spyItemsRemoved.takeFirst();
478 removedRange = spyItemsRemovedArgs.at(0).value<KItemRangeList>();
479 QCOMPARE(removedRange.size(), 1);
480 QCOMPARE(removedRange.first().index, index);
481 QCOMPARE(removedRange.first().count, 1);
482
483 // allow model to show hidden items
484 m_model->setHiddenItemsShown(true);
485
486 // check if the items inserted was fired
487 spyItemsInsertedArgs = spyItemsInserted.takeFirst();
488 insertedRange = spyItemsInsertedArgs.at(0).value<KItemRangeList>();
489 QCOMPARE(insertedRange.size(), 1);
490 QCOMPARE(insertedRange.first().index, index);
491 QCOMPARE(insertedRange.first().count, 1);
492
493 // mark item as visible
494 item = m_model->placesItem(index);
495 item->setHidden(false);
496
497 // mark model to hide invisible items
498 m_model->setHiddenItemsShown(true);
499
500 QTRY_COMPARE(m_model->count(), 17);
501 }
502
503 void PlacesItemModelTest::testSystemItems()
504 {
505 QCOMPARE(m_model->count(), 17);
506 for (int r = 0; r < m_model->count(); r++) {
507 QCOMPARE(m_model->placesItem(r)->isSystemItem(), !m_model->placesItem(r)->device().isValid());
508 }
509
510 QSignalSpy itemsInsertedSpy(m_model, &PlacesItemModel::itemsInserted);
511
512 // create a new entry (non system item)
513 createPlaceItem(QStringLiteral("Temporary Dir"), QUrl::fromLocalFile(QStandardPaths::writableLocation(QStandardPaths::TempLocation)), QString());
514
515 // check if the new entry was created
516 QTRY_COMPARE(itemsInsertedSpy.count(), 1);
517
518 // make sure the new place get removed
519 removePlaceAfter(3);
520
521 QList<QVariant> args = itemsInsertedSpy.takeFirst();
522 KItemRangeList range = args.at(0).value<KItemRangeList>();
523 QCOMPARE(range.first().index, 3);
524 QCOMPARE(range.first().count, 1);
525 QVERIFY(!m_model->placesItem(3)->isSystemItem());
526 QCOMPARE(m_model->count(), 18);
527
528 QTest::qWait(300);
529 // check if the removal signal is correct
530 QSignalSpy itemsRemovedSpy(m_model, &PlacesItemModel::itemsRemoved);
531 m_model->deleteItem(3);
532 QTRY_COMPARE(itemsRemovedSpy.count(), 1);
533 args = itemsRemovedSpy.takeFirst();
534 range = args.at(0).value<KItemRangeList>();
535 QCOMPARE(range.first().index, 3);
536 QCOMPARE(range.first().count, 1);
537 QTRY_COMPARE(m_model->count(), 17);
538
539 //cancel removal (it was removed above)
540 cancelPlaceRemoval(3);
541 }
542
543 void PlacesItemModelTest::testEditBookmark()
544 {
545 QScopedPointer<PlacesItemModel> other(new PlacesItemModel());
546
547 createPlaceItem(QStringLiteral("Temporary Dir"), QUrl::fromLocalFile(QStandardPaths::writableLocation(QStandardPaths::TempLocation)), QString());
548
549 // make sure that the new item will be removed later
550 removePlaceAfter(3);
551
552 QSignalSpy itemsChangedSply(m_model, &PlacesItemModel::itemsChanged);
553
554 // modify place text
555 m_model->item(3)->setText(QStringLiteral("Renamed place"));
556 m_model->refresh();
557
558 // check if the correct signal was fired
559 QTRY_COMPARE(itemsChangedSply.count(), 1);
560 QList<QVariant> args = itemsChangedSply.takeFirst();
561 KItemRangeList range = args.at(0).value<KItemRangeList>();
562 QCOMPARE(range.first().index, 3);
563 QCOMPARE(range.first().count, 1);
564 QSet<QByteArray> roles = args.at(1).value<QSet<QByteArray> >();
565 QCOMPARE(roles.size(), 1);
566 QCOMPARE(*roles.begin(), QByteArrayLiteral("text"));
567 QCOMPARE(m_model->item(3)->text(), QStringLiteral("Renamed place"));
568
569 // check if the item was updated in the other model
570 QTRY_COMPARE(other->item(3)->text(), QStringLiteral("Renamed place"));
571 }
572
573 void PlacesItemModelTest::testEditAfterCreation()
574 {
575 const QUrl tempUrl = QUrl::fromLocalFile(QStandardPaths::writableLocation(QStandardPaths::TempLocation));
576 QSignalSpy itemsInsertedSpy(m_model, &PlacesItemModel::itemsInserted);
577
578 // create a new place
579 createPlaceItem(QStringLiteral("Temporary Dir"), tempUrl, QString());
580 QTRY_COMPARE(itemsInsertedSpy.count(), 1);
581
582 PlacesItemModel *model = new PlacesItemModel();
583 QTRY_COMPARE(model->count(), m_model->count());
584
585 // make sure that the new item will be removed later
586 removePlaceAfter(3);
587
588 // modify place text
589 PlacesItem *item = m_model->placesItem(3);
590 item->setText(QStringLiteral("Renamed place"));
591 m_model->refresh();
592
593 // check if the second model got the changes
594 QTRY_COMPARE(model->count(), m_model->count());
595 QTRY_COMPARE(model->placesItem(3)->text(), m_model->placesItem(3)->text());
596 QTRY_COMPARE(model->placesItem(3)->bookmark().metaDataItem(QStringLiteral("OnlyInApp")),
597 m_model->placesItem(3)->bookmark().metaDataItem(QStringLiteral("OnlyInApp")));
598 QTRY_COMPARE(model->placesItem(3)->icon(), m_model->placesItem(3)->icon());
599 QTRY_COMPARE(model->placesItem(3)->url(), m_model->placesItem(3)->url());
600 }
601
602 void PlacesItemModelTest::testEditMetadata()
603 {
604 const QUrl tempUrl = QUrl::fromLocalFile(QStandardPaths::writableLocation(QStandardPaths::TempLocation));
605 QSignalSpy itemsInsertedSpy(m_model, &PlacesItemModel::itemsInserted);
606
607 // create a new place
608 createPlaceItem(QStringLiteral("Temporary Dir"), tempUrl, QString());
609 QTRY_COMPARE(itemsInsertedSpy.count(), 1);
610
611 // check if the new entry was created
612 PlacesItemModel *model = new PlacesItemModel();
613 QTRY_COMPARE(model->count(), m_model->count());
614
615 // make sure that the new item will be removed later
616 removePlaceAfter(3);
617
618 // modify place metadata
619 PlacesItem *item = m_model->placesItem(3);
620 item->bookmark().setMetaDataItem(QStringLiteral("OnlyInApp"), KAboutData::applicationData().componentName());
621 m_model->refresh();
622
623 // check if the place was modified in both models
624 QTRY_COMPARE(model->placesItem(3)->bookmark().metaDataItem(QStringLiteral("OnlyInApp")),
625 KAboutData::applicationData().componentName());
626 QTRY_COMPARE(model->placesItem(3)->text(), m_model->placesItem(3)->text());
627 QTRY_COMPARE(model->placesItem(3)->bookmark().metaDataItem(QStringLiteral("OnlyInApp")),
628 m_model->placesItem(3)->bookmark().metaDataItem(QStringLiteral("OnlyInApp")));
629 QTRY_COMPARE(model->placesItem(3)->icon(), m_model->placesItem(3)->icon());
630 QTRY_COMPARE(model->placesItem(3)->url(), m_model->placesItem(3)->url());
631 }
632
633 void PlacesItemModelTest::testRefresh()
634 {
635 const QUrl tempUrl = QUrl::fromLocalFile(QStandardPaths::writableLocation(QStandardPaths::TempLocation));
636 QSignalSpy itemsInsertedSpy(m_model, &PlacesItemModel::itemsInserted);
637
638 // create a new place
639 createPlaceItem(QStringLiteral("Temporary Dir"), tempUrl, QString());
640 QTRY_COMPARE(itemsInsertedSpy.count(), 1);
641
642 PlacesItemModel *model = new PlacesItemModel();
643 QTRY_COMPARE(model->count(), m_model->count());
644
645 // make sure that the new item will be removed later
646 removePlaceAfter(3);
647
648 PlacesItem *item = m_model->placesItem(3);
649 PlacesItem *sameItem = model->placesItem(3);
650 QCOMPARE(item->text(), sameItem->text());
651
652 // modify place text
653 item->setText(QStringLiteral("Renamed place"));
654
655 // item from another model is not affected at the moment
656 QVERIFY(item->text() != sameItem->text());
657
658 // propagate change
659 m_model->refresh();
660
661 // item must be equal
662 QTRY_COMPARE(item->text(), sameItem->text());
663 }
664
665 void PlacesItemModelTest::testIcons_data()
666 {
667 QTest::addColumn<QUrl>("url");
668 QTest::addColumn<QString>("expectedIconName");
669
670 // places
671 QTest::newRow("Places - Home") << QUrl::fromLocalFile(QDir::homePath()) << QStringLiteral("user-home");
672
673 // baloo -search
674 QTest::newRow("Baloo - Documents") << QUrl("search:/documents") << QStringLiteral("folder-text");
675
676 // baloo - timeline
677 QTest::newRow("Baloo - Last Month") << QUrl("timeline:/lastmonth") << QStringLiteral("view-calendar-month");
678
679 // devices
680 QTest::newRow("Devices - Floppy") << QUrl("file:///media/floppy0") << QStringLiteral("blockdevice");
681 }
682
683 void PlacesItemModelTest::testIcons()
684 {
685 QFETCH(QUrl, url);
686 QFETCH(QString, expectedIconName);
687
688 PlacesItem *item = m_model->placesItem(indexOf(url));
689 QCOMPARE(item->icon(), expectedIconName);
690
691 for (int r = 0; r < m_model->count(); r++) {
692 QVERIFY(!m_model->placesItem(r)->icon().isEmpty());
693 }
694 }
695
696 void PlacesItemModelTest::testDragAndDrop()
697 {
698 QList<QVariant> args;
699 KItemRangeList range;
700 QStringList urls = initialUrls();
701 QSignalSpy itemsInsertedSpy(m_model, &PlacesItemModel::itemsInserted);
702 QSignalSpy itemsRemovedSpy(m_model, &PlacesItemModel::itemsRemoved);
703
704 CHECK_PLACES_URLS(initialUrls());
705 // Move the KDE_ROOT_PATH at the end of the places list will case it to be moved to the end of the places group
706 QMimeData *dropData = createMimeData(QList<int>() << 1);
707 m_model->dropMimeDataBefore(m_model->count() - 1, dropData);
708 urls.move(1, 2);
709 delete dropData;
710
711 QTRY_COMPARE(itemsInsertedSpy.count(), 1);
712 QTRY_COMPARE(itemsRemovedSpy.count(), 1);
713
714 // remove item from actual position
715 args = itemsRemovedSpy.takeFirst();
716 range = args.at(0).value<KItemRangeList>();
717 QCOMPARE(range.size(), 1);
718 QCOMPARE(range.at(0).count, 1);
719 QCOMPARE(range.at(0).index, 1);
720
721 // insert intem in his group
722 args = itemsInsertedSpy.takeFirst();
723 range = args.at(0).value<KItemRangeList>();
724 QCOMPARE(range.size(), 1);
725 QCOMPARE(range.at(0).count, 1);
726 QCOMPARE(range.at(0).index, 2);
727
728 CHECK_PLACES_URLS(urls);
729
730 itemsInsertedSpy.clear();
731 itemsRemovedSpy.clear();
732
733 // Move the KDE_ROOT_PATH to his original position
734 dropData = createMimeData(QList<int>() << 2);
735 m_model->dropMimeDataBefore(1, dropData);
736 urls.move(2, 1);
737 delete dropData;
738
739 QTRY_COMPARE(itemsInsertedSpy.count(), 1);
740 QTRY_COMPARE(itemsRemovedSpy.count(), 1);
741
742 // remove item from actual position
743 args = itemsRemovedSpy.takeFirst();
744 range = args.at(0).value<KItemRangeList>();
745 QCOMPARE(range.size(), 1);
746 QCOMPARE(range.at(0).count, 1);
747 QCOMPARE(range.at(0).index, 2);
748
749 // insert intem in the requested position
750 args = itemsInsertedSpy.takeFirst();
751 range = args.at(0).value<KItemRangeList>();
752 QCOMPARE(range.size(), 1);
753 QCOMPARE(range.at(0).count, 1);
754 QCOMPARE(range.at(0).index, 1);
755
756 CHECK_PLACES_URLS(urls);
757 }
758
759 void PlacesItemModelTest::testHideDevices()
760 {
761 QSignalSpy itemsRemoved(m_model, &PlacesItemModel::itemsRemoved);
762 QStringList urls = initialUrls();
763
764 m_model->setGroupHidden(KFilePlacesModel::RemovableDevicesType, true);
765 QTRY_VERIFY(m_model->isGroupHidden(KFilePlacesModel::RemovableDevicesType));
766 QTRY_COMPARE(itemsRemoved.count(), 3);
767
768 // remove removable-devices
769 urls.removeOne(QStringLiteral("/media/floppy0"));
770 urls.removeOne(QStringLiteral("/media/XO-Y4"));
771 urls.removeOne(QStringLiteral("/media/cdrom"));
772
773 // check if the correct urls was removed
774 CHECK_PLACES_URLS(urls);
775
776 delete m_model;
777 m_model = new PlacesItemModel();
778 QTRY_COMPARE(m_model->count(), urls.count());
779 CHECK_PLACES_URLS(urls);
780
781 // revert changes
782 m_model->setGroupHidden(KFilePlacesModel::RemovableDevicesType, false);
783 urls = initialUrls();
784 QTRY_COMPARE(m_model->count(), urls.count());
785 CHECK_PLACES_URLS(urls);
786 }
787
788 void PlacesItemModelTest::testDuplicatedEntries()
789 {
790 QStringList urls = initialUrls();
791 // create a duplicated entry on bookmark
792 KBookmarkManager *bookmarkManager = KBookmarkManager::managerForFile(bookmarksFile(), QStringLiteral("kfilePlaces"));
793 KBookmarkGroup root = bookmarkManager->root();
794 KBookmark bookmark = root.addBookmark(QStringLiteral("Duplicated Search Videos"), QUrl("search:/videos"), {});
795
796 const QString id = QUuid::createUuid().toString();
797 bookmark.setMetaDataItem(QStringLiteral("ID"), id);
798 bookmark.setMetaDataItem(QStringLiteral("OnlyInApp"), KAboutData::applicationData().componentName());
799 bookmarkManager->emitChanged(bookmarkManager->root());
800
801 PlacesItemModel *newModel = new PlacesItemModel();
802 QTRY_COMPARE(placesUrls(newModel).count(QStringLiteral("search:/videos")), 1);
803 QTRY_COMPARE(urls, placesUrls(newModel));
804 delete newModel;
805 }
806
807 void PlacesItemModelTest::renameAfterCreation()
808 {
809 const QUrl tempUrl = QUrl::fromLocalFile(QStandardPaths::writableLocation(QStandardPaths::TempLocation));
810 QStringList urls = initialUrls();
811 PlacesItemModel *model = new PlacesItemModel();
812
813 CHECK_PLACES_URLS(urls);
814 QTRY_COMPARE(model->count(), m_model->count());
815
816 // create a new place
817 createPlaceItem(QStringLiteral("Temporary Dir"), tempUrl, QString());
818 urls.insert(3, tempUrl.toLocalFile());
819
820 // make sure that the new item will be removed later
821 removePlaceAfter(3);
822
823 CHECK_PLACES_URLS(urls);
824 QCOMPARE(model->count(), m_model->count());
825
826
827 // modify place text
828 QSignalSpy changedSpy(m_model, &PlacesItemModel::itemsChanged);
829
830 PlacesItem *item = m_model->placesItem(3);
831 item->setText(QStringLiteral("New Temporary Dir"));
832 item->setUrl(item->url());
833 item->setIcon(item->icon());
834 m_model->refresh();
835
836 QTRY_COMPARE(changedSpy.count(), 1);
837
838 // check if the place was modified in both models
839 QTRY_COMPARE(m_model->placesItem(3)->text(), QStringLiteral("New Temporary Dir"));
840 QTRY_COMPARE(model->placesItem(3)->text(), QStringLiteral("New Temporary Dir"));
841 }
842
843 QTEST_MAIN(PlacesItemModelTest)
844
845 #include "placesitemmodeltest.moc"