X-Git-Url: https://cloud.milkyroute.net/gitweb/dolphin.git/blobdiff_plain/3696213ccbbe27e9ef3fc85eb97dd32fd669066f..0464ea82a6850f58805bc4d6fc1df5369d83c3df:/src/tests/kitemlistcontrollertest.cpp diff --git a/src/tests/kitemlistcontrollertest.cpp b/src/tests/kitemlistcontrollertest.cpp index a882accaa..e9e1e66c2 100644 --- a/src/tests/kitemlistcontrollertest.cpp +++ b/src/tests/kitemlistcontrollertest.cpp @@ -73,8 +73,10 @@ private Q_SLOTS: void init(); void cleanup(); - void testKeyboardNavigation_data(); - void testKeyboardNavigation(); + void testKeyboardNavigationMultiSelection_data(); + void testKeyboardNavigationMultiSelection(); + void testKeyboardNavigationSingleSelectionNoSelection_data(); + void testKeyboardNavigationSingleSelectionNoSelection(); void testMouseClickActivation(); private: @@ -170,6 +172,9 @@ void KItemListControllerTest::init() const QSizeF itemSize(50, 50); m_view->setItemSize(itemSize); QCOMPARE(m_view->itemSize(), itemSize); + + m_controller->setSelectionBehavior(KItemListController::MultiSelection); + QCOMPARE(m_controller->selectionBehavior(), KItemListController::MultiSelection); } void KItemListControllerTest::cleanup() @@ -217,14 +222,441 @@ 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, + * This function tests all possible combinations of view layouts, layout direction, * 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() +void KItemListControllerTest::testKeyboardNavigationMultiSelection_data() +{ + QTest::addColumn("layout"); + QTest::addColumn("scrollOrientation"); + QTest::addColumn("columnCount"); + QTest::addColumn("groupingEnabled"); + QTest::addColumn("layoutDirection"); + QTest::addColumn( + "selectionModeEnabled"); // Don't confuse this with "selectionBehaviour". This is about changing controls for users to help multi-selecting. + QTest::addColumn>>("testList"); + + QList layoutList; + QHash layoutNames; + layoutList.append(KFileItemListView::IconsLayout); + layoutNames[KFileItemListView::IconsLayout] = "Icons"; + layoutList.append(KFileItemListView::CompactLayout); + layoutNames[KFileItemListView::CompactLayout] = "Compact"; + layoutList.append(KFileItemListView::DetailsLayout); + layoutNames[KFileItemListView::DetailsLayout] = "Details"; + + QList groupingEnabledList; + QHash groupingEnabledNames; + groupingEnabledList.append(false); + groupingEnabledNames[false] = "ungrouped"; + groupingEnabledList.append(true); + groupingEnabledNames[true] = "grouping enabled"; + + QList layoutDirectionList; + QHash layoutDirectionNames; + layoutDirectionList.append(Qt::LeftToRight); + layoutDirectionNames[Qt::LeftToRight] = "Left-to-Right LayoutDirection"; + layoutDirectionList.append(Qt::RightToLeft); + layoutDirectionNames[Qt::RightToLeft] = "Right-to-Left LayoutDirection"; + + bool selectionModeEnabled = false; // For most tests this is kept disabled because it is not really affected by all the other test conditions. + // We only enable it for a few separate tests at the end. + + for (const KFileItemListView::ItemLayout &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_Right; + Qt::Key previousItemKey = Qt::Key_Right; + Qt::Key nextRowKey = Qt::Key_Right; + Qt::Key previousRowKey = Qt::Key_Right; + + 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; + } + for (auto layoutDirection : std::as_const(layoutDirectionList)) { + if (layoutDirection == Qt::RightToLeft) { + switch (layout) { + case KFileItemListView::IconsLayout: + std::swap(nextItemKey, previousItemKey); + break; + case KFileItemListView::CompactLayout: + std::swap(nextRowKey, previousRowKey); + break; + default: + break; + } + } + for (int columnCount : std::as_const(columnCountList)) { + for (bool groupingEnabled : std::as_const(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, KItemSet() << 1)) + << qMakePair(KeyPress(Qt::Key_Return), ViewState(1, KItemSet() << 1, true)) + << qMakePair(KeyPress(Qt::Key_Enter), ViewState(1, KItemSet() << 1, true)) + << qMakePair(KeyPress(nextItemKey), ViewState(2, KItemSet() << 2)) + << qMakePair(KeyPress(nextItemKey, Qt::ShiftModifier), ViewState(3, KItemSet() << 2 << 3)) + << qMakePair(KeyPress(Qt::Key_Return), ViewState(3, KItemSet() << 2 << 3, true)) + << qMakePair(KeyPress(previousItemKey, Qt::ShiftModifier), ViewState(2, KItemSet() << 2)) + << qMakePair(KeyPress(nextItemKey, Qt::ShiftModifier), ViewState(3, KItemSet() << 2 << 3)) + << qMakePair(KeyPress(nextItemKey, Qt::ControlModifier), ViewState(4, KItemSet() << 2 << 3)) + << qMakePair(KeyPress(Qt::Key_Return), ViewState(4, KItemSet() << 2 << 3, true)) + << qMakePair(KeyPress(previousItemKey), ViewState(3, KItemSet() << 3)) + << qMakePair(KeyPress(Qt::Key_Home, Qt::ShiftModifier), ViewState(0, KItemSet() << 0 << 1 << 2 << 3)) + << qMakePair(KeyPress(nextItemKey, Qt::ControlModifier), ViewState(1, KItemSet() << 0 << 1 << 2 << 3)) + << qMakePair(KeyPress(Qt::Key_Space, Qt::ControlModifier), ViewState(1, KItemSet() << 0 << 2 << 3)) + << qMakePair(KeyPress(Qt::Key_Space, Qt::ControlModifier), ViewState(1, KItemSet() << 0 << 1 << 2 << 3)) + << qMakePair(KeyPress(Qt::Key_End), ViewState(19, KItemSet() << 19)) + << qMakePair(KeyPress(previousItemKey, Qt::ShiftModifier), ViewState(18, KItemSet() << 18 << 19)) + << qMakePair(KeyPress(Qt::Key_Home), ViewState(0, KItemSet() << 0)) + << qMakePair(KeyPress(Qt::Key_Space, Qt::ControlModifier), ViewState(0, KItemSet())) + << qMakePair(KeyPress(Qt::Key_Enter), ViewState(0, KItemSet(), true)) + << qMakePair(KeyPress(Qt::Key_Space, Qt::ControlModifier), ViewState(0, KItemSet() << 0)) + << qMakePair(KeyPress(Qt::Key_Space, Qt::ControlModifier), ViewState(0, KItemSet())) + << qMakePair(KeyPress(Qt::Key_Space), ViewState(0, KItemSet() << 0)) + << qMakePair(KeyPress(Qt::Key_E), ViewState(13, KItemSet() << 13)) + << qMakePair(KeyPress(Qt::Key_Space), ViewState(14, KItemSet() << 14)) + << qMakePair(KeyPress(Qt::Key_3), ViewState(15, KItemSet() << 15)) + << qMakePair(KeyPress(Qt::Key_Escape), ViewState(15, KItemSet())) + << qMakePair(KeyPress(Qt::Key_E), ViewState(13, KItemSet() << 13)) + << qMakePair(KeyPress(Qt::Key_E), ViewState(14, KItemSet() << 14)) + << qMakePair(KeyPress(previousItemKey), ViewState(13, KItemSet() << 13)) + << qMakePair(KeyPress(Qt::Key_E), ViewState(14, KItemSet() << 14)) + << qMakePair(KeyPress(Qt::Key_Escape), ViewState(14, KItemSet())) + << qMakePair(KeyPress(Qt::Key_E), ViewState(13, KItemSet() << 13)) + << qMakePair(KeyPress(Qt::Key_Home), ViewState(0, KItemSet() << 0)) + << qMakePair(KeyPress(Qt::Key_Escape), ViewState(0, KItemSet())); + + // 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, KItemSet() << 1)) + << qMakePair(KeyPress(nextRowKey, Qt::ShiftModifier), ViewState(2, KItemSet() << 1 << 2)) + << qMakePair(KeyPress(nextRowKey, Qt::ControlModifier), ViewState(3, KItemSet() << 1 << 2)) + << qMakePair(KeyPress(previousRowKey), ViewState(2, KItemSet() << 2)) + << qMakePair(KeyPress(previousItemKey), ViewState(1, KItemSet() << 1)) + << qMakePair(KeyPress(Qt::Key_Home), ViewState(0, KItemSet() << 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, KItemSet() << 3)) + << qMakePair(KeyPress(nextItemKey, Qt::ControlModifier), ViewState(4, KItemSet() << 3)) + << qMakePair(KeyPress(nextRowKey), ViewState(7, KItemSet() << 7)) + << qMakePair(KeyPress(nextItemKey, Qt::ShiftModifier), ViewState(8, KItemSet() << 7 << 8)) + << qMakePair(KeyPress(nextItemKey, Qt::ShiftModifier), ViewState(9, KItemSet() << 7 << 8 << 9)) + << qMakePair(KeyPress(previousItemKey, Qt::ShiftModifier), ViewState(8, KItemSet() << 7 << 8)) + << qMakePair(KeyPress(previousItemKey, Qt::ShiftModifier), ViewState(7, KItemSet() << 7)) + << qMakePair(KeyPress(previousItemKey, Qt::ShiftModifier), ViewState(6, KItemSet() << 6 << 7)) + << qMakePair(KeyPress(previousItemKey, Qt::ShiftModifier), ViewState(5, KItemSet() << 5 << 6 << 7)) + << qMakePair(KeyPress(nextItemKey, Qt::ShiftModifier), ViewState(6, KItemSet() << 6 << 7)) + << qMakePair(KeyPress(nextItemKey, Qt::ShiftModifier), ViewState(7, KItemSet() << 7)) + << qMakePair(KeyPress(nextRowKey), ViewState(10, KItemSet() << 10)) + << qMakePair(KeyPress(nextItemKey), ViewState(11, KItemSet() << 11)) + << qMakePair(KeyPress(nextRowKey), ViewState(14, KItemSet() << 14)) + << qMakePair(KeyPress(nextRowKey), ViewState(17, KItemSet() << 17)) + << qMakePair(KeyPress(nextRowKey), ViewState(19, KItemSet() << 19)) + << qMakePair(KeyPress(previousRowKey), ViewState(17, KItemSet() << 17)) + << qMakePair(KeyPress(Qt::Key_End), ViewState(19, KItemSet() << 19)) + << qMakePair(KeyPress(previousRowKey), ViewState(16, KItemSet() << 16)) + << qMakePair(KeyPress(Qt::Key_Home), ViewState(0, KItemSet() << 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, KItemSet() << 5)) + << qMakePair(KeyPress(nextItemKey, Qt::ControlModifier), ViewState(6, KItemSet() << 5)) + << qMakePair(KeyPress(nextRowKey), ViewState(11, KItemSet() << 11)) + << qMakePair(KeyPress(nextItemKey), ViewState(12, KItemSet() << 12)) + << qMakePair(KeyPress(nextRowKey, Qt::ShiftModifier), ViewState(17, KItemSet() << 12 << 13 << 14 << 15 << 16 << 17)) + << qMakePair(KeyPress(previousRowKey, Qt::ShiftModifier), ViewState(12, KItemSet() << 12)) + << qMakePair(KeyPress(previousRowKey, Qt::ShiftModifier), ViewState(7, KItemSet() << 7 << 8 << 9 << 10 << 11 << 12)) + << qMakePair(KeyPress(nextRowKey, Qt::ShiftModifier), ViewState(12, KItemSet() << 12)) + << qMakePair(KeyPress(Qt::Key_End, Qt::ControlModifier), ViewState(19, KItemSet() << 12)) + << qMakePair(KeyPress(previousRowKey), ViewState(14, KItemSet() << 14)) + << qMakePair(KeyPress(Qt::Key_Home), ViewState(0, KItemSet() << 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, KItemSet() << 1)) + << qMakePair(KeyPress(nextItemKey), ViewState(2, KItemSet() << 2)) + << qMakePair(KeyPress(nextRowKey, Qt::ShiftModifier), ViewState(3, KItemSet() << 2 << 3)) + << qMakePair(KeyPress(nextRowKey, Qt::ShiftModifier), ViewState(6, KItemSet() << 2 << 3 << 4 << 5 << 6)) + << qMakePair(KeyPress(nextRowKey), ViewState(8, KItemSet() << 8)) + << qMakePair(KeyPress(nextRowKey), ViewState(11, KItemSet() << 11)) + << qMakePair(KeyPress(nextItemKey, Qt::ControlModifier), ViewState(12, KItemSet() << 11)) + << qMakePair(KeyPress(nextRowKey), ViewState(13, KItemSet() << 13)) + << qMakePair(KeyPress(nextRowKey), ViewState(16, KItemSet() << 16)) + << qMakePair(KeyPress(nextItemKey), ViewState(17, KItemSet() << 17)) + << qMakePair(KeyPress(nextRowKey), ViewState(19, KItemSet() << 19)) + << qMakePair(KeyPress(previousRowKey), ViewState(17, KItemSet() << 17)) + << qMakePair(KeyPress(Qt::Key_Home), ViewState(0, KItemSet() << 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, KItemSet() << 1)) + << qMakePair(KeyPress(nextRowKey, Qt::ShiftModifier), ViewState(3, KItemSet() << 1 << 2 << 3)) + << qMakePair(KeyPress(nextRowKey, Qt::ShiftModifier), ViewState(5, KItemSet() << 1 << 2 << 3 << 4 << 5)) + << qMakePair(KeyPress(nextItemKey), ViewState(6, KItemSet() << 6)) + << qMakePair(KeyPress(nextItemKey, Qt::ControlModifier), ViewState(7, KItemSet() << 6)) + << qMakePair(KeyPress(nextItemKey, Qt::ControlModifier), ViewState(8, KItemSet() << 6)) + << qMakePair(KeyPress(nextRowKey), ViewState(12, KItemSet() << 12)) + << qMakePair(KeyPress(nextRowKey), ViewState(17, KItemSet() << 17)) + << qMakePair(KeyPress(nextRowKey), ViewState(19, KItemSet() << 19)) + << qMakePair(KeyPress(previousRowKey), ViewState(17, KItemSet() << 17)) + << qMakePair(KeyPress(Qt::Key_End, Qt::ShiftModifier), ViewState(19, KItemSet() << 17 << 18 << 19)) + << qMakePair(KeyPress(previousRowKey, Qt::ShiftModifier), ViewState(14, KItemSet() << 14 << 15 << 16 << 17)) + << qMakePair(KeyPress(Qt::Key_Home), ViewState(0, KItemSet() << 0)); + } + + const QString testName = layoutNames[layout] + ", " + QStringLiteral("%1 columns, ").arg(columnCount) + + groupingEnabledNames[groupingEnabled] + ", " + layoutDirectionNames[layoutDirection]; + + const QByteArray testNameAscii = testName.toLatin1(); + + QTest::newRow(testNameAscii.data()) + << layout << scrollOrientation << columnCount << groupingEnabled << layoutDirection << selectionModeEnabled << testList; + } + } + } + } + + /** + * Selection mode tests + * We only test for the default icon view mode with typical scrollOrientation, selectionBehaviour, no grouping, left-to-right layoutDirection because none + * of this should affect selection mode and special-casing selection mode within the above test would make the above code even more complex than it already + * is. + */ + selectionModeEnabled = true; + const KFileItemListView::ItemLayout layout = KFileItemListView::IconsLayout; + const Qt::Orientation scrollOrientation = Qt::Vertical; + const int columnCount = 3; + const Qt::Key nextItemKey = Qt::Key_Right; + const Qt::Key previousItemKey = Qt::Key_Left; + const Qt::Key nextRowKey = Qt::Key_Down; + const Qt::Key previousRowKey = Qt::Key_Up; + + const Qt::LayoutDirection layoutDirection = Qt::LeftToRight; + const bool groupingEnabled = false; + + QList> testList; + + testList << qMakePair(KeyPress(nextItemKey), ViewState(1, KItemSet())) // In selection mode nothing is selected simply by moving with arrow keys. + << qMakePair(KeyPress(Qt::Key_Return), ViewState(1, KItemSet() << 1)) // Pressing Return toggles the selection but does not activate. + << qMakePair(KeyPress(Qt::Key_Enter), ViewState(1, KItemSet())) // Pressing Enter toggles the selection but does not activate. + << qMakePair(KeyPress(nextItemKey), ViewState(2, KItemSet())) + << qMakePair(KeyPress(nextItemKey, Qt::ShiftModifier), ViewState(3, KItemSet() << 2 << 3)) // Shift+Arrow key still selects in selection mode. + << qMakePair(KeyPress(Qt::Key_Return), ViewState(3, KItemSet() << 2)) + << qMakePair(KeyPress(previousItemKey, Qt::ShiftModifier), ViewState(2, KItemSet() << 2 << 3)) + << qMakePair(KeyPress(nextItemKey, Qt::ShiftModifier), ViewState(3, KItemSet() << 2)) // Shift+Left and then Shift+Right cancel each other out. + << qMakePair(KeyPress(nextItemKey, Qt::ControlModifier), ViewState(4, KItemSet() << 2)) + << qMakePair(KeyPress(Qt::Key_Return), ViewState(4, KItemSet() << 2 << 4)) + << qMakePair(KeyPress(previousItemKey), ViewState(3, KItemSet() << 2 << 4)) + << qMakePair(KeyPress(Qt::Key_Home, Qt::ShiftModifier), ViewState(0, KItemSet() << 0 << 1 << 2 << 3 << 4)) + << qMakePair(KeyPress(nextItemKey, Qt::ControlModifier), ViewState(1, KItemSet() << 0 << 1 << 2 << 3 << 4)) + << qMakePair(KeyPress(Qt::Key_Space, Qt::ControlModifier), ViewState(1, KItemSet() << 0 << 2 << 3 << 4)) + << qMakePair(KeyPress(Qt::Key_Space, Qt::ControlModifier), ViewState(1, KItemSet() << 0 << 1 << 2 << 3 << 4)) + << qMakePair(KeyPress(Qt::Key_End), ViewState(19, KItemSet() << 0 << 1 << 2 << 3 << 4)) + << qMakePair(KeyPress(previousItemKey, Qt::ShiftModifier), ViewState(18, KItemSet() << 0 << 1 << 2 << 3 << 4 << 18 << 19)) + << qMakePair(KeyPress(Qt::Key_Home), ViewState(0, KItemSet() << 0 << 1 << 2 << 3 << 4 << 18 << 19)) + << qMakePair(KeyPress(Qt::Key_Space, Qt::ControlModifier), ViewState(0, KItemSet() << 1 << 2 << 3 << 4 << 18 << 19)) + << qMakePair(KeyPress(Qt::Key_Enter), ViewState(0, KItemSet() << 0 << 1 << 2 << 3 << 4 << 18 << 19)) + << qMakePair(KeyPress(Qt::Key_Space, Qt::ControlModifier), ViewState(0, KItemSet() << 1 << 2 << 3 << 4 << 18 << 19)) + << qMakePair(KeyPress(Qt::Key_Space, Qt::ControlModifier), ViewState(0, KItemSet() << 0 << 1 << 2 << 3 << 4 << 18 << 19)) + << qMakePair(KeyPress(Qt::Key_Space), ViewState(0, KItemSet() << 1 << 2 << 3 << 4 << 18 << 19)) // Space toggles selection in selection mode. + << qMakePair(KeyPress(Qt::Key_D), ViewState(9, KItemSet() << 1 << 2 << 3 << 4 << 18 << 19)) // No selection change by type-ahead. + << qMakePair(KeyPress(Qt::Key_Space), ViewState(9, KItemSet() << 1 << 2 << 3 << 4 << 9 << 18 << 19)) // Space is not added to type-ahead. + << qMakePair(KeyPress(Qt::Key_4), ViewState(12, KItemSet() << 1 << 2 << 3 << 4 << 9 << 18 << 19)) // No selection change by type-ahead. + << qMakePair(KeyPress(Qt::Key_Home), ViewState(0, KItemSet() << 1 << 2 << 3 << 4 << 9 << 18 << 19)) + + // The following tests assume a columnCount of three and no grouping enabled. + << qMakePair(KeyPress(nextRowKey), ViewState(3, KItemSet() << 1 << 2 << 3 << 4 << 9 << 18 << 19)) + << qMakePair(KeyPress(nextItemKey, Qt::ControlModifier), ViewState(4, KItemSet() << 1 << 2 << 3 << 4 << 9 << 18 << 19)) + << qMakePair(KeyPress(nextRowKey), ViewState(7, KItemSet() << 1 << 2 << 3 << 4 << 9 << 18 << 19)) + << qMakePair(KeyPress(nextItemKey, Qt::ShiftModifier), ViewState(8, KItemSet() << 1 << 2 << 3 << 4 << 7 << 8 << 9 << 18 << 19)) + << qMakePair(KeyPress(nextItemKey, Qt::ShiftModifier), ViewState(9, KItemSet() << 1 << 2 << 3 << 4 << 7 << 8 << 9 << 18 << 19)) + << qMakePair(KeyPress(previousItemKey, Qt::ShiftModifier), ViewState(8, KItemSet() << 1 << 2 << 3 << 4 << 7 << 8 << 9 << 18 << 19)) + << qMakePair(KeyPress(previousItemKey, Qt::ShiftModifier), ViewState(7, KItemSet() << 1 << 2 << 3 << 4 << 9 << 18 << 19)) + << qMakePair(KeyPress(previousItemKey, Qt::ShiftModifier), ViewState(6, KItemSet() << 1 << 2 << 3 << 4 << 6 << 7 << 9 << 18 << 19)) + << qMakePair(KeyPress(previousItemKey, Qt::ShiftModifier), ViewState(5, KItemSet() << 1 << 2 << 3 << 4 << 5 << 6 << 7 << 9 << 18 << 19)) + << qMakePair(KeyPress(nextItemKey, Qt::ShiftModifier), ViewState(6, KItemSet() << 1 << 2 << 3 << 4 << 6 << 7 << 9 << 18 << 19)) + << qMakePair(KeyPress(nextItemKey, Qt::ShiftModifier), ViewState(7, KItemSet() << 1 << 2 << 3 << 4 << 9 << 18 << 19)) + << qMakePair(KeyPress(nextRowKey), ViewState(10, KItemSet() << 1 << 2 << 3 << 4 << 9 << 18 << 19)) + << qMakePair(KeyPress(nextItemKey), ViewState(11, KItemSet() << 1 << 2 << 3 << 4 << 9 << 18 << 19)) + << qMakePair(KeyPress(nextRowKey), ViewState(14, KItemSet() << 1 << 2 << 3 << 4 << 9 << 18 << 19)) + << qMakePair(KeyPress(nextRowKey), ViewState(17, KItemSet() << 1 << 2 << 3 << 4 << 9 << 18 << 19)) + << qMakePair(KeyPress(nextRowKey), ViewState(19, KItemSet() << 1 << 2 << 3 << 4 << 9 << 18 << 19)) + << qMakePair(KeyPress(previousRowKey), ViewState(17, KItemSet() << 1 << 2 << 3 << 4 << 9 << 18 << 19)) + << qMakePair(KeyPress(Qt::Key_End), ViewState(19, KItemSet() << 1 << 2 << 3 << 4 << 9 << 18 << 19)) + << qMakePair(KeyPress(previousRowKey), ViewState(16, KItemSet() << 1 << 2 << 3 << 4 << 9 << 18 << 19)) + << qMakePair(KeyPress(Qt::Key_Home), ViewState(0, KItemSet() << 1 << 2 << 3 << 4 << 9 << 18 << 19)); + + const QString testName = "Selection Mode: " + layoutNames[layout] + ", " + QStringLiteral("%1 columns, ").arg(columnCount) + + groupingEnabledNames[groupingEnabled] + ", " + layoutDirectionNames[layoutDirection]; + + const QByteArray testNameAscii = testName.toLatin1(); + + QTest::newRow(testNameAscii.data()) << layout << scrollOrientation << columnCount << groupingEnabled << layoutDirection << selectionModeEnabled << testList; +} + +/** + * This function sets the view's properties according to the data provided. + * + * 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::testKeyboardNavigationMultiSelection() +{ + QFETCH(KFileItemListView::ItemLayout, layout); + QFETCH(Qt::Orientation, scrollOrientation); + QFETCH(int, columnCount); + QFETCH(bool, groupingEnabled); + QFETCH(Qt::LayoutDirection, layoutDirection); + QFETCH(bool, selectionModeEnabled); + QFETCH(QList, testList); + + QApplication::setLayoutDirection(layoutDirection); + m_view->setLayoutDirection(layoutDirection); + + m_view->setItemLayout(layout); + QCOMPARE(m_view->itemLayout(), layout); + + m_view->setScrollOrientation(scrollOrientation); + QCOMPARE(m_view->scrollOrientation(), scrollOrientation); + + m_controller->setSelectionBehavior(KItemListController::MultiSelection); + QCOMPARE(m_controller->selectionBehavior(), KItemListController::MultiSelection); + + m_model->setGroupedSorting(groupingEnabled); + QCOMPARE(m_model->groupedSorting(), groupingEnabled); + + m_controller->setSelectionModeEnabled(selectionModeEnabled); + QCOMPARE(m_controller->selectionMode(), selectionModeEnabled); + + adjustGeometryForColumnCount(columnCount); + QCOMPARE(m_view->m_layouter->m_columnCount, columnCount); + + QSignalSpy spySingleItemActivated(m_controller, &KItemListController::itemActivated); + QSignalSpy spyMultipleItemsActivated(m_controller, &KItemListController::itemsActivated); + + int rowCount = 0; + while (!testList.isEmpty()) { + ++rowCount; + 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 KItemSet selection = test.second.m_selection; + const bool activated = test.second.m_activated; + + QTest::keyClick(m_container, key, modifier); + + QVERIFY2( + m_selectionManager->currentItem() == current, + qPrintable(QStringLiteral("currentItem() returns index %1 but %2 would be expected. Before this, key \"%3\" was pressed. This test case is defined " + "in row %4 of the testList from KItemListControllerTest::testKeyboardNavigationMultiSelection_data().") + .arg(m_selectionManager->currentItem()) + .arg(current) + .arg(QKeySequence(key).toString()) + .arg(rowCount))); + QCOMPARE(m_selectionManager->selectedItems(), selection); + + if (activated) { + if (!selection.isEmpty()) { + // The selected items should be activated. + if (selection.count() == 1) { + QVERIFY(!spySingleItemActivated.isEmpty()); + QCOMPARE(qvariant_cast(spySingleItemActivated.takeFirst().at(0)), selection.first()); + QVERIFY(spyMultipleItemsActivated.isEmpty()); + } else { + QVERIFY(spySingleItemActivated.isEmpty()); + QVERIFY(!spyMultipleItemsActivated.isEmpty()); + QCOMPARE(qvariant_cast(spyMultipleItemsActivated.takeFirst().at(0)), selection); + } + } else { + QVERIFY(!spySingleItemActivated.isEmpty()); + QCOMPARE(qvariant_cast(spySingleItemActivated.takeFirst().at(0)), current); + QVERIFY(spyMultipleItemsActivated.isEmpty()); + } + } + } +} + +/** + * This function tests all possible combinations of view layouts, layout direction, + * 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::testKeyboardNavigationSingleSelectionNoSelection_data() { QTest::addColumn("layout"); QTest::addColumn("scrollOrientation"); @@ -251,8 +683,6 @@ void KItemListControllerTest::testKeyboardNavigation_data() selectionBehaviorNames[KItemListController::NoSelection] = "NoSelection"; selectionBehaviorList.append(KItemListController::SingleSelection); selectionBehaviorNames[KItemListController::SingleSelection] = "SingleSelection"; - selectionBehaviorList.append(KItemListController::MultiSelection); - selectionBehaviorNames[KItemListController::MultiSelection] = "MultiSelection"; QList groupingEnabledList; QHash groupingEnabledNames; @@ -277,10 +707,10 @@ void KItemListControllerTest::testKeyboardNavigation_data() // Compact layout. Qt::Orientation scrollOrientation; QList columnCountList; - Qt::Key nextItemKey; - Qt::Key previousItemKey; - Qt::Key nextRowKey; - Qt::Key previousRowKey; + Qt::Key nextItemKey = Qt::Key_Right; + Qt::Key previousItemKey = Qt::Key_Right; + Qt::Key nextRowKey = Qt::Key_Right; + Qt::Key previousRowKey = Qt::Key_Right; switch (layout) { case KFileItemListView::IconsLayout: @@ -355,11 +785,12 @@ void KItemListControllerTest::testKeyboardNavigation_data() << qMakePair(KeyPress(Qt::Key_Space), ViewState(14, KItemSet() << 14)) << qMakePair(KeyPress(Qt::Key_3), ViewState(15, KItemSet() << 15)) << qMakePair(KeyPress(Qt::Key_Escape), ViewState(15, KItemSet())) - << qMakePair(KeyPress(Qt::Key_E), ViewState(13, KItemSet() << 13)) - << qMakePair(KeyPress(Qt::Key_E), ViewState(14, KItemSet() << 14)) - << qMakePair(KeyPress(Qt::Key_E), ViewState(15, KItemSet() << 15)) - << qMakePair(KeyPress(Qt::Key_Escape), ViewState(15, KItemSet())) - << qMakePair(KeyPress(Qt::Key_E), ViewState(13, KItemSet() << 13)) + << qMakePair(KeyPress(Qt::Key_E), ViewState(16, KItemSet() << 16)) + << qMakePair(KeyPress(Qt::Key_E), ViewState(17, KItemSet() << 17)) + << qMakePair(KeyPress(previousItemKey), ViewState(16, KItemSet() << 16)) + << qMakePair(KeyPress(Qt::Key_E), ViewState(17, KItemSet() << 17)) + << qMakePair(KeyPress(Qt::Key_Escape), ViewState(17, KItemSet())) + << qMakePair(KeyPress(Qt::Key_E), ViewState(18, KItemSet() << 18)) << qMakePair(KeyPress(Qt::Key_Home), ViewState(0, KItemSet() << 0)) << qMakePair(KeyPress(Qt::Key_Escape), ViewState(0, KItemSet())); @@ -497,95 +928,15 @@ void KItemListControllerTest::testKeyboardNavigation_data() } } } - - /** - * Selection mode tests - * We only test for the default icon view mode with typical scrollOrientation, selectionBehaviour, no grouping, left-to-right layoutDirection because none - * of this should affect selection mode and special-casing selection mode within the above test would make the above code even more complex than it already - * is. - */ - selectionModeEnabled = true; - const KFileItemListView::ItemLayout layout = KFileItemListView::IconsLayout; - const Qt::Orientation scrollOrientation = Qt::Vertical; - const int columnCount = 3; - const Qt::Key nextItemKey = Qt::Key_Right; - const Qt::Key previousItemKey = Qt::Key_Left; - const Qt::Key nextRowKey = Qt::Key_Down; - const Qt::Key previousRowKey = Qt::Key_Up; - - const Qt::LayoutDirection layoutDirection = Qt::LeftToRight; - const KItemListController::SelectionBehavior &selectionBehavior = KItemListController::MultiSelection; - const bool groupingEnabled = false; - - QList> testList; - - testList << qMakePair(KeyPress(nextItemKey), ViewState(1, KItemSet())) // In selection mode nothing is selected simply by moving with arrow keys. - << qMakePair(KeyPress(Qt::Key_Return), ViewState(1, KItemSet() << 1)) // Pressing Return toggles the selection but does not activate. - << qMakePair(KeyPress(Qt::Key_Enter), ViewState(1, KItemSet())) // Pressing Enter toggles the selection but does not activate. - << qMakePair(KeyPress(nextItemKey), ViewState(2, KItemSet())) - << qMakePair(KeyPress(nextItemKey, Qt::ShiftModifier), ViewState(3, KItemSet() << 2 << 3)) // Shift+Arrow key still selects in selection mode. - << qMakePair(KeyPress(Qt::Key_Return), ViewState(3, KItemSet() << 2)) - << qMakePair(KeyPress(previousItemKey, Qt::ShiftModifier), ViewState(2, KItemSet() << 2 << 3)) - << qMakePair(KeyPress(nextItemKey, Qt::ShiftModifier), ViewState(3, KItemSet() << 2)) // Shift+Left and then Shift+Right cancel each other out. - << qMakePair(KeyPress(nextItemKey, Qt::ControlModifier), ViewState(4, KItemSet() << 2)) - << qMakePair(KeyPress(Qt::Key_Return), ViewState(4, KItemSet() << 2 << 4)) - << qMakePair(KeyPress(previousItemKey), ViewState(3, KItemSet() << 2 << 4)) - << qMakePair(KeyPress(Qt::Key_Home, Qt::ShiftModifier), ViewState(0, KItemSet() << 0 << 1 << 2 << 3 << 4)) - << qMakePair(KeyPress(nextItemKey, Qt::ControlModifier), ViewState(1, KItemSet() << 0 << 1 << 2 << 3 << 4)) - << qMakePair(KeyPress(Qt::Key_Space, Qt::ControlModifier), ViewState(1, KItemSet() << 0 << 2 << 3 << 4)) - << qMakePair(KeyPress(Qt::Key_Space, Qt::ControlModifier), ViewState(1, KItemSet() << 0 << 1 << 2 << 3 << 4)) - << qMakePair(KeyPress(Qt::Key_End), ViewState(19, KItemSet() << 0 << 1 << 2 << 3 << 4)) - << qMakePair(KeyPress(previousItemKey, Qt::ShiftModifier), ViewState(18, KItemSet() << 0 << 1 << 2 << 3 << 4 << 18 << 19)) - << qMakePair(KeyPress(Qt::Key_Home), ViewState(0, KItemSet() << 0 << 1 << 2 << 3 << 4 << 18 << 19)) - << qMakePair(KeyPress(Qt::Key_Space, Qt::ControlModifier), ViewState(0, KItemSet() << 1 << 2 << 3 << 4 << 18 << 19)) - << qMakePair(KeyPress(Qt::Key_Enter), ViewState(0, KItemSet() << 0 << 1 << 2 << 3 << 4 << 18 << 19)) - << qMakePair(KeyPress(Qt::Key_Space, Qt::ControlModifier), ViewState(0, KItemSet() << 1 << 2 << 3 << 4 << 18 << 19)) - << qMakePair(KeyPress(Qt::Key_Space, Qt::ControlModifier), ViewState(0, KItemSet() << 0 << 1 << 2 << 3 << 4 << 18 << 19)) - << qMakePair(KeyPress(Qt::Key_Space), ViewState(0, KItemSet() << 1 << 2 << 3 << 4 << 18 << 19)) // Space toggles selection in selection mode. - << qMakePair(KeyPress(Qt::Key_D), ViewState(9, KItemSet() << 1 << 2 << 3 << 4 << 18 << 19)) // No selection change by type-ahead. - << qMakePair(KeyPress(Qt::Key_Space), ViewState(9, KItemSet() << 1 << 2 << 3 << 4 << 9 << 18 << 19)) // Space is not added to type-ahead. - << qMakePair(KeyPress(Qt::Key_4), ViewState(12, KItemSet() << 1 << 2 << 3 << 4 << 9 << 18 << 19)) // No selection change by type-ahead. - << qMakePair(KeyPress(Qt::Key_Home), ViewState(0, KItemSet() << 1 << 2 << 3 << 4 << 9 << 18 << 19)) - - // The following tests assume a columnCount of three and no grouping enabled. - << qMakePair(KeyPress(nextRowKey), ViewState(3, KItemSet() << 1 << 2 << 3 << 4 << 9 << 18 << 19)) - << qMakePair(KeyPress(nextItemKey, Qt::ControlModifier), ViewState(4, KItemSet() << 1 << 2 << 3 << 4 << 9 << 18 << 19)) - << qMakePair(KeyPress(nextRowKey), ViewState(7, KItemSet() << 1 << 2 << 3 << 4 << 9 << 18 << 19)) - << qMakePair(KeyPress(nextItemKey, Qt::ShiftModifier), ViewState(8, KItemSet() << 1 << 2 << 3 << 4 << 7 << 8 << 9 << 18 << 19)) - << qMakePair(KeyPress(nextItemKey, Qt::ShiftModifier), ViewState(9, KItemSet() << 1 << 2 << 3 << 4 << 7 << 8 << 9 << 18 << 19)) - << qMakePair(KeyPress(previousItemKey, Qt::ShiftModifier), ViewState(8, KItemSet() << 1 << 2 << 3 << 4 << 7 << 8 << 9 << 18 << 19)) - << qMakePair(KeyPress(previousItemKey, Qt::ShiftModifier), ViewState(7, KItemSet() << 1 << 2 << 3 << 4 << 9 << 18 << 19)) - << qMakePair(KeyPress(previousItemKey, Qt::ShiftModifier), ViewState(6, KItemSet() << 1 << 2 << 3 << 4 << 6 << 7 << 9 << 18 << 19)) - << qMakePair(KeyPress(previousItemKey, Qt::ShiftModifier), ViewState(5, KItemSet() << 1 << 2 << 3 << 4 << 5 << 6 << 7 << 9 << 18 << 19)) - << qMakePair(KeyPress(nextItemKey, Qt::ShiftModifier), ViewState(6, KItemSet() << 1 << 2 << 3 << 4 << 6 << 7 << 9 << 18 << 19)) - << qMakePair(KeyPress(nextItemKey, Qt::ShiftModifier), ViewState(7, KItemSet() << 1 << 2 << 3 << 4 << 9 << 18 << 19)) - << qMakePair(KeyPress(nextRowKey), ViewState(10, KItemSet() << 1 << 2 << 3 << 4 << 9 << 18 << 19)) - << qMakePair(KeyPress(nextItemKey), ViewState(11, KItemSet() << 1 << 2 << 3 << 4 << 9 << 18 << 19)) - << qMakePair(KeyPress(nextRowKey), ViewState(14, KItemSet() << 1 << 2 << 3 << 4 << 9 << 18 << 19)) - << qMakePair(KeyPress(nextRowKey), ViewState(17, KItemSet() << 1 << 2 << 3 << 4 << 9 << 18 << 19)) - << qMakePair(KeyPress(nextRowKey), ViewState(19, KItemSet() << 1 << 2 << 3 << 4 << 9 << 18 << 19)) - << qMakePair(KeyPress(previousRowKey), ViewState(17, KItemSet() << 1 << 2 << 3 << 4 << 9 << 18 << 19)) - << qMakePair(KeyPress(Qt::Key_End), ViewState(19, KItemSet() << 1 << 2 << 3 << 4 << 9 << 18 << 19)) - << qMakePair(KeyPress(previousRowKey), ViewState(16, KItemSet() << 1 << 2 << 3 << 4 << 9 << 18 << 19)) - << qMakePair(KeyPress(Qt::Key_Home), ViewState(0, KItemSet() << 1 << 2 << 3 << 4 << 9 << 18 << 19)); - - const QString testName = "Selection Mode: " + layoutNames[layout] + ", " + QStringLiteral("%1 columns, ").arg(columnCount) - + selectionBehaviorNames[selectionBehavior] + ", " + groupingEnabledNames[groupingEnabled] + ", " + layoutDirectionNames[layoutDirection]; - - const QByteArray testNameAscii = testName.toLatin1(); - - QTest::newRow(testNameAscii.data()) << layout << scrollOrientation << columnCount << selectionBehavior << groupingEnabled << layoutDirection - << selectionModeEnabled << testList; } /** - * This function sets the view's properties according to the data provided by - * KItemListControllerTest::testKeyboardNavigation_data(). + * This function sets the view's properties according to the data provided. * * 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() +void KItemListControllerTest::testKeyboardNavigationSingleSelectionNoSelection() { QFETCH(KFileItemListView::ItemLayout, layout); QFETCH(Qt::Orientation, scrollOrientation); @@ -635,7 +986,7 @@ void KItemListControllerTest::testKeyboardNavigation() QVERIFY2( m_selectionManager->currentItem() == current, qPrintable(QStringLiteral("currentItem() returns index %1 but %2 would be expected. Before this, key \"%3\" was pressed. This test case is defined " - "in row %4 of the testList from KItemListControllerTest::testKeyboardNavigation_data().") + "in row %4 of the testList from KItemListControllerTest::testKeyboardNavigationSingleSelectionNoSelection_data().") .arg(m_selectionManager->currentItem()) .arg(current) .arg(QKeySequence(key).toString()) @@ -647,30 +998,12 @@ void KItemListControllerTest::testKeyboardNavigation() case KItemListController::SingleSelection: QCOMPARE(m_selectionManager->selectedItems(), KItemSet() << current); break; - case KItemListController::MultiSelection: - QCOMPARE(m_selectionManager->selectedItems(), selection); - break; + default: + Q_UNREACHABLE(); } if (activated) { switch (selectionBehavior) { - case KItemListController::MultiSelection: - if (!selection.isEmpty()) { - // The selected items should be activated. - if (selection.count() == 1) { - QVERIFY(!spySingleItemActivated.isEmpty()); - QCOMPARE(qvariant_cast(spySingleItemActivated.takeFirst().at(0)), selection.first()); - QVERIFY(spyMultipleItemsActivated.isEmpty()); - } else { - QVERIFY(spySingleItemActivated.isEmpty()); - QVERIFY(!spyMultipleItemsActivated.isEmpty()); - QCOMPARE(qvariant_cast(spyMultipleItemsActivated.takeFirst().at(0)), selection); - } - break; - } - // No items are selected. Therefore, the current item should be activated. - // This is handled by falling through to the NoSelection/SingleSelection case. - Q_FALLTHROUGH(); case KItemListController::NoSelection: case KItemListController::SingleSelection: // In NoSelection and SingleSelection mode, the current item should be activated. @@ -678,6 +1011,8 @@ void KItemListControllerTest::testKeyboardNavigation() QCOMPARE(qvariant_cast(spySingleItemActivated.takeFirst().at(0)), current); QVERIFY(spyMultipleItemsActivated.isEmpty()); break; + default: + Q_UNREACHABLE(); } } }