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