1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76
|
Description: QWidget: fix setTabOrder for compound widgets
Origin: upstream, commits:
https://code.qt.io/cgit/qt/qtbase.git/commit/?id=81e298a51d08c510
https://code.qt.io/cgit/qt/qtbase.git/commit/?id=a7cbb8c639487edb
Last-Update: 2022-02-13
--- a/src/widgets/kernel/qwidget.cpp
+++ b/src/widgets/kernel/qwidget.cpp
@@ -6975,35 +6975,41 @@ void QWidget::setTabOrder(QWidget* first
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);
+ {
+ 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);
+ }
- // If the tab order is already correct, exit early
- if (lastFocusChildOfFirst->d_func()->focus_next == second)
- return;
-
- // 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
|