]> cloud.milkyroute.net Git - dolphin.git/blob - src/tests/dolphinviewtest_allviewmodes.cpp
Dolphin unit test refactoring
[dolphin.git] / src / tests / dolphinviewtest_allviewmodes.cpp
1 /****************************************************************************
2 * Copyright (C) 2010-2011 by Frank Reininghaus (frank78ac@googlemail.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 <kdebug.h>
21
22 #include "dolphinviewtest_allviewmodes.h"
23
24 #include <qtest_kde.h>
25
26 #include "testdir.h"
27
28 #include "views/dolphinview.h"
29 #include "views/dolphinmodel.h"
30 #include "views/dolphindirlister.h"
31 #include "views/dolphinsortfilterproxymodel.h"
32 #include "views/zoomlevelinfo.h"
33
34 #include <QScrollBar>
35
36 #include <qtestmouse.h>
37 #include <qtestkeyboard.h>
38
39 DolphinViewTest_AllViewModes::DolphinViewTest_AllViewModes() {
40 // Need to register KFileItemList for use with QSignalSpy
41 qRegisterMetaType<KFileItemList>("KFileItemList");
42 }
43
44 /**
45 * testSelection() checks the basic selection functionality of DolphinView, including:
46 *
47 * selectedItems()
48 * selectedItemsCount()
49 * selectAll()
50 * invertSelection()
51 * clearSelection()
52 * hasSelection()
53 *
54 * and the signal selectionChanged(const KFileItemList& selection)
55 */
56
57 Q_DECLARE_METATYPE(KFileItemList)
58
59 void DolphinViewTest_AllViewModes::testSelection() {
60 TestDir dir;
61 const int totalItems = 50;
62 for (int i = 0; i < totalItems; i++) {
63 dir.createFile(QString("%1").arg(i));
64 }
65
66 DolphinView view(dir.url(), 0);
67 QAbstractItemView* itemView = initView(&view);
68
69 // Start with an empty selection
70 view.clearSelection();
71
72 QCOMPARE(view.selectedItems().count(), 0);
73 QCOMPARE(view.selectedItemsCount(), 0);
74 QVERIFY(!view.hasSelection());
75
76 // First some simple tests where either all or no items are selected
77 view.selectAll();
78 verifySelectedItemsCount(&view, totalItems);
79
80 view.invertSelection();
81 verifySelectedItemsCount(&view, 0);
82
83 view.invertSelection();
84 verifySelectedItemsCount(&view, totalItems);
85
86 view.clearSelection();
87 verifySelectedItemsCount(&view, 0);
88
89 // Now we select individual items using mouse clicks
90 QModelIndex index = itemView->model()->index(2, 0);
91 itemView->scrollTo(index);
92 QTest::mouseClick(itemView->viewport(), Qt::LeftButton, Qt::ControlModifier, itemView->visualRect(index).center());
93 verifySelectedItemsCount(&view, 1);
94
95 index = itemView->model()->index(totalItems - 5, 0);
96 itemView->scrollTo(index);
97 QTest::mouseClick(itemView->viewport(), Qt::LeftButton, Qt::ControlModifier, itemView->visualRect(index).center());
98 verifySelectedItemsCount(&view, 2);
99
100 index = itemView->model()->index(totalItems - 2, 0);
101 itemView->scrollTo(index);
102 QTest::mouseClick(itemView->viewport(), Qt::LeftButton, Qt::ShiftModifier, itemView->visualRect(index).center());
103 verifySelectedItemsCount(&view, 5);
104
105 view.invertSelection();
106 verifySelectedItemsCount(&view, totalItems - 5);
107
108 // Pressing Esc should clear the selection
109 QTest::keyClick(itemView->viewport(), Qt::Key_Escape);
110 verifySelectedItemsCount(&view, 0);
111 }
112
113 /**
114 * Check that setting the directory view properties works.
115 */
116
117 void DolphinViewTest_AllViewModes::testViewPropertySettings()
118 {
119 // Create some files with different sizes and modification times to check the different sorting options
120 QDateTime now = QDateTime::currentDateTime();
121
122 TestDir dir;
123 dir.createFile("a", "A file", now.addDays(-3));
124 dir.createFile("b", "A larger file", now.addDays(0));
125 dir.createDir("c", now.addDays(-2));
126 dir.createFile("d", "The largest file in this directory", now.addDays(-1));
127 dir.createFile("e", "An even larger file", now.addDays(-4));
128 dir.createFile(".f");
129
130 DolphinView view(dir.url(), 0);
131 initView(&view);
132
133 // First set all settings to the default.
134 view.setSorting(DolphinView::SortByName);
135 QCOMPARE(view.sorting(), DolphinView::SortByName);
136
137 view.setSortOrder(Qt::AscendingOrder);
138 QCOMPARE(view.sortOrder(), Qt::AscendingOrder);
139
140 view.setSortFoldersFirst(true);
141 QVERIFY(view.sortFoldersFirst());
142
143 view.setShowPreview(false);
144 QVERIFY(!view.showPreview());
145
146 view.setShowHiddenFiles(false);
147 QVERIFY(!view.showHiddenFiles());
148
149 /** Check that the sort order is correct for different kinds of settings */
150
151 // Sort by Name, ascending
152 QCOMPARE(view.sorting(), DolphinView::SortByName);
153 QCOMPARE(view.sortOrder(), Qt::AscendingOrder);
154 QCOMPARE(viewItems(&view), QStringList() << "c" << "a" << "b" << "d" << "e");
155
156 // Sort by Name, descending
157 view.setSortOrder(Qt::DescendingOrder);
158 QCOMPARE(view.sorting(), DolphinView::SortByName);
159 QCOMPARE(view.sortOrder(), Qt::DescendingOrder);
160 QCOMPARE(viewItems(&view), QStringList() << "c" << "e" << "d" << "b" << "a");
161
162 // Sort by Size, descending
163 view.setSorting(DolphinView::SortBySize);
164 QCOMPARE(view.sorting(), DolphinView::SortBySize);
165 QCOMPARE(view.sortOrder(), Qt::DescendingOrder);
166 QCOMPARE(viewItems(&view), QStringList() << "c" << "d" << "e" << "b" << "a");
167
168 // Sort by Size, ascending
169 view.setSortOrder(Qt::AscendingOrder);
170 QCOMPARE(view.sorting(), DolphinView::SortBySize);
171 QCOMPARE(view.sortOrder(), Qt::AscendingOrder);
172 QCOMPARE(viewItems(&view), QStringList() << "c" << "a" << "b" << "e" << "d");
173
174 // Sort by Date, ascending
175 view.setSorting(DolphinView::SortByDate);
176 QCOMPARE(view.sorting(), DolphinView::SortByDate);
177 QCOMPARE(view.sortOrder(), Qt::AscendingOrder);
178 QCOMPARE(viewItems(&view), QStringList() << "c" << "e" << "a" << "d" << "b");
179
180 // Sort by Date, descending
181 view.setSortOrder(Qt::DescendingOrder);
182 QCOMPARE(view.sorting(), DolphinView::SortByDate);
183 QCOMPARE(view.sortOrder(), Qt::DescendingOrder);
184 QCOMPARE(viewItems(&view), QStringList() << "c" << "b" << "d" << "a" << "e");
185
186 // Disable "Sort Folders First"
187 view.setSortFoldersFirst(false);
188 QVERIFY(!view.sortFoldersFirst());
189 QCOMPARE(viewItems(&view), QStringList()<< "b" << "d" << "c" << "a" << "e");
190
191 // Try again with Sort by Name, ascending
192 view.setSorting(DolphinView::SortByName);
193 view.setSortOrder(Qt::AscendingOrder);
194 QCOMPARE(view.sorting(), DolphinView::SortByName);
195 QCOMPARE(view.sortOrder(), Qt::AscendingOrder);
196 QCOMPARE(viewItems(&view), QStringList() << "a" << "b" << "c" << "d" << "e");
197
198 // Show hidden files. This triggers the dir lister
199 // -> we have to wait until loading the hidden files is finished
200 view.setShowHiddenFiles(true);
201 QVERIFY(QTest::kWaitForSignal(&view, SIGNAL(finishedPathLoading(const KUrl&)), 2000));
202 QVERIFY(view.showHiddenFiles());
203 QCOMPARE(viewItems(&view), QStringList() << ".f" << "a" << "b" << "c" << "d" << "e");
204
205 // Previews
206 view.setShowPreview(true);
207 QVERIFY(view.showPreview());
208
209 // TODO: Check that the view properties are restored correctly when changing the folder and then going back.
210 }
211
212 /**
213 * testZoomLevel() checks that setting the zoom level works, both using DolphinView's API and using Ctrl+mouse wheel.
214 */
215
216 void DolphinViewTest_AllViewModes::testZoomLevel()
217 {
218 TestDir dir;
219 dir.createFiles(QStringList() << "a" << "b");
220 DolphinView view(dir.url(), 0);
221 QAbstractItemView* itemView = initView(&view);
222
223 view.setShowPreview(false);
224 QVERIFY(!view.showPreview());
225
226 int zoomLevelBackup = view.zoomLevel();
227
228 int zoomLevel = ZoomLevelInfo::minimumLevel();
229 view.setZoomLevel(zoomLevel);
230 QCOMPARE(view.zoomLevel(), zoomLevel);
231
232 // Increase the zoom level successively to the maximum.
233 while(zoomLevel < ZoomLevelInfo::maximumLevel()) {
234 zoomLevel++;
235 view.setZoomLevel(zoomLevel);
236 QCOMPARE(view.zoomLevel(), zoomLevel);
237 }
238
239 // Try setting a zoom level larger than the maximum
240 view.setZoomLevel(ZoomLevelInfo::maximumLevel() + 1);
241 QCOMPARE(view.zoomLevel(), ZoomLevelInfo::maximumLevel());
242
243 // Turn previews on and try setting a zoom level smaller than the minimum
244 view.setShowPreview(true);
245 QVERIFY(view.showPreview());
246 view.setZoomLevel(ZoomLevelInfo::minimumLevel() - 1);
247 QCOMPARE(view.zoomLevel(), ZoomLevelInfo::minimumLevel());
248
249 // Turn previews off again and check that the zoom level is restored
250 view.setShowPreview(false);
251 QVERIFY(!view.showPreview());
252 QCOMPARE(view.zoomLevel(), ZoomLevelInfo::maximumLevel());
253
254 // Change the zoom level using Ctrl+mouse wheel
255 QModelIndex index = itemView->model()->index(0, 0);
256 itemView->scrollTo(index);
257
258 while (view.zoomLevel() > ZoomLevelInfo::minimumLevel()) {
259 int oldZoomLevel = view.zoomLevel();
260 QWheelEvent wheelEvent(itemView->visualRect(index).center(), -1, Qt::NoButton, Qt::ControlModifier);
261 bool wheelEventReceived = qApp->notify(itemView->viewport(), &wheelEvent);
262 QVERIFY(wheelEventReceived);
263 QVERIFY(view.zoomLevel() < oldZoomLevel);
264 }
265 QCOMPARE(view.zoomLevel(), ZoomLevelInfo::minimumLevel());
266
267 while (view.zoomLevel() < ZoomLevelInfo::maximumLevel()) {
268 int oldZoomLevel = view.zoomLevel();
269 QWheelEvent wheelEvent(itemView->visualRect(index).center(), 1, Qt::NoButton, Qt::ControlModifier);
270 bool wheelEventReceived = qApp->notify(itemView->viewport(), &wheelEvent);
271 QVERIFY(wheelEventReceived);
272 QVERIFY(view.zoomLevel() > oldZoomLevel);
273 }
274 QCOMPARE(view.zoomLevel(), ZoomLevelInfo::maximumLevel());
275
276 // Turn previews on again and check that the zoom level is restored
277 view.setShowPreview(true);
278 QVERIFY(view.showPreview());
279 QCOMPARE(view.zoomLevel(), ZoomLevelInfo::minimumLevel());
280
281 // Restore the initial state
282 view.setZoomLevel(zoomLevelBackup);
283 view.setShowPreview(false);
284 view.setZoomLevel(zoomLevelBackup);
285 }
286
287 /**
288 * testSaveAndRestoreState() checks if saving and restoring the view state (current item, scroll position).
289 *
290 * Note that we call qApp->sendPostedEvents() every time the view's finishedPathLoading(const KUrl&) signal
291 * is received. The reason is that the scroll position is restored in the slot restoreContentsPosition(),
292 * which is been invoked using a queued connection in DolphinView::slotLoadingCompleted(). To make sure
293 * that this slot is really executed before we proceed, we have to empty the event queue using qApp->sendPostedEvents().
294 */
295
296 void DolphinViewTest_AllViewModes::testSaveAndRestoreState()
297 {
298 const int totalItems = 50;
299 TestDir dir;
300 for (int i = 0; i < totalItems; i++) {
301 dir.createFile(QString("%1").arg(i));
302 }
303 dir.createDir("51");
304 DolphinView view(dir.url(), 0);
305 initView(&view);
306
307 // Set sorting settings to the default to make sure that the item positions are reproducible.
308 view.setSorting(DolphinView::SortByName);
309 QCOMPARE(view.sorting(), DolphinView::SortByName);
310 view.setSortOrder(Qt::AscendingOrder);
311 QCOMPARE(view.sortOrder(), Qt::AscendingOrder);
312
313 const QModelIndex index45 = itemView(&view)->model()->index(45, 0);
314 itemView(&view)->scrollTo(index45);
315 itemView(&view)->setCurrentIndex(index45);
316 const int scrollPosX = itemView(&view)->horizontalScrollBar()->value();
317 const int scrollPosY = itemView(&view)->verticalScrollBar()->value();
318 QTest::qWait(2000);
319
320 // Save the view state
321 QByteArray viewState;
322 QDataStream saveStream(&viewState, QIODevice::WriteOnly);
323 view.saveState(saveStream);
324
325 // Change the URL
326 view.setUrl(dir.name() + "51");
327 QVERIFY(QTest::kWaitForSignal(&view, SIGNAL(finishedPathLoading(const KUrl&)), 2000));
328 qApp->sendPostedEvents();
329
330 // Go back, but do not call DolphinView::restoreState()
331 view.setUrl(dir.url());
332 QVERIFY(QTest::kWaitForSignal(&view, SIGNAL(finishedPathLoading(const KUrl&)), 2000));
333 qApp->sendPostedEvents();
334
335 // Verify that the view is scrolled to top-left corner and that item 45 is not the current item.
336 // Note that the vertical position of the columns view might not be zero -> skip that part
337 // of the check in this case.
338 QVERIFY(itemView(&view)->currentIndex() != index45);
339 QCOMPARE(itemView(&view)->horizontalScrollBar()->value(), 0);
340 if (mode() != DolphinView::ColumnView) {
341 QCOMPARE(itemView(&view)->verticalScrollBar()->value(), 0);
342 }
343
344 // Change the URL again
345 view.setUrl(dir.name() + "51");
346 QVERIFY(QTest::kWaitForSignal(&view, SIGNAL(finishedPathLoading(const KUrl&)), 2000));
347 qApp->sendPostedEvents();
348
349 // Check that the current item and scroll position are correct if DolphinView::restoreState()
350 // is called after the URL change
351 view.setUrl(dir.url());
352 QDataStream restoreStream(viewState);
353 view.restoreState(restoreStream);
354 QVERIFY(QTest::kWaitForSignal(&view, SIGNAL(finishedPathLoading(const KUrl&)), 2000));
355 qApp->sendPostedEvents();
356
357 QCOMPARE(itemView(&view)->currentIndex(), index45);
358 QCOMPARE(itemView(&view)->horizontalScrollBar()->value(), scrollPosX);
359 QCOMPARE(itemView(&view)->verticalScrollBar()->value(), scrollPosY);
360 }
361
362 /**
363 * testKeyboardFocus() checks whether a view grabs the keyboard focus.
364 *
365 * A view may never grab the keyboard focus itself and must respect the focus-state
366 * when switching the view mode, see
367 *
368 * https://bugs.kde.org/show_bug.cgi?id=261147
369 */
370
371 void DolphinViewTest_AllViewModes::testKeyboardFocus()
372 {
373 TestDir dir;
374 dir.createFiles(QStringList() << "a" << "b");
375 DolphinView view(dir.url(), 0);
376 initView(&view);
377
378 // Move keyboard focus to another widget. To see that this is needed, run only this test,
379 // i.e., pass 'testKeyboardFocus' as a parameter on the command line.
380 QWidget widget;
381 widget.show();
382 QTest::qWaitForWindowShown(&widget);
383 widget.setFocus();
384
385 QVERIFY(!view.hasFocus());
386
387 // Switch view modes and verify that the view does not get the focus back
388 for (int i = 0; i <= DolphinView::MaxModeEnum; ++i) {
389 view.setMode(static_cast<DolphinView::Mode>(i));
390 QVERIFY(!view.hasFocus());
391 }
392 }
393
394 QAbstractItemView* DolphinViewTest_AllViewModes::initView(DolphinView* view) const
395 {
396 view->setMode(mode());
397 view->resize(200, 300);
398 view->show();
399 QTest::qWaitForWindowShown(view);
400 Q_ASSERT(verifyCorrectViewMode(view));
401 reloadViewAndWait(view);
402 return itemView(view);
403 }
404
405 /**
406 * verifySelectedItemsCount(int) waits until the DolphinView's selectionChanged(const KFileItemList&)
407 * signal is received and checks that the selection state of the view is as expected.
408 */
409
410 void DolphinViewTest_AllViewModes::verifySelectedItemsCount(DolphinView* view, int itemsCount) const
411 {
412 QSignalSpy spySelectionChanged(view, SIGNAL(selectionChanged(const KFileItemList&)));
413 QVERIFY(QTest::kWaitForSignal(view, SIGNAL(selectionChanged(const KFileItemList&)), 500));
414
415 QCOMPARE(view->selectedItems().count(), itemsCount);
416 QCOMPARE(view->selectedItemsCount(), itemsCount);
417 QCOMPARE(spySelectionChanged.count(), 1);
418 QCOMPARE(qvariant_cast<KFileItemList>(spySelectionChanged.at(0).at(0)).count(), itemsCount);
419 if (itemsCount) {
420 QVERIFY(view->hasSelection());
421 }
422 else {
423 QVERIFY(!view->hasSelection());
424 }
425 }
426
427 #include "dolphinviewtest_allviewmodes.moc"