]> cloud.milkyroute.net Git - dolphin.git/blob - src/tests/placesitemmodeltest.cpp
Remove unused #include
[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 for (int i : m_tobeRemoved) {
232 int before = m_model->count();
233 m_model->deleteItem(i);
234 QTRY_COMPARE(m_model->count(), before - 1);
235 }
236 m_tobeRemoved.clear();
237 delete m_model;
238 m_model = nullptr;
239 removeTestUserData();
240 }
241
242 void PlacesItemModelTest::initTestCase()
243 {
244 QStandardPaths::setTestModeEnabled(true);
245 // remove test user data
246 removeTestUserData();
247
248 const QString fakeHw = QFINDTESTDATA("data/fakecomputer.xml");
249 QVERIFY(!fakeHw.isEmpty());
250 qputenv("SOLID_FAKEHW", QFile::encodeName(fakeHw));
251
252 setBalooEnabled(true);
253 const QString bookmarsFileName = bookmarksFile();
254 if (QFileInfo::exists(bookmarsFileName)) {
255 // Ensure we'll have a clean bookmark file to start
256 QVERIFY(QFile::remove(bookmarsFileName));
257 }
258
259 qRegisterMetaType<KItemRangeList>();
260 qRegisterMetaType<KItemRange>();
261 }
262
263 void PlacesItemModelTest::cleanupTestCase()
264 {
265 qDeleteAll(m_interfacesMap);
266 QFile::remove(bookmarksFile());
267
268 // Remove any previous properties file
269 removeTestUserData();
270 }
271
272 void PlacesItemModelTest::testModelSort()
273 {
274 CHECK_PLACES_URLS(initialUrls());
275 }
276
277 void PlacesItemModelTest::testGroups()
278 {
279 const auto groups = m_model->groups();
280
281 QCOMPARE(groups.size(), 6);
282
283 QCOMPARE(groups.at(0).first, 0);
284 QCOMPARE(groups.at(0).second.toString(), QStringLiteral("Places"));
285
286 QCOMPARE(groups.at(1).first, 3);
287 QCOMPARE(groups.at(1).second.toString(), QStringLiteral("Remote"));
288
289 QCOMPARE(groups.at(2).first, 4);
290 QCOMPARE(groups.at(2).second.toString(), QStringLiteral("Recently Saved"));
291
292 QCOMPARE(groups.at(3).first, 8);
293 QCOMPARE(groups.at(3).second.toString(), QStringLiteral("Search For"));
294
295 QCOMPARE(groups.at(4).first, 12);
296 QCOMPARE(groups.at(4).second.toString(), QStringLiteral("Devices"));
297
298 QCOMPARE(groups.at(5).first, 14);
299 QCOMPARE(groups.at(5).second.toString(), QStringLiteral("Removable Devices"));
300 }
301
302 void PlacesItemModelTest::testPlaceItem_data()
303 {
304 QTest::addColumn<QUrl>("url");
305 QTest::addColumn<bool>("expectedIsHidden");
306 QTest::addColumn<bool>("expectedIsSystemItem");
307 QTest::addColumn<QString>("expectedGroup");
308 QTest::addColumn<bool>("expectedStorageSetupNeeded");
309
310 // places
311 QTest::newRow("Places - Home") << QUrl::fromLocalFile(QDir::homePath()) << false << true << QStringLiteral("Places") << false;
312
313 // baloo -search
314 QTest::newRow("Baloo - Documents") << QUrl("search:/documents") << false << true << QStringLiteral("Search For") << false;
315
316 // baloo - timeline
317 QTest::newRow("Baloo - Last Month") << QUrl("timeline:/lastmonth") << false << true << QStringLiteral("Recently Saved") << false;
318
319 // devices
320 QTest::newRow("Devices - Floppy") << QUrl("file:///media/floppy0") << false << false << QStringLiteral("Removable Devices") << false;
321 }
322
323 void PlacesItemModelTest::testPlaceItem()
324 {
325 QFETCH(QUrl, url);
326 QFETCH(bool, expectedIsHidden);
327 QFETCH(bool, expectedIsSystemItem);
328 QFETCH(QString, expectedGroup);
329 QFETCH(bool, expectedStorageSetupNeeded);
330
331 const int index = indexOf(url);
332 PlacesItem *item = m_model->placesItem(index);
333 QCOMPARE(item->url(), url);
334 QCOMPARE(item->isHidden(), expectedIsHidden);
335 QCOMPARE(item->isSystemItem(), expectedIsSystemItem);
336 QCOMPARE(item->group(), expectedGroup);
337 QCOMPARE(item->storageSetupNeeded(), expectedStorageSetupNeeded);
338 }
339
340 void PlacesItemModelTest::testDeletePlace()
341 {
342 const QUrl tempUrl = QUrl::fromLocalFile(QStandardPaths::writableLocation(QStandardPaths::TempLocation));
343 QStringList urls = initialUrls();
344 QSignalSpy itemsInsertedSpy(m_model, &PlacesItemModel::itemsInserted);
345 QSignalSpy itemsRemovedSpy(m_model, &PlacesItemModel::itemsRemoved);
346
347 PlacesItemModel *model = new PlacesItemModel();
348
349 // create a new place
350 createPlaceItem(QStringLiteral("Temporary Dir"), tempUrl, QString());
351 urls.insert(3, tempUrl.toLocalFile());
352
353 // check if the new entry was created
354 QTRY_COMPARE(itemsInsertedSpy.count(), 1);
355 CHECK_PLACES_URLS(urls);
356 QTRY_COMPARE(model->count(), m_model->count());
357
358 // delete item
359 m_model->deleteItem(3);
360
361 // make sure that the new item is removed
362 QTRY_COMPARE(itemsRemovedSpy.count(), 1);
363 QTRY_COMPARE(m_model->count(), 17);
364 CHECK_PLACES_URLS(initialUrls());
365 QTRY_COMPARE(model->count(), m_model->count());
366 }
367
368 void PlacesItemModelTest::testTearDownDevice()
369 {
370 const QUrl mediaUrl = QUrl::fromLocalFile(QStringLiteral("/media/XO-Y4"));
371 int index = indexOf(mediaUrl);
372 QVERIFY(index != -1);
373
374 auto ejectAction = m_model->ejectAction(index);
375 QVERIFY(!ejectAction);
376
377 auto teardownAction = m_model->teardownAction(index);
378 QVERIFY(teardownAction);
379
380 QCOMPARE(m_model->count(), 17);
381
382 QSignalSpy spyItemsRemoved(m_model, &PlacesItemModel::itemsRemoved);
383 fakeManager()->call(QStringLiteral("unplug"), "/org/kde/solid/fakehw/volume_part1_size_993284096");
384 QTRY_COMPARE(m_model->count(), 16);
385 QCOMPARE(spyItemsRemoved.count(), 1);
386 const QList<QVariant> spyItemsRemovedArgs = spyItemsRemoved.takeFirst();
387 const KItemRangeList removedRange = spyItemsRemovedArgs.at(0).value<KItemRangeList>();
388 QCOMPARE(removedRange.size(), 1);
389 QCOMPARE(removedRange.first().index, index);
390 QCOMPARE(removedRange.first().count, 1);
391
392 QCOMPARE(indexOf(mediaUrl), -1);
393
394 QSignalSpy spyItemsInserted(m_model, &PlacesItemModel::itemsInserted);
395 fakeManager()->call(QStringLiteral("plug"), "/org/kde/solid/fakehw/volume_part1_size_993284096");
396 QTRY_COMPARE(m_model->count(), 17);
397 QCOMPARE(spyItemsInserted.count(), 1);
398 index = indexOf(mediaUrl);
399
400 const QList<QVariant> args = spyItemsInserted.takeFirst();
401 const KItemRangeList insertedRange = args.at(0).value<KItemRangeList>();
402 QCOMPARE(insertedRange.size(), 1);
403 QCOMPARE(insertedRange.first().index, index);
404 QCOMPARE(insertedRange.first().count, 1);
405 }
406
407 void PlacesItemModelTest::testDefaultViewProperties_data()
408 {
409 QTest::addColumn<QUrl>("url");
410 QTest::addColumn<DolphinView::Mode>("expectedViewMode");
411 QTest::addColumn<bool>("expectedPreviewShow");
412 QTest::addColumn<QList<QByteArray> >("expectedVisibleRole");
413
414 // places
415 QTest::newRow("Places - Home") << QUrl::fromLocalFile(QDir::homePath()) << DolphinView::IconsView << true << QList<QByteArray>({"text"});
416
417 // baloo -search
418 QTest::newRow("Baloo - Documents") << QUrl("search:/documents") << DolphinView::DetailsView << false << QList<QByteArray>({"text", "path"});
419
420 // audio files
421 QTest::newRow("Places - Audio") << QUrl("search:/audio") << DolphinView::DetailsView << false << QList<QByteArray>({"text", "artist", "album"});
422
423 // baloo - timeline
424 QTest::newRow("Baloo - Last Month") << QUrl("timeline:/lastmonth") << DolphinView::DetailsView << true << QList<QByteArray>({"text", "modificationtime"});
425
426 // devices
427 QTest::newRow("Devices - Floppy") << QUrl("file:///media/floppy0") << DolphinView::IconsView << true << QList<QByteArray>({"text"});
428
429 }
430
431 void PlacesItemModelTest::testDefaultViewProperties()
432 {
433 QFETCH(QUrl, url);
434 QFETCH(DolphinView::Mode, expectedViewMode);
435 QFETCH(bool, expectedPreviewShow);
436 QFETCH(QList<QByteArray>, expectedVisibleRole);
437
438 ViewProperties properties(KFilePlacesModel::convertedUrl(url));
439 QCOMPARE(properties.viewMode(), expectedViewMode);
440 QCOMPARE(properties.previewsShown(), expectedPreviewShow);
441 QCOMPARE(properties.visibleRoles(), expectedVisibleRole);
442 }
443
444 void PlacesItemModelTest::testClear()
445 {
446 QCOMPARE(m_model->count(), 17);
447 m_model->clear();
448 QCOMPARE(m_model->count(), 0);
449 QCOMPARE(m_model->hiddenCount(), 0);
450 m_model->refresh();
451 QTRY_COMPARE(m_model->count(), 17);
452 }
453
454 void PlacesItemModelTest::testHideItem()
455 {
456 const QUrl mediaUrl = QUrl::fromLocalFile(QStringLiteral("/media/XO-Y4"));
457 const int index = indexOf(mediaUrl);
458
459 PlacesItem *item = m_model->placesItem(index);
460
461 QSignalSpy spyItemsRemoved(m_model, &PlacesItemModel::itemsRemoved);
462 QList<QVariant> spyItemsRemovedArgs;
463 KItemRangeList removedRange;
464
465 QSignalSpy spyItemsInserted(m_model, &PlacesItemModel::itemsInserted);
466 QList<QVariant> spyItemsInsertedArgs;
467 KItemRangeList insertedRange;
468 QVERIFY(item);
469
470 // hide an item
471 item->setHidden(true);
472
473 // check if items removed was fired
474 QTRY_COMPARE(m_model->count(), 16);
475 QCOMPARE(spyItemsRemoved.count(), 1);
476 spyItemsRemovedArgs = spyItemsRemoved.takeFirst();
477 removedRange = spyItemsRemovedArgs.at(0).value<KItemRangeList>();
478 QCOMPARE(removedRange.size(), 1);
479 QCOMPARE(removedRange.first().index, index);
480 QCOMPARE(removedRange.first().count, 1);
481
482 // allow model to show hidden items
483 m_model->setHiddenItemsShown(true);
484
485 // check if the items inserted was fired
486 spyItemsInsertedArgs = spyItemsInserted.takeFirst();
487 insertedRange = spyItemsInsertedArgs.at(0).value<KItemRangeList>();
488 QCOMPARE(insertedRange.size(), 1);
489 QCOMPARE(insertedRange.first().index, index);
490 QCOMPARE(insertedRange.first().count, 1);
491
492 // mark item as visible
493 item = m_model->placesItem(index);
494 item->setHidden(false);
495
496 // mark model to hide invisible items
497 m_model->setHiddenItemsShown(true);
498
499 QTRY_COMPARE(m_model->count(), 17);
500 }
501
502 void PlacesItemModelTest::testSystemItems()
503 {
504 QCOMPARE(m_model->count(), 17);
505 for (int r = 0; r < m_model->count(); r++) {
506 QCOMPARE(m_model->placesItem(r)->isSystemItem(), !m_model->placesItem(r)->device().isValid());
507 }
508
509 QSignalSpy itemsInsertedSpy(m_model, &PlacesItemModel::itemsInserted);
510
511 // create a new entry (non system item)
512 createPlaceItem(QStringLiteral("Temporary Dir"), QUrl::fromLocalFile(QStandardPaths::writableLocation(QStandardPaths::TempLocation)), QString());
513
514 // check if the new entry was created
515 QTRY_COMPARE(itemsInsertedSpy.count(), 1);
516
517 // make sure the new place get removed
518 removePlaceAfter(3);
519
520 QList<QVariant> args = itemsInsertedSpy.takeFirst();
521 KItemRangeList range = args.at(0).value<KItemRangeList>();
522 QCOMPARE(range.first().index, 3);
523 QCOMPARE(range.first().count, 1);
524 QVERIFY(!m_model->placesItem(3)->isSystemItem());
525 QCOMPARE(m_model->count(), 18);
526
527 QTest::qWait(300);
528 // check if the removal signal is correct
529 QSignalSpy itemsRemovedSpy(m_model, &PlacesItemModel::itemsRemoved);
530 m_model->deleteItem(3);
531 QTRY_COMPARE(itemsRemovedSpy.count(), 1);
532 args = itemsRemovedSpy.takeFirst();
533 range = args.at(0).value<KItemRangeList>();
534 QCOMPARE(range.first().index, 3);
535 QCOMPARE(range.first().count, 1);
536 QTRY_COMPARE(m_model->count(), 17);
537
538 //cancel removal (it was removed above)
539 cancelPlaceRemoval(3);
540 }
541
542 void PlacesItemModelTest::testEditBookmark()
543 {
544 const QUrl tempUrl = QUrl::fromLocalFile(QStandardPaths::writableLocation(QStandardPaths::TempLocation));
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"