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