diff options
| author | Felix Ernst <[email protected]> | 2024-12-29 11:27:18 +0000 |
|---|---|---|
| committer | Felix Ernst <[email protected]> | 2024-12-29 11:27:18 +0000 |
| commit | 3696213ccbbe27e9ef3fc85eb97dd32fd669066f (patch) | |
| tree | 7b6db1a823da09b3bedab8aaf2ea0e82393ceab5 /src/tests/kitemlistcontrollertest.cpp | |
| parent | 4f71b3c539eb54c3db184d85ebc9bfce5ecfb989 (diff) | |
Have special keyboard controls in selection mode
Prior to this commit keyboard controls and behaviour of Dolphin's main
view were identical no matter if selection mode was enabled or not.
While selection mode makes it impossible to accidentally clear the
selection by singular mouse clicks, any press of an arrow key on the
keyboard would still clear the full selection which goes against
selection mode's objective.
Furthermore, keyboard-only users had no reason to ever enable selection
mode because it made no difference to them.
This commit changes this by offering a changed control scheme for key
presses while in selection mode. Arrow key presses without modifier now
only move focus between items but do no longer clear or change the
selection. Similarly, Page Up/Down, Home, and End key presses only move
keyboard focus. Enter, Return, and Space key presses now only toggle
the selection for the current item.
The above controls are however mostly unchanged when combining them
with Modifier keys like Shift or Control.
The type-ahead feature is also changed in selection mode to only move
keyboard focus without changing the selection.
This way keyboard users are less likely to clear their selection by
mistake. Regression tests are added for these selection mode controls.
The code changes to change this keyboard behaviour are quite minimal.
Most of the added code is for making selection mode accessible. That's
because we need to make sure the changed control scheme is properly
announced and communicated or a blind user will be left utterly
confused why the normal keyboard controls "stopped working".
Enabling or disabling selection mode is announced to accessibility
software. Furthermore whenever focus goes to the main view, the
selection mode state is also mentioned when active.
BUG: 458091
Diffstat (limited to 'src/tests/kitemlistcontrollertest.cpp')
| -rw-r--r-- | src/tests/kitemlistcontrollertest.cpp | 95 |
1 files changed, 92 insertions, 3 deletions
diff --git a/src/tests/kitemlistcontrollertest.cpp b/src/tests/kitemlistcontrollertest.cpp index de40331e6..a882accaa 100644 --- a/src/tests/kitemlistcontrollertest.cpp +++ b/src/tests/kitemlistcontrollertest.cpp @@ -174,6 +174,7 @@ void KItemListControllerTest::init() void KItemListControllerTest::cleanup() { + m_controller->setSelectionModeEnabled(false); } /** @@ -228,9 +229,11 @@ void KItemListControllerTest::testKeyboardNavigation_data() QTest::addColumn<KFileItemListView::ItemLayout>("layout"); QTest::addColumn<Qt::Orientation>("scrollOrientation"); QTest::addColumn<int>("columnCount"); - QTest::addColumn<KItemListController::SelectionBehavior>("selectionBehavior"); + QTest::addColumn<KItemListController::SelectionBehavior>("selectionBehavior"); // Defines how many items can be selected at the same time. QTest::addColumn<bool>("groupingEnabled"); QTest::addColumn<Qt::LayoutDirection>("layoutDirection"); + QTest::addColumn<bool>( + "selectionModeEnabled"); // Don't confuse this with "selectionBehaviour". This is about changing controls for users to help multi-selecting. QTest::addColumn<QList<QPair<KeyPress, ViewState>>>("testList"); QList<KFileItemListView::ItemLayout> layoutList; @@ -265,6 +268,9 @@ void KItemListControllerTest::testKeyboardNavigation_data() 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 @@ -484,13 +490,92 @@ void KItemListControllerTest::testKeyboardNavigation_data() const QByteArray testNameAscii = testName.toLatin1(); - QTest::newRow(testNameAscii.data()) - << layout << scrollOrientation << columnCount << selectionBehavior << groupingEnabled << layoutDirection << testList; + QTest::newRow(testNameAscii.data()) << layout << scrollOrientation << columnCount << selectionBehavior << 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 KItemListController::SelectionBehavior &selectionBehavior = KItemListController::MultiSelection; + const bool groupingEnabled = false; + + QList<QPair<KeyPress, ViewState>> 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; } /** @@ -508,6 +593,7 @@ void KItemListControllerTest::testKeyboardNavigation() QFETCH(KItemListController::SelectionBehavior, selectionBehavior); QFETCH(bool, groupingEnabled); QFETCH(Qt::LayoutDirection, layoutDirection); + QFETCH(bool, selectionModeEnabled); QFETCH(QList<keyPressViewStatePair>, testList); QApplication::setLayoutDirection(layoutDirection); @@ -525,6 +611,9 @@ void KItemListControllerTest::testKeyboardNavigation() 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); |
