summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorChristian Ehrlicher <ch.ehrlicher@gmx.de>2018-12-08 19:58:00 +0100
committerChristian Ehrlicher <ch.ehrlicher@gmx.de>2018-12-18 05:33:52 +0000
commit7863be311570fa219066df5fe8720d5b92ddb680 (patch)
tree3cbcaca76768c6525d618a6e85848678a2dd74b7 /src
parent53ae00d03c4065ca2235dc41636be0274d074c57 (diff)
QTableView: Fix keyboard navigation with disabled rows
The keyboard navigation with MovePageUp/Down and MoveEnd did not honor disabled cells in all cases which lead to inconsistencies in the navigation (esp. since MoveHome does honor them correctly). Therefore make sure that all four move operations work consistent by refactoring the code to use common functions. Fixes: QTBUG-72400 Change-Id: I63fa3b626510d21c66f4f9b2b1bfb3261728ecaf Reviewed-by: Friedemann Kleint <Friedemann.Kleint@qt.io> Reviewed-by: Luca Beldi <v.ronin@yahoo.it> Reviewed-by: Samuel Gaist <samuel.gaist@idiap.ch> Reviewed-by: Richard Moe Gustavsen <richard.gustavsen@qt.io>
Diffstat (limited to 'src')
-rw-r--r--src/widgets/itemviews/qtableview.cpp103
-rw-r--r--src/widgets/itemviews/qtableview_p.h20
2 files changed, 91 insertions, 32 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;