diff --git a/dolphin/src/kitemviews/kitemlistcontroller.cpp b/dolphin/src/kitemviews/kitemlistcontroller.cpp index e3210dd222..69320247a8 100644 --- a/dolphin/src/kitemviews/kitemlistcontroller.cpp +++ b/dolphin/src/kitemviews/kitemlistcontroller.cpp @@ -203,7 +203,8 @@ bool KItemListController::keyPressEvent(QKeyEvent* event) } } - const bool selectSingleItem = itemCount == 1 && + const bool selectSingleItem = m_selectionBehavior != NoSelection && + itemCount == 1 && (key == Qt::Key_Home || key == Qt::Key_End || key == Qt::Key_Up || key == Qt::Key_Down || key == Qt::Key_Left || key == Qt::Key_Right); @@ -322,13 +323,15 @@ bool KItemListController::keyPressEvent(QKeyEvent* event) } case Qt::Key_Space: - if (controlPressed) { - m_selectionManager->endAnchoredSelection(); - m_selectionManager->setSelected(index, 1, KItemListSelectionManager::Toggle); - m_selectionManager->beginAnchoredSelection(index); - } else { - const int current = m_selectionManager->currentItem(); - m_selectionManager->setSelected(current); + if (m_selectionBehavior == MultiSelection) { + if (controlPressed) { + m_selectionManager->endAnchoredSelection(); + m_selectionManager->setSelected(index, 1, KItemListSelectionManager::Toggle); + m_selectionManager->beginAnchoredSelection(index); + } else { + const int current = m_selectionManager->currentItem(); + m_selectionManager->setSelected(current); + } } break; @@ -361,19 +364,33 @@ bool KItemListController::keyPressEvent(QKeyEvent* event) } if (m_selectionManager->currentItem() != index) { - if (controlPressed) { - m_selectionManager->endAnchoredSelection(); - } + switch (m_selectionBehavior) { + case NoSelection: + m_selectionManager->setCurrentItem(index); + break; - m_selectionManager->setCurrentItem(index); - - if (!shiftOrControlPressed || m_selectionBehavior == SingleSelection) { + case SingleSelection: + m_selectionManager->setCurrentItem(index); m_selectionManager->clearSelection(); m_selectionManager->setSelected(index, 1); - } + break; - if (!shiftPressed) { - m_selectionManager->beginAnchoredSelection(index); + case MultiSelection: + if (controlPressed) { + m_selectionManager->endAnchoredSelection(); + } + + m_selectionManager->setCurrentItem(index); + + if (!shiftOrControlPressed) { + m_selectionManager->clearSelection(); + m_selectionManager->setSelected(index, 1); + } + + if (!shiftPressed) { + m_selectionManager->beginAnchoredSelection(index); + } + break; } m_view->scrollToItem(index); diff --git a/dolphin/src/kitemviews/kitemlistview.h b/dolphin/src/kitemviews/kitemlistview.h index 95215fffdb..9c34daba3f 100644 --- a/dolphin/src/kitemviews/kitemlistview.h +++ b/dolphin/src/kitemviews/kitemlistview.h @@ -513,6 +513,7 @@ private: bool m_useHeaderWidths; friend class KItemListController; + friend class KItemListControllerTest; }; /** diff --git a/dolphin/src/kitemviews/kitemlistviewlayouter_p.h b/dolphin/src/kitemviews/kitemlistviewlayouter_p.h index dec99d0542..25f8eb6cda 100644 --- a/dolphin/src/kitemviews/kitemlistviewlayouter_p.h +++ b/dolphin/src/kitemviews/kitemlistviewlayouter_p.h @@ -161,6 +161,8 @@ private: qreal m_groupHeaderHeight; QList m_itemRects; + + friend class KItemListControllerTest; }; #endif diff --git a/dolphin/src/tests/CMakeLists.txt b/dolphin/src/tests/CMakeLists.txt index c3360674c1..43d1c9bf72 100644 --- a/dolphin/src/tests/CMakeLists.txt +++ b/dolphin/src/tests/CMakeLists.txt @@ -12,6 +12,18 @@ set(kitemlistselectionmanagertest_SRCS kde4_add_unit_test(kitemlistselectionmanagertest TEST ${kitemlistselectionmanagertest_SRCS}) target_link_libraries(kitemlistselectionmanagertest dolphinprivate ${KDE4_KIO_LIBS} ${QT_QTTEST_LIBRARY}) +# KItemListControllerTest +set(kitemlistcontrollertest_SRCS + kitemlistcontrollertest.cpp + testdir.cpp + ../kitemviews/kfileitemmodel.cpp + ../kitemviews/kfileitemlistview.cpp + ../kitemviews/kitemmodelbase.cpp + ../kitemviews/kitemlistview.cpp +) +kde4_add_unit_test(kitemlistcontrollertest TEST ${kitemlistcontrollertest_SRCS}) +target_link_libraries(kitemlistcontrollertest dolphinprivate ${KDE4_KIO_LIBS} ${QT_QTTEST_LIBRARY}) + # KFileItemListViewTest set(kfileitemlistviewtest_SRCS kfileitemlistviewtest.cpp diff --git a/dolphin/src/tests/kitemlistcontrollertest.cpp b/dolphin/src/tests/kitemlistcontrollertest.cpp new file mode 100644 index 0000000000..443faa35ff --- /dev/null +++ b/dolphin/src/tests/kitemlistcontrollertest.cpp @@ -0,0 +1,505 @@ +/*************************************************************************** + * Copyright (C) 2012 by Frank Reininghaus * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * + ***************************************************************************/ + +#include +#include +#include + +#include +#include "kitemviews/kitemlistcontainer.h" +#include "kitemviews/kfileitemlistview.h" +#include "kitemviews/kfileitemmodel.h" +#include "kitemviews/kitemlistcontroller.h" +#include "kitemviews/kitemlistselectionmanager.h" +#include "kitemviews/kitemlistviewlayouter_p.h" +#include "testdir.h" + +namespace { + const int DefaultTimeout = 2000; +}; + +Q_DECLARE_METATYPE(KFileItemListView::Layout); +Q_DECLARE_METATYPE(Qt::Orientation); +Q_DECLARE_METATYPE(KItemListController::SelectionBehavior); + +class KItemListControllerTest : public QObject +{ + Q_OBJECT + +private slots: + void initTestCase(); + void cleanupTestCase(); + + void init(); + void cleanup(); + + void testKeyboardNavigation_data(); + void testKeyboardNavigation(); + +private: + /** + * Make sure that the number of columns in the view is equal to \a count + * by changing the geometry of the container. + */ + void adjustGeometryForColumnCount(int count); + +private: + KFileItemListView* m_view; + KItemListController* m_controller; + KItemListSelectionManager* m_selectionManager; + KFileItemModel* m_model; + KDirLister* m_dirLister; + TestDir* m_testDir; + KItemListContainer* m_container; +}; + +/** + * This function initializes the member objects, creates the temporary files, and + * shows the view on the screen on startup. This could also be done before every + * single test, but this would make the time needed to run the test much larger. + */ +void KItemListControllerTest::initTestCase() +{ + m_testDir = new TestDir(); + m_dirLister = new KDirLister(); + m_model = new KFileItemModel(m_dirLister); + m_container = new KItemListContainer(); + m_controller = m_container->controller(); + m_controller->setSelectionBehavior(KItemListController::MultiSelection); + m_selectionManager = m_controller->selectionManager(); + + m_view = new KFileItemListView(); + m_controller->setView(m_view); + m_controller->setModel(m_model); + + QStringList files; + files + << "a1" << "a2" << "a3" + << "b1" + << "c1" << "c2" << "c3" << "c4" << "c5" + << "d1" << "d2" << "d3" << "d4" + << "e1" << "e2" << "e3" << "e4" << "e5" << "e6" << "e7"; + + m_testDir->createFiles(files); + m_dirLister->openUrl(m_testDir->url()); + QVERIFY(QTest::kWaitForSignal(m_model, SIGNAL(loadingCompleted()), DefaultTimeout)); + + m_container->show(); + QTest::qWaitForWindowShown(m_container); +} + +void KItemListControllerTest::cleanupTestCase() +{ + delete m_view; + m_view = 0; + + delete m_container; + m_container = 0; + m_controller = 0; + + delete m_model; + m_model = 0; + + delete m_dirLister; + m_dirLister = 0; + + delete m_testDir; + m_testDir = 0; +} + +/** Before each test, the current item, selection, and item size are reset to the defaults. */ +void KItemListControllerTest::init() +{ + m_selectionManager->setCurrentItem(0); + QCOMPARE(m_selectionManager->currentItem(), 0); + + m_selectionManager->clearSelection(); + QVERIFY(!m_selectionManager->hasSelection()); + + const QSizeF itemSize(50, 50); + m_view->setItemSize(itemSize); + QCOMPARE(m_view->itemSize(), itemSize); +} + +void KItemListControllerTest::cleanup() +{ +} + +/** + * \class KeyPress is a small helper struct that represents a key press event, + * including the key and the keyboard modifiers. + */ +struct KeyPress { + + KeyPress(Qt::Key key, Qt::KeyboardModifiers modifier = Qt::NoModifier) : + m_key(key), + m_modifier(modifier) + {} + + Qt::Key m_key; + Qt::KeyboardModifiers m_modifier; +}; + +/** + * \class ViewState is a small helper struct that represents a certain state + * of the view, including the current item and the selected items. + */ +struct ViewState { + + ViewState(int current, QSet selection) : + m_current(current), + m_selection(selection) + {} + + int m_current; + QSet m_selection; +}; + +// We have to define a typedef for the pair in order to make the test compile. +typedef QPair keyPressViewStatePair; +Q_DECLARE_METATYPE(QList); + +/** + * This function provides the data for the actual test function + * KItemListControllerTest::testKeyboardNavigation(). + * It tests all possible combinations of view layouts, selection behaviors, + * and enabled/disabled groupings for different column counts, and + * provides a list of key presses and the states that the view should be in + * after the key press event. + */ +void KItemListControllerTest::testKeyboardNavigation_data() +{ + QTest::addColumn("layout"); + QTest::addColumn("scrollOrientation"); + QTest::addColumn("columnCount"); + QTest::addColumn("selectionBehavior"); + QTest::addColumn("groupingEnabled"); + QTest::addColumn > >("testList"); + + static QList layoutList; + static QHash layoutNames; + if (layoutList.isEmpty()) { + layoutList.append(KFileItemListView::IconsLayout); + layoutNames[KFileItemListView::IconsLayout] = "Icons"; + + layoutList.append(KFileItemListView::CompactLayout); + layoutNames[KFileItemListView::CompactLayout] = "Compact"; + + layoutList.append(KFileItemListView::DetailsLayout); + layoutNames[KFileItemListView::DetailsLayout] = "Details"; + } + + static QList selectionBehaviorList; + static QHash selectionBehaviorNames; + if (selectionBehaviorList.isEmpty()) { + selectionBehaviorList.append(KItemListController::NoSelection); + selectionBehaviorNames[KItemListController::NoSelection] = "NoSelection"; + + selectionBehaviorList.append(KItemListController::SingleSelection); + selectionBehaviorNames[KItemListController::SingleSelection] = "SingleSelection"; + + selectionBehaviorList.append(KItemListController::MultiSelection); + selectionBehaviorNames[KItemListController::MultiSelection] = "MultiSelection"; + } + + static QList groupingEnabledList; + static QHash groupingEnabledNames; + if (groupingEnabledList.isEmpty()) { + groupingEnabledList.append(false); + groupingEnabledNames[false] = "ungrouped"; + + groupingEnabledList.append(true); + groupingEnabledNames[true] = "grouping enabled"; + } + + foreach (KFileItemListView::Layout layout, layoutList) { + // The following settings depend on the layout. + // Note that 'columns' are actually 'rows' in + // Compact layout. + Qt::Orientation scrollOrientation; + QList columnCountList; + Qt::Key nextItemKey; + Qt::Key previousItemKey; + Qt::Key nextRowKey; + Qt::Key previousRowKey; + + switch (layout) { + case KFileItemListView::IconsLayout: + scrollOrientation = Qt::Vertical; + columnCountList << 1 << 3 << 5; + nextItemKey = Qt::Key_Right; + previousItemKey = Qt::Key_Left; + nextRowKey = Qt::Key_Down; + previousRowKey = Qt::Key_Up; + break; + case KFileItemListView::CompactLayout: + scrollOrientation = Qt::Horizontal; + columnCountList << 1 << 3 << 5; + nextItemKey = Qt::Key_Down; + previousItemKey = Qt::Key_Up; + nextRowKey = Qt::Key_Right; + previousRowKey = Qt::Key_Left; + break; + case KFileItemListView::DetailsLayout: + scrollOrientation = Qt::Vertical; + columnCountList << 1; + nextItemKey = Qt::Key_Down; + previousItemKey = Qt::Key_Up; + nextRowKey = Qt::Key_Down; + previousRowKey = Qt::Key_Up; + break; + } + + foreach (int columnCount, columnCountList) { + foreach (KItemListController::SelectionBehavior selectionBehavior, selectionBehaviorList) { + foreach (bool groupingEnabled, groupingEnabledList) { + QList > testList; + + // First, key presses which should have the same effect + // for any layout and any number of columns. + testList + << qMakePair(KeyPress(nextItemKey), ViewState(1, QSet() << 1)) + << qMakePair(KeyPress(nextItemKey), ViewState(2, QSet() << 2)) + << qMakePair(KeyPress(nextItemKey, Qt::ShiftModifier), ViewState(3, QSet() << 2 << 3)) + << qMakePair(KeyPress(previousItemKey, Qt::ShiftModifier), ViewState(2, QSet() << 2)) + << qMakePair(KeyPress(nextItemKey, Qt::ShiftModifier), ViewState(3, QSet() << 2 << 3)) + << qMakePair(KeyPress(nextItemKey, Qt::ControlModifier), ViewState(4, QSet() << 2 << 3)) + << qMakePair(KeyPress(previousItemKey), ViewState(3, QSet() << 3)) + << qMakePair(KeyPress(Qt::Key_Home, Qt::ShiftModifier), ViewState(0, QSet() << 0 << 1 << 2 << 3)) + << qMakePair(KeyPress(nextItemKey, Qt::ControlModifier), ViewState(1, QSet() << 0 << 1 << 2 << 3)) + << qMakePair(KeyPress(Qt::Key_Space, Qt::ControlModifier), ViewState(1, QSet() << 0 << 2 << 3)) + << qMakePair(KeyPress(Qt::Key_Space, Qt::ControlModifier), ViewState(1, QSet() << 0 << 1 << 2 << 3)) + << qMakePair(KeyPress(Qt::Key_End), ViewState(19, QSet() << 19)) + << qMakePair(KeyPress(previousItemKey, Qt::ShiftModifier), ViewState(18, QSet() << 18 << 19)) + << qMakePair(KeyPress(Qt::Key_Home), ViewState(0, QSet() << 0)); + + // Next, we test combinations of key presses which only work for a + // particular number of columns and either enabled or disabled grouping. + + // One column. + if (columnCount == 1) { + testList + << qMakePair(KeyPress(nextRowKey), ViewState(1, QSet() << 1)) + << qMakePair(KeyPress(nextRowKey, Qt::ShiftModifier), ViewState(2, QSet() << 1 << 2)) + << qMakePair(KeyPress(nextRowKey, Qt::ControlModifier), ViewState(3, QSet() << 1 << 2)) + << qMakePair(KeyPress(previousRowKey), ViewState(2, QSet() << 2)) + << qMakePair(KeyPress(previousItemKey), ViewState(1, QSet() << 1)) + << qMakePair(KeyPress(Qt::Key_Home), ViewState(0, QSet() << 0)); + } + + // Multiple columns: we test both 3 and 5 columns with grouping + // enabled or disabled. For each case, the layout of the items + // in the view is shown (both using file names and indices) to + // make it easier to understand what the tests do. + + if (columnCount == 3 && !groupingEnabled) { + // 3 columns, no grouping: + // + // a1 a2 a3 | 0 1 2 + // b1 c1 c2 | 3 4 5 + // c3 c4 c5 | 6 7 8 + // d1 d2 d3 | 9 10 11 + // d4 e1 e2 | 12 13 14 + // e3 e4 e5 | 15 16 17 + // e6 e7 | 18 19 + testList + << qMakePair(KeyPress(nextRowKey), ViewState(3, QSet() << 3)) + << qMakePair(KeyPress(nextItemKey, Qt::ControlModifier), ViewState(4, QSet() << 3)) + << qMakePair(KeyPress(nextRowKey), ViewState(7, QSet() << 7)) + << qMakePair(KeyPress(nextItemKey, Qt::ShiftModifier), ViewState(8, QSet() << 7 << 8)) + << qMakePair(KeyPress(nextItemKey, Qt::ShiftModifier), ViewState(9, QSet() << 7 << 8 << 9)) + << qMakePair(KeyPress(previousItemKey, Qt::ShiftModifier), ViewState(8, QSet() << 7 << 8)) + << qMakePair(KeyPress(previousItemKey, Qt::ShiftModifier), ViewState(7, QSet() << 7)) + << qMakePair(KeyPress(previousItemKey, Qt::ShiftModifier), ViewState(6, QSet() << 6 << 7)) + << qMakePair(KeyPress(previousItemKey, Qt::ShiftModifier), ViewState(5, QSet() << 5 << 6 << 7)) + << qMakePair(KeyPress(nextItemKey, Qt::ShiftModifier), ViewState(6, QSet() << 6 << 7)) + << qMakePair(KeyPress(nextItemKey, Qt::ShiftModifier), ViewState(7, QSet() << 7)) + << qMakePair(KeyPress(nextRowKey), ViewState(10, QSet() << 10)) + << qMakePair(KeyPress(nextItemKey), ViewState(11, QSet() << 11)) + << qMakePair(KeyPress(nextRowKey), ViewState(14, QSet() << 14)) + << qMakePair(KeyPress(nextRowKey), ViewState(17, QSet() << 17)) + << qMakePair(KeyPress(nextRowKey), ViewState(19, QSet() << 19)) + << qMakePair(KeyPress(previousRowKey), ViewState(17, QSet() << 17)) + << qMakePair(KeyPress(Qt::Key_End), ViewState(19, QSet() << 19)) + << qMakePair(KeyPress(previousRowKey), ViewState(16, QSet() << 16)) + << qMakePair(KeyPress(Qt::Key_Home), ViewState(0, QSet() << 0)); + } + + if (columnCount == 5 && !groupingEnabled) { + // 5 columns, no grouping: + // + // a1 a2 a3 b1 c1 | 0 1 2 3 4 + // c2 c3 c4 c5 d1 | 5 6 7 8 9 + // d2 d3 d4 e1 e2 | 10 11 12 13 14 + // e3 e4 e5 e6 e7 | 15 16 17 18 19 + testList + << qMakePair(KeyPress(nextRowKey), ViewState(5, QSet() << 5)) + << qMakePair(KeyPress(nextItemKey, Qt::ControlModifier), ViewState(6, QSet() << 5)) + << qMakePair(KeyPress(nextRowKey), ViewState(11, QSet() << 11)) + << qMakePair(KeyPress(nextItemKey), ViewState(12, QSet() << 12)) + << qMakePair(KeyPress(nextRowKey, Qt::ShiftModifier), ViewState(17, QSet() << 12 << 13 << 14 << 15 << 16 << 17)) + << qMakePair(KeyPress(previousRowKey, Qt::ShiftModifier), ViewState(12, QSet() << 12)) + << qMakePair(KeyPress(previousRowKey, Qt::ShiftModifier), ViewState(7, QSet() << 7 << 8 << 9 << 10 << 11 << 12)) + << qMakePair(KeyPress(nextRowKey, Qt::ShiftModifier), ViewState(12, QSet() << 12)) + << qMakePair(KeyPress(Qt::Key_End, Qt::ControlModifier), ViewState(19, QSet() << 12)) + << qMakePair(KeyPress(previousRowKey), ViewState(14, QSet() << 14)) + << qMakePair(KeyPress(Qt::Key_Home), ViewState(0, QSet() << 0)); + } + + if (columnCount == 3 && groupingEnabled) { + // 3 columns, with grouping: + // + // a1 a2 a3 | 0 1 2 + // b1 | 3 + // c1 c2 c3 | 4 5 6 + // c4 c5 | 7 8 + // d1 d2 d3 | 9 10 11 + // d4 | 12 + // e1 e2 e3 | 13 14 15 + // e4 e5 e6 | 16 17 18 + // e7 | 19 + testList + << qMakePair(KeyPress(nextItemKey), ViewState(1, QSet() << 1)) + << qMakePair(KeyPress(nextItemKey), ViewState(2, QSet() << 2)) + << qMakePair(KeyPress(nextRowKey, Qt::ShiftModifier), ViewState(3, QSet() << 2 << 3)) + << qMakePair(KeyPress(nextRowKey, Qt::ShiftModifier), ViewState(6, QSet() << 2 << 3 << 4 << 5 << 6)) + << qMakePair(KeyPress(nextRowKey), ViewState(8, QSet() << 8)) + << qMakePair(KeyPress(nextRowKey), ViewState(11, QSet() << 11)) + << qMakePair(KeyPress(nextItemKey, Qt::ControlModifier), ViewState(12, QSet() << 11)) + << qMakePair(KeyPress(nextRowKey), ViewState(13, QSet() << 13)) + << qMakePair(KeyPress(nextRowKey), ViewState(16, QSet() << 16)) + << qMakePair(KeyPress(nextItemKey), ViewState(17, QSet() << 17)) + << qMakePair(KeyPress(nextRowKey), ViewState(19, QSet() << 19)) + << qMakePair(KeyPress(previousRowKey), ViewState(17, QSet() << 17)) + << qMakePair(KeyPress(Qt::Key_Home), ViewState(0, QSet() << 0)); + } + + if (columnCount == 5 && groupingEnabled) { + // 5 columns, with grouping: + // + // a1 a2 a3 | 0 1 2 + // b1 | 3 + // c1 c2 c3 c4 c5 | 4 5 6 7 8 + // d1 d2 d3 d4 | 9 10 11 12 + // e1 e2 e3 e4 e5 | 13 14 15 16 17 + // e6 e7 | 18 19 + testList + << qMakePair(KeyPress(nextItemKey), ViewState(1, QSet() << 1)) + << qMakePair(KeyPress(nextRowKey, Qt::ShiftModifier), ViewState(3, QSet() << 1 << 2 << 3)) + << qMakePair(KeyPress(nextRowKey, Qt::ShiftModifier), ViewState(5, QSet() << 1 << 2 << 3 << 4 << 5)) + << qMakePair(KeyPress(nextItemKey), ViewState(6, QSet() << 6)) + << qMakePair(KeyPress(nextItemKey, Qt::ControlModifier), ViewState(7, QSet() << 6)) + << qMakePair(KeyPress(nextItemKey, Qt::ControlModifier), ViewState(8, QSet() << 6)) + << qMakePair(KeyPress(nextRowKey), ViewState(12, QSet() << 12)) + << qMakePair(KeyPress(nextRowKey), ViewState(17, QSet() << 17)) + << qMakePair(KeyPress(nextRowKey), ViewState(19, QSet() << 19)) + << qMakePair(KeyPress(previousRowKey), ViewState(17, QSet() << 17)) + << qMakePair(KeyPress(Qt::Key_End, Qt::ShiftModifier), ViewState(19, QSet() << 17 << 18 << 19)) + << qMakePair(KeyPress(previousRowKey, Qt::ShiftModifier), ViewState(14, QSet() << 14 << 15 << 16 << 17)) + << qMakePair(KeyPress(Qt::Key_Home), ViewState(0, QSet() << 0)); + } + + const QString testName = + layoutNames[layout] + ", " + + QString("%1 columns, ").arg(columnCount) + + selectionBehaviorNames[selectionBehavior] + ", " + + groupingEnabledNames[groupingEnabled]; + + const QByteArray testNameAscii = testName.toAscii(); + + QTest::newRow(testNameAscii.data()) + << layout + << scrollOrientation + << columnCount + << selectionBehavior + << groupingEnabled + << testList; + } + } + } + } +} + +/** + * This function sets the view's properties according to the data provided by + * KItemListControllerTest::testKeyboardNavigation_data(). + * + * The list \a testList contains pairs of key presses, which are sent to the + * container, and expected view states, which are verified then. + */ +void KItemListControllerTest::testKeyboardNavigation() +{ + QFETCH(KFileItemListView::Layout, layout); + QFETCH(Qt::Orientation, scrollOrientation); + QFETCH(int, columnCount); + QFETCH(KItemListController::SelectionBehavior, selectionBehavior); + QFETCH(bool, groupingEnabled); + QFETCH(QList, testList); + + m_view->setItemLayout(layout); + QCOMPARE(m_view->itemLayout(), layout); + + m_view->setScrollOrientation(scrollOrientation); + QCOMPARE(m_view->scrollOrientation(), scrollOrientation); + + adjustGeometryForColumnCount(columnCount); + QCOMPARE(m_view->m_layouter->m_columnCount, columnCount); + + m_controller->setSelectionBehavior(selectionBehavior); + QCOMPARE(m_controller->selectionBehavior(), selectionBehavior); + + m_model->setGroupedSorting(groupingEnabled); + QCOMPARE(m_model->groupedSorting(), groupingEnabled); + + while (!testList.isEmpty()) { + const QPair test = testList.takeFirst(); + const Qt::Key key = test.first.m_key; + const Qt::KeyboardModifiers modifier = test.first.m_modifier; + const int current = test.second.m_current; + const QSet selection = test.second.m_selection; + + QTest::keyClick(m_container, key, modifier); + QCOMPARE(m_selectionManager->currentItem(), current); + switch (selectionBehavior) { + case KItemListController::NoSelection: QVERIFY(m_selectionManager->selectedItems().isEmpty()); break; + case KItemListController::SingleSelection: QCOMPARE(m_selectionManager->selectedItems(), QSet() << current); break; + case KItemListController::MultiSelection: QCOMPARE(m_selectionManager->selectedItems(), selection); break; + } + } +} + +void KItemListControllerTest::adjustGeometryForColumnCount(int count) +{ + const QSize size = m_view->itemSize().toSize(); + + QRect rect = m_container->geometry(); + rect.setSize(size * count); + m_container->setGeometry(rect); + + // Increase the size of the container until the correct column count is reached. + while (m_view->m_layouter->m_columnCount < count) { + rect = m_container->geometry(); + rect.setSize(rect.size() + size); + m_container->setGeometry(rect); + } +} + +QTEST_KDEMAIN(KItemListControllerTest, GUI) + +#include "kitemlistcontrollertest.moc"