summaryrefslogtreecommitdiffstats
path: root/src/widgets
diff options
context:
space:
mode:
authorChristian Ehrlicher <ch.ehrlicher@gmx.de>2019-06-10 13:44:42 +0200
committerChristian Ehrlicher <ch.ehrlicher@gmx.de>2019-06-10 13:44:42 +0200
commita7cbb8c639487edbabc08ea99498503b33c9f6d6 (patch)
tree5bad01705226bfbc421974feac4682f474ed260b /src/widgets
parenta489e11b97ca6c0f5893711a363c9896dd8377f8 (diff)
QWidget: fix setTabOrder for compound widgets
81e298a51d08c510457b4a26b37c0d4aac5eba65 fixed a case where the focus chain was screwed up when the order was already correct. This worked correctly in most cases but not when the next focus widget of the first one had Qt::NoFocus. The optimization check if lastFocusChildOfFirst is the same as second is thrown away since it now does not longer screw up the focus chain and the save would only be four pointer assignments. Fixes: QTBUG-75388 Task-number: QTBUG-10907 Task-number: QTBUG-68393 Task-number: QTBUG-69619 Change-Id: I581ed532156c34ea970123afd063194aab016304 Reviewed-by: Richard Moe Gustavsen <richard.gustavsen@qt.io>
Diffstat (limited to 'src/widgets')
-rw-r--r--src/widgets/kernel/qwidget.cpp60
1 files changed, 32 insertions, 28 deletions
diff --git a/src/widgets/kernel/qwidget.cpp b/src/widgets/kernel/qwidget.cpp
index 8b225df8be..6ef3a4f163 100644
--- a/src/widgets/kernel/qwidget.cpp
+++ b/src/widgets/kernel/qwidget.cpp
@@ -1,4 +1,4 @@
-/****************************************************************************
+/****************************************************************************
**
** Copyright (C) 2017 The Qt Company Ltd.
** Copyright (C) 2016 Intel Corporation.
@@ -7017,37 +7017,41 @@ void QWidget::setTabOrder(QWidget* first, QWidget *second)
lastFocusChild = focusNext;
}
};
+ auto setPrev = [](QWidget *w, QWidget *prev)
+ {
+ w->d_func()->focus_prev = prev;
+ };
+ auto setNext = [](QWidget *w, QWidget *next)
+ {
+ w->d_func()->focus_next = next;
+ };
- QWidget *lastFocusChildOfFirst, *lastFocusChildOfSecond;
- determineLastFocusChild(first, lastFocusChildOfFirst);
+ // remove the second widget from the chain
+ QWidget *lastFocusChildOfSecond;
determineLastFocusChild(second, lastFocusChildOfSecond);
-
- // If the tab order is already correct, exit early
- if (lastFocusChildOfFirst == second ||
- lastFocusChildOfFirst->d_func()->focus_next == second) {
- return;
+ {
+ QWidget *oldPrev = second->d_func()->focus_prev;
+ QWidget *prevWithFocus = oldPrev;
+ while (prevWithFocus->focusPolicy() == Qt::NoFocus)
+ prevWithFocus = prevWithFocus->d_func()->focus_prev;
+ // only widgets between first and second -> all is fine
+ if (prevWithFocus == first)
+ return;
+ QWidget *oldNext = lastFocusChildOfSecond->d_func()->focus_next;
+ setPrev(oldNext, oldPrev);
+ setNext(oldPrev, oldNext);
}
- // Note that we need to handle two different sections in the tab chain; The section
- // that 'first' belongs to (firstSection), where we are about to insert 'second', and
- // the section that 'second' used be a part of (secondSection). When we pull 'second'
- // out of the second section and insert it into the first, we also need to ensure
- // that we leave the second section in a connected state.
- QWidget *firstChainOldSecond = lastFocusChildOfFirst->d_func()->focus_next;
- QWidget *secondChainNewFirst = second->d_func()->focus_prev;
- QWidget *secondChainNewSecond = lastFocusChildOfSecond->d_func()->focus_next;
-
- // Insert 'second' after 'first'
- lastFocusChildOfFirst->d_func()->focus_next = second;
- second->d_func()->focus_prev = lastFocusChildOfFirst;
-
- // The widget that used to be 'second' in the first section, should now become 'third'
- lastFocusChildOfSecond->d_func()->focus_next = firstChainOldSecond;
- firstChainOldSecond->d_func()->focus_prev = lastFocusChildOfSecond;
-
- // Repair the second section after we pulled 'second' out of it
- secondChainNewFirst->d_func()->focus_next = secondChainNewSecond;
- secondChainNewSecond->d_func()->focus_prev = secondChainNewFirst;
+ // insert the second widget into the chain
+ QWidget *lastFocusChildOfFirst;
+ determineLastFocusChild(first, lastFocusChildOfFirst);
+ {
+ QWidget *oldNext = lastFocusChildOfFirst->d_func()->focus_next;
+ setPrev(second, lastFocusChildOfFirst);
+ setNext(lastFocusChildOfFirst, second);
+ setPrev(oldNext, lastFocusChildOfSecond);
+ setNext(lastFocusChildOfSecond, oldNext);
+ }
}
/*!\internal