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