]> cloud.milkyroute.net Git - dolphin.git/blob - src/tests/placesitemmodeltest.cpp
Add missing i18n call
[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 QScopedPointer<PlacesItemModel> other(new PlacesItemModel());
545
546 createPlaceItem(QStringLiteral("Temporary Dir"), QUrl::fromLocalFile(QStandardPaths::writableLocation(QStandardPaths::TempLocation)), QString());
547
548 // make sure that the new item will be removed later
549 removePlaceAfter(3);
550
551 QSignalSpy itemsChangedSply(m_model, &PlacesItemModel::itemsChanged);
552
553 // modify place text
554 m_model->item(3)->setText(QStringLiteral("Renamed place"));
555 m_model->refresh();
556
557 // check if the correct signal was fired
558 QTRY_COMPARE(itemsChangedSply.count(), 1);
559 QList<QVariant> args = itemsChangedSply.takeFirst();
560 KItemRangeList range = args.at(0).value<KItemRangeList>();
561 QCOMPARE(range.first().index, 3);
562 QCOMPARE(range.first().count, 1);
563 QSet<QByteArray> roles = args.at(1).value<QSet<QByteArray> >();
564 QCOMPARE(roles.size(), 1);
565 QCOMPARE(*roles.begin(), QByteArrayLiteral("text"));
566 QCOMPARE(m_model->item(3)->text(), QStringLiteral("Renamed place"));
567
568 // check if the item was updated in the other model
569 QTRY_COMPARE(other->item(3)->text(), QStringLiteral("Renamed place"));
570 }
571
572 void PlacesItemModelTest::testEditAfterCreation()
573 {
574 const QUrl tempUrl = QUrl::fromLocalFile(QStandardPaths::writableLocation(QStandardPaths::TempLocation));
575 QSignalSpy itemsInsertedSpy(m_model, &PlacesItemModel::itemsInserted);
576
577 // create a new place
578 createPlaceItem(QStringLiteral("Temporary Dir"), tempUrl, QString());
579 QTRY_COMPARE(itemsInsertedSpy.count(), 1);
580
581 PlacesItemModel *model = new PlacesItemModel();
582 QTRY_COMPARE(model->count(), m_model->count());
583
584 // make sure that the new item will be removed later
585 removePlaceAfter(3);
586
587 // modify place text
588 PlacesItem *item = m_model->placesItem(3);
589 item->setText(QStringLiteral("Renamed place"));
590 m_model->refresh();
591
592 // check if the second model got the changes
593 QTRY_COMPARE(model->count(), m_model->count());
594 QTRY_COMPARE(model->placesItem(3)->text(), m_model->placesItem(3)->text());
595 QTRY_COMPARE(model->placesItem(3)->bookmark().metaDataItem(QStringLiteral("OnlyInApp")),
596 m_model->placesItem(3)->bookmark().metaDataItem(QStringLiteral("OnlyInApp")));
597 QTRY_COMPARE(model->placesItem(3)->icon(), m_model->placesItem(3)->icon());
598 QTRY_COMPARE(model->placesItem(3)->url(), m_model->placesItem(3)->url());
599 }
600
601 void PlacesItemModelTest::testEditMetadata()
602 {
603 const QUrl tempUrl = QUrl::fromLocalFile(QStandardPaths::writableLocation(QStandardPaths::TempLocation));
604 QSignalSpy itemsInsertedSpy(m_model, &PlacesItemModel::itemsInserted);
605
606 // create a new place
607 createPlaceItem(QStringLiteral("Temporary Dir"), tempUrl, QString());
608 QTRY_COMPARE(itemsInsertedSpy.count(), 1);
609
610 // check if the new entry was created
611 PlacesItemModel *model = new PlacesItemModel();
612 QTRY_COMPARE(model->count(), m_model->count());
613
614 // make sure that the new item will be removed later
615 removePlaceAfter(3);
616
617 // modify place metadata
618 PlacesItem *item = m_model->placesItem(3);
619 item->bookmark().setMetaDataItem(QStringLiteral("OnlyInApp"), KAboutData::applicationData().componentName());
620 m_model->refresh();
621
622 // check if the place was modified in both models
623 QTRY_COMPARE(model->placesItem(3)->bookmark().metaDataItem(QStringLiteral("OnlyInApp")),
624 KAboutData::applicationData().componentName());
625 QTRY_COMPARE(model->placesItem(3)->text(), m_model->placesItem(3)->text());
626 QTRY_COMPARE(model->placesItem(3)->bookmark().metaDataItem(QStringLiteral("OnlyInApp")),
627 m_model->placesItem(3)->bookmark().metaDataItem(QStringLiteral("OnlyInApp")));
628 QTRY_COMPARE(model->placesItem(3)->icon(), m_model->placesItem(3)->icon());
629 QTRY_COMPARE(model->placesItem(3)->url(), m_model->placesItem(3)->url());
630 }
631
632 void PlacesItemModelTest::testRefresh()
633 {
634 const QUrl tempUrl = QUrl::fromLocalFile(QStandardPaths::writableLocation(QStandardPaths::TempLocation));
635 QSignalSpy itemsInsertedSpy(m_model, &PlacesItemModel::itemsInserted);
636
637 // create a new place
638 createPlaceItem(QStringLiteral("Temporary Dir"), tempUrl, QString());
639 QTRY_COMPARE(itemsInsertedSpy.count(), 1);
640
641 PlacesItemModel *model = new PlacesItemModel();
642 QTRY_COMPARE(model->count(), m_model->count());
643
644 // make sure that the new item will be removed later
645 removePlaceAfter(3);
646
647 PlacesItem *item = m_model->placesItem(3);
648 PlacesItem *sameItem = model->placesItem(3);
649 QCOMPARE(item->text(), sameItem->text());
650
651 // modify place text
652 item->setText(QStringLiteral("Renamed place"));
653
654 // item from another model is not affected at the moment
655 QVERIFY(item->text() != sameItem->text());
656
657 // propagate change
658 m_model->refresh();
659
660 // item must be equal
661 QTRY_COMPARE(item->text(), sameItem->text());
662 }
663
664 void PlacesItemModelTest::testIcons_data()
665 {
666 QTest::addColumn<QUrl>("url");
667 QTest::addColumn<QString>("expectedIconName");
668
669 // places
670 QTest::newRow("Places - Home") << QUrl::fromLocalFile(QDir::homePath()) << QStringLiteral("user-home");
671
672 // baloo -search
673 QTest::newRow("Baloo - Documents") << QUrl("search:/documents") << QStringLiteral("folder-text");
674
675 // baloo - timeline
676 QTest::newRow("Baloo - Last Month") << QUrl("timeline:/lastmonth") << QStringLiteral("view-calendar-month");
677
678 // devices
679 QTest::newRow("Devices - Floppy") << QUrl("file:///media/floppy0") << QStringLiteral("blockdevice");
680 }
681
682 void PlacesItemModelTest::testIcons()
683 {
684 QFETCH(QUrl, url);
685 QFETCH(QString, expectedIconName);
686
687 PlacesItem *item = m_model->placesItem(indexOf(url));
688 QCOMPARE(item->icon(), expectedIconName);
689
690 for (int r = 0; r < m_model->count(); r++) {
691 QVERIFY(!m_model->placesItem(r)->icon().isEmpty());
692 }
693 }
694
695 void PlacesItemModelTest::testDragAndDrop()
696 {
697 QList<QVariant> args;
698 KItemRangeList range;
699 QStringList urls = initialUrls();
700 QSignalSpy itemsInsertedSpy(m_model, &PlacesItemModel::itemsInserted);
701 QSignalSpy itemsRemovedSpy(m_model, &PlacesItemModel::itemsRemoved);
702
703 CHECK_PLACES_URLS(initialUrls());
704 // 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
705 QMimeData *dropData = createMimeData(QList<int>() << 1);
706 m_model->dropMimeDataBefore(m_model->count() - 1, dropData);
707 urls.move(1, 2);
708 delete dropData;
709
710 QTRY_COMPARE(itemsInsertedSpy.count(), 1);
711 QTRY_COMPARE(itemsRemovedSpy.count(), 1);
712
713 // remove item from actual position
714 args = itemsRemovedSpy.takeFirst();
715 range = args.at(0).value<KItemRangeList>();
716 QCOMPARE(range.size(), 1);
717 QCOMPARE(range.at(0).count, 1);
718 QCOMPARE(range.at(0).index, 1);
719
720 // insert intem in his group
721 args = itemsInsertedSpy.takeFirst();
722 range = args.at(0).value<KItemRangeList>();
723 QCOMPARE(range.size(), 1);
724 QCOMPARE(range.at(0).count, 1);
725 QCOMPARE(range.at(0).index, 2);
726
727 CHECK_PLACES_URLS(urls);
728
729 itemsInsertedSpy.clear();
730 itemsRemovedSpy.clear();
731
732 // Move the KDE_ROOT_PATH to his original position
733 dropData = createMimeData(QList<int>() << 2);
734 m_model->dropMimeDataBefore(1, dropData);
735 urls.move(2, 1);
736 delete dropData;
737
738 QTRY_COMPARE(itemsInsertedSpy.count(), 1);
739 QTRY_COMPARE(itemsRemovedSpy.count(), 1);
740
741 // remove item from actual position
742 args = itemsRemovedSpy.takeFirst();
743 range = args.at(0).value<KItemRangeList>();
744 QCOMPARE(range.size(), 1);
745 QCOMPARE(range.at(0).count, 1);
746 QCOMPARE(range.at(0).index, 2);
747
748 // insert intem in the requested position
749 args = itemsInsertedSpy.takeFirst();
750 range = args.at(0).value<KItemRangeList>();
751 QCOMPARE(range.size(), 1);
752 QCOMPARE(range.at(0).count, 1);
753 QCOMPARE(range.at(0).index, 1);
754
755 CHECK_PLACES_URLS(urls);
756 }
757
758 void PlacesItemModelTest::testHideDevices()
759 {
760 QSignalSpy itemsRemoved(m_model, &PlacesItemModel::itemsRemoved);
761 QStringList urls = initialUrls();
762
763 m_model->setGroupHidden(KFilePlacesModel::RemovableDevicesType, true);
764 QTRY_VERIFY(m_model->isGroupHidden(KFilePlacesModel::RemovableDevicesType));
765 QTRY_COMPARE(itemsRemoved.count(), 3);
766
767 // remove removable-devices
768 urls.removeOne(QStringLiteral("/media/floppy0"));
769 urls.removeOne(QStringLiteral("/media/XO-Y4"));
770 urls.removeOne(QStringLiteral("/media/cdrom"));
771
772 // check if the correct urls was removed
773 CHECK_PLACES_URLS(urls);
774
775 delete m_model;
776 m_model = new PlacesItemModel();
777 QTRY_COMPARE(m_model->count(), urls.count());
778 CHECK_PLACES_URLS(urls);
779
780 // revert changes
781 m_model->setGroupHidden(KFilePlacesModel::RemovableDevicesType, false);
782 urls = initialUrls();
783 QTRY_COMPARE(m_model->count(), urls.count());
784 CHECK_PLACES_URLS(urls);
785 }
786
787 void PlacesItemModelTest::testDuplicatedEntries()
788 {
789 QStringList urls = initialUrls();
790 // create a duplicated entry on bookmark
791 KBookmarkManager *bookmarkManager = KBookmarkManager::managerForFile(bookmarksFile(), QStringLiteral("kfilePlaces"));
792 KBookmarkGroup root = bookmarkManager->root();
793 KBookmark bookmark = root.addBookmark(QStringLiteral("Duplicated Search Videos"), QUrl("search:/videos"), {});
794
795 const QString id = QUuid::createUuid().toString();
796 bookmark.setMetaDataItem(QStringLiteral("ID"), id);
797 bookmark.setMetaDataItem(QStringLiteral("OnlyInApp"), KAboutData::applicationData().componentName());
798 bookmarkManager->emitChanged(bookmarkManager->root());
799
800 PlacesItemModel *newModel = new PlacesItemModel();
801 QTRY_COMPARE(placesUrls(newModel).count(QStringLiteral("search:/videos")), 1);
802 QTRY_COMPARE(urls, placesUrls(newModel));
803 delete newModel;
804 }
805
806 void PlacesItemModelTest::renameAfterCreation()
807 {
808 const QUrl tempUrl = QUrl::fromLocalFile(QStandardPaths::writableLocation(QStandardPaths::TempLocation));
809 QStringList urls = initialUrls();
810 PlacesItemModel *model = new PlacesItemModel();
811
812 CHECK_PLACES_URLS(urls);
813 QTRY_COMPARE(model->count(), m_model->count());
814
815 // create a new place
816 createPlaceItem(QStringLiteral("Temporary Dir"), tempUrl, QString());
817 urls.insert(3, tempUrl.toLocalFile());
818
819 // make sure that the new item will be removed later
820 removePlaceAfter(3);
821
822 CHECK_PLACES_URLS(urls);
823 QCOMPARE(model->count(), m_model->count());
824
825
826 // modify place text
827 QSignalSpy changedSpy(m_model, &PlacesItemModel::itemsChanged);
828
829 PlacesItem *item = m_model->placesItem(3);
830 item->setText(QStringLiteral("New Temporary Dir"));
831 item->setUrl(item->url());
832 item->setIcon(item->icon());
833 m_model->refresh();
834
835 QTRY_COMPARE(changedSpy.count(), 1);
836
837 // check if the place was modified in both models
838 QTRY_COMPARE(m_model->placesItem(3)->text(), QStringLiteral("New Temporary Dir"));
839 QTRY_COMPARE(model->placesItem(3)->text(), QStringLiteral("New Temporary Dir"));
840 }
841
842 QTEST_MAIN(PlacesItemModelTest)
843
844 #include "placesitemmodeltest.moc"