summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/widgets/itemviews/qtableview.cpp103
-rw-r--r--src/widgets/itemviews/qtableview_p.h20
-rw-r--r--tests/auto/widgets/itemviews/qtableview/tst_qtableview.cpp40
3 files changed, 125 insertions, 38 deletions
diff --git a/src/widgets/itemviews/qtableview.cpp b/src/widgets/itemviews/qtableview.cpp
index 9725a768de..9c509583e6 100644
--- a/src/widgets/itemviews/qtableview.cpp
+++ b/src/widgets/itemviews/qtableview.cpp
@@ -766,6 +766,66 @@ bool QTableViewPrivate::spanContainsSection(const QHeaderView *header, int logic
/*!
\internal
+ Searches for the next cell which is available for e.g. keyboard navigation
+ The search is done by row
+*/
+int QTableViewPrivate::nextActiveVisualRow(int rowToStart, int column, int limit,
+ SearchDirection searchDirection) const
+{
+ const int lc = logicalColumn(column);
+ int visualRow = rowToStart;
+ const auto isCellActive = [this](int vr, int lc)
+ {
+ const int lr = logicalRow(vr);
+ return !isRowHidden(lr) && isCellEnabled(lr, lc);
+ };
+ switch (searchDirection) {
+ case SearchDirection::Increasing:
+ if (visualRow < limit) {
+ while (!isCellActive(visualRow, lc)) {
+ if (++visualRow == limit)
+ return rowToStart;
+ }
+ }
+ break;
+ case SearchDirection::Decreasing:
+ while (visualRow > limit && !isCellActive(visualRow, lc))
+ --visualRow;
+ break;
+ }
+ return visualRow;
+}
+
+/*!
+ \internal
+ Searches for the next cell which is available for e.g. keyboard navigation
+ The search is done by column
+*/
+int QTableViewPrivate::nextActiveVisualColumn(int row, int columnToStart, int limit,
+ SearchDirection searchDirection) const
+{
+ const int lr = logicalRow(row);
+ int visualColumn = columnToStart;
+ const auto isCellActive = [this](int lr, int vc)
+ {
+ const int lc = logicalColumn(vc);
+ return !isColumnHidden(lc) && isCellEnabled(lr, lc);
+ };
+ switch (searchDirection) {
+ case SearchDirection::Increasing:
+ while (visualColumn < limit && !isCellActive(lr, visualColumn))
+ ++visualColumn;
+ break;
+ case SearchDirection::Decreasing:
+ while (visualColumn > limit && !isCellActive(lr, visualColumn))
+ --visualColumn;
+ break;
+ }
+ return visualColumn;
+}
+
+/*!
+ \internal
Returns the visual rect for the given \a span.
*/
QRect QTableViewPrivate::visualSpanRect(const QSpanCollection::Span &span) const
@@ -1800,35 +1860,34 @@ QModelIndex QTableView::moveCursor(CursorAction cursorAction, Qt::KeyboardModifi
break;
}
case MoveHome:
- visualColumn = 0;
- while (visualColumn < right && d->isVisualColumnHiddenOrDisabled(visualRow, visualColumn))
- ++visualColumn;
- if (modifiers & Qt::ControlModifier) {
- visualRow = 0;
- while (visualRow < bottom && d->isVisualRowHiddenOrDisabled(visualRow, visualColumn))
- ++visualRow;
- }
+ visualColumn = d->nextActiveVisualColumn(visualRow, 0, right,
+ QTableViewPrivate::SearchDirection::Increasing);
+ if (modifiers & Qt::ControlModifier)
+ visualRow = d->nextActiveVisualRow(0, visualColumn, bottom,
+ QTableViewPrivate::SearchDirection::Increasing);
break;
case MoveEnd:
- visualColumn = right;
+ visualColumn = d->nextActiveVisualColumn(visualRow, right, -1,
+ QTableViewPrivate::SearchDirection::Decreasing);
if (modifiers & Qt::ControlModifier)
- visualRow = bottom;
+ visualRow = d->nextActiveVisualRow(bottom, current.column(), -1,
+ QTableViewPrivate::SearchDirection::Decreasing);
break;
case MovePageUp: {
- int newRow = rowAt(visualRect(current).bottom() - d->viewport->height());
- if (newRow == -1) {
- int visualRow = 0;
- while (visualRow < bottom && isRowHidden(d->logicalRow(visualRow)))
- ++visualRow;
- newRow = d->logicalRow(visualRow);
- }
- return d->model->index(newRow, current.column(), d->root);
+ int newLogicalRow = rowAt(visualRect(current).bottom() - d->viewport->height());
+ int visualRow = (newLogicalRow == -1 ? 0 : d->visualRow(newLogicalRow));
+ visualRow = d->nextActiveVisualRow(visualRow, current.column(), bottom,
+ QTableViewPrivate::SearchDirection::Increasing);
+ newLogicalRow = d->logicalRow(visualRow);
+ return d->model->index(newLogicalRow, current.column(), d->root);
}
case MovePageDown: {
- int newRow = rowAt(visualRect(current).top() + d->viewport->height());
- if (newRow == -1)
- newRow = d->logicalRow(bottom);
- return d->model->index(newRow, current.column(), d->root);
+ int newLogicalRow = rowAt(visualRect(current).top() + d->viewport->height());
+ int visualRow = (newLogicalRow == -1 ? bottom : d->visualRow(newLogicalRow));
+ visualRow = d->nextActiveVisualRow(visualRow, current.column(), -1,
+ QTableViewPrivate::SearchDirection::Decreasing);
+ newLogicalRow = d->logicalRow(visualRow);
+ return d->model->index(newLogicalRow, current.column(), d->root);
}}
d->visualCursor = QPoint(visualColumn, visualRow);
diff --git a/src/widgets/itemviews/qtableview_p.h b/src/widgets/itemviews/qtableview_p.h
index 805787597c..a50e6b6410 100644
--- a/src/widgets/itemviews/qtableview_p.h
+++ b/src/widgets/itemviews/qtableview_p.h
@@ -234,16 +234,16 @@ public:
inline bool isCellEnabled(int row, int column) const {
return isIndexEnabled(model->index(row, column, root));
}
- inline bool isVisualRowHiddenOrDisabled(int row, int column) const {
- int r = logicalRow(row);
- int c = logicalColumn(column);
- return isRowHidden(r) || !isCellEnabled(r, c);
- }
- inline bool isVisualColumnHiddenOrDisabled(int row, int column) const {
- int r = logicalRow(row);
- int c = logicalColumn(column);
- return isColumnHidden(c) || !isCellEnabled(r, c);
- }
+
+ enum class SearchDirection
+ {
+ Increasing,
+ Decreasing
+ };
+ int nextActiveVisualRow(int rowToStart, int column, int limit,
+ SearchDirection searchDirection) const;
+ int nextActiveVisualColumn(int row, int columnToStart, int limit,
+ SearchDirection searchDirection) const;
QRect visualSpanRect(const QSpanCollection::Span &span) const;
diff --git a/tests/auto/widgets/itemviews/qtableview/tst_qtableview.cpp b/tests/auto/widgets/itemviews/qtableview/tst_qtableview.cpp
index ab746dfee8..1b95b5a3ca 100644
--- a/tests/auto/widgets/itemviews/qtableview/tst_qtableview.cpp
+++ b/tests/auto/widgets/itemviews/qtableview/tst_qtableview.cpp
@@ -1264,19 +1264,47 @@ void tst_QTableView::moveCursorStrikesBack_data()
for (int i = 0; i < 7; ++i)
fullList << i;
- QTest::newRow("All disabled, wrap forward. Timeout => FAIL") << -1 << -1
+ QTest::newRow("All disabled, wrap forward. => invalid index") << -1 << -1
<< fullList
<< fullList
<< QRect()
<< 1 << 0 << (IntList() << int(QtTestTableView::MoveNext))
- << 1 << 0;
+ << -1 << -1;
- QTest::newRow("All disabled, wrap backwards. Timeout => FAIL") << -1 << -1
+ QTest::newRow("All disabled, wrap backwards. => invalid index") << -1 << -1
<< fullList
<< fullList
<< QRect()
<< 1 << 0 << (IntList() << int(QtTestTableView::MovePrevious))
+ << -1 << -1;
+
+ QTest::newRow("Last column disabled, MoveEnd. QTBUG-72400") << -1 << -1
+ << IntList()
+ << (IntList() << 6)
+ << QRect()
+ << 0 << 0 << (IntList() << int(QtTestTableView::MoveEnd))
+ << 0 << 5;
+
+ QTest::newRow("First column disabled, MoveHome. QTBUG-72400") << -1 << -1
+ << IntList()
+ << (IntList() << 0)
+ << QRect()
+ << 0 << 6 << (IntList() << int(QtTestTableView::MoveHome))
+ << 0 << 1;
+
+ QTest::newRow("First row disabled, MovePageUp. QTBUG-72400") << -1 << -1
+ << (IntList() << 0)
+ << IntList()
+ << QRect()
+ << 2 << 0 << (IntList() << int(QtTestTableView::MovePageUp))
<< 1 << 0;
+
+ QTest::newRow("Last row disabled, MovePageDown. QTBUG-72400") << -1 << -1
+ << (IntList() << 6)
+ << IntList()
+ << QRect()
+ << 4 << 0 << (IntList() << int(QtTestTableView::MovePageDown))
+ << 5 << 0;
}
void tst_QTableView::moveCursorStrikesBack()
@@ -1302,6 +1330,9 @@ void tst_QTableView::moveCursorStrikesBack()
if (span.height() && span.width())
view.setSpan(span.top(), span.left(), span.height(), span.width());
view.show();
+ QVERIFY(QTest::qWaitForWindowActive(&view));
+ // resize to make sure there are scrollbars
+ view.resize(view.columnWidth(0) * 7, view.rowHeight(0) * 7);
QModelIndex index = model.index(startRow, startColumn);
view.setCurrentIndex(index);
@@ -1320,9 +1351,6 @@ void tst_QTableView::moveCursorStrikesBack()
newColumn = newIndex.column();
}
- // expected fails, task 119433
- if(newRow == -1)
- return;
QCOMPARE(newRow, expectedRow);
QCOMPARE(newColumn, expectedColumn);
}