QWidget: add overload to set tab order as a list of widgets
The "two widgets at a time" API to set the tab order is awkward and easily misused (as the documentation explicitly explains). Add an inline overload that takes an initializer_list, and call the existing function for each consecutive pair of widgets in the list. Add documentation with snippet, and a test. Change-Id: I8e6f14a242866e3ee7cfb8ecade4697d6bdfb4d4 Reviewed-by: Christian Ehrlicher <ch.ehrlicher@gmx.de> Reviewed-by: Richard Moe Gustavsen <richard.gustavsen@qt.io>
This commit is contained in:
parent
ce5fb1e709
commit
cf5d9e9eb5
@ -61,6 +61,11 @@ setTabOrder(c, d); // a to b to c to d
|
||||
//! [9]
|
||||
|
||||
|
||||
//! [9.list]
|
||||
setTabOrder({a, b, c, d}); // a to b to c to d
|
||||
//! [9.list]
|
||||
|
||||
|
||||
//! [10]
|
||||
// WRONG
|
||||
setTabOrder(c, d); // c to d
|
||||
|
@ -6918,6 +6918,30 @@ bool QWidget::isActiveWindow() const
|
||||
return false;
|
||||
}
|
||||
|
||||
/*!
|
||||
\fn void QWidget::setTabOrder(std::initializer_list<QWidget *> widgets)
|
||||
\overload
|
||||
\since 6.6
|
||||
|
||||
Sets the tab order for the widgets in the \a widgets list by calling
|
||||
\l{QWidget::setTabOrder(QWidget *, QWidget *)} for each consecutive
|
||||
pair of widgets.
|
||||
|
||||
Instead of setting up each pair manually like this:
|
||||
|
||||
\snippet code/src_gui_kernel_qwidget.cpp 9
|
||||
|
||||
you can call:
|
||||
|
||||
\snippet code/src_gui_kernel_qwidget.cpp 9.list
|
||||
|
||||
The call does not create a closed tab focus loop. If there are more widgets
|
||||
with \l{Qt::TabFocus} focus policy, tabbing on \c{d} will move focus to one
|
||||
of those widgets, not back to \c{a}.
|
||||
|
||||
\sa setFocusPolicy(), setFocusProxy(), {Keyboard Focus in Widgets}
|
||||
*/
|
||||
|
||||
/*!
|
||||
Puts the \a second widget after the \a first widget in the focus order.
|
||||
|
||||
|
@ -432,6 +432,7 @@ public:
|
||||
void setFocusPolicy(Qt::FocusPolicy policy);
|
||||
bool hasFocus() const;
|
||||
static void setTabOrder(QWidget *, QWidget *);
|
||||
static inline void setTabOrder(std::initializer_list<QWidget *> widgets);
|
||||
void setFocusProxy(QWidget *);
|
||||
QWidget *focusProxy() const;
|
||||
Qt::ContextMenuPolicy contextMenuPolicy() const;
|
||||
@ -916,6 +917,18 @@ inline bool QWidget::testAttribute(Qt::WidgetAttribute attribute) const
|
||||
return testAttribute_helper(attribute);
|
||||
}
|
||||
|
||||
inline void QWidget::setTabOrder(std::initializer_list<QWidget *> widgets)
|
||||
{
|
||||
QWidget *prev = nullptr;
|
||||
for (const auto &widget : widgets) {
|
||||
if (!prev) {
|
||||
prev = widget;
|
||||
} else {
|
||||
QWidget::setTabOrder(prev, widget);
|
||||
prev = widget;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#define QWIDGETSIZE_MAX ((1<<24)-1)
|
||||
|
||||
|
@ -173,6 +173,7 @@ private slots:
|
||||
void appFocusWidgetWhenLosingFocusProxy();
|
||||
void explicitTabOrderWithComplexWidget();
|
||||
void explicitTabOrderWithSpinBox_QTBUG81097();
|
||||
void tabOrderList();
|
||||
#if defined(Q_OS_WIN)
|
||||
void activation();
|
||||
#endif
|
||||
@ -1929,6 +1930,26 @@ public:
|
||||
QLineEdit *lineEdit3;
|
||||
};
|
||||
|
||||
static QList<QWidget *> getFocusChain(QWidget *start, bool bForward)
|
||||
{
|
||||
QList<QWidget *> ret;
|
||||
QWidget *cur = start;
|
||||
// detect infinite loop
|
||||
int count = 100;
|
||||
auto loopGuard = qScopeGuard([]{
|
||||
QFAIL("Inifinite loop detected in focus chain");
|
||||
});
|
||||
do {
|
||||
ret += cur;
|
||||
auto widgetPrivate = static_cast<QWidgetPrivate *>(qt_widget_private(cur));
|
||||
cur = bForward ? widgetPrivate->focus_next : widgetPrivate->focus_prev;
|
||||
if (!--count)
|
||||
return ret;
|
||||
} while (cur != start);
|
||||
loopGuard.dismiss();
|
||||
return ret;
|
||||
}
|
||||
|
||||
void tst_QWidget::defaultTabOrder()
|
||||
{
|
||||
if (QGuiApplication::platformName().startsWith(QLatin1String("wayland"), Qt::CaseInsensitive))
|
||||
@ -2048,6 +2069,17 @@ void tst_QWidget::reverseTabOrder()
|
||||
QVERIFY(firstEdit->hasFocus());
|
||||
}
|
||||
|
||||
void tst_QWidget::tabOrderList()
|
||||
{
|
||||
Composite c;
|
||||
QCOMPARE(getFocusChain(&c, true),
|
||||
QList<QWidget *>({&c, c.lineEdit1, c.lineEdit2, c.lineEdit3}));
|
||||
QWidget::setTabOrder({c.lineEdit3, c.lineEdit2, c.lineEdit1});
|
||||
// not starting with 3 like one would maybe expect, but still 3, 2, 1
|
||||
QCOMPARE(getFocusChain(&c, true),
|
||||
QList<QWidget *>({&c, c.lineEdit1, c.lineEdit3, c.lineEdit2}));
|
||||
}
|
||||
|
||||
void tst_QWidget::tabOrderWithProxy()
|
||||
{
|
||||
if (QGuiApplication::platformName().startsWith(QLatin1String("wayland"), Qt::CaseInsensitive))
|
||||
@ -2269,26 +2301,6 @@ void tst_QWidget::tabOrderWithCompoundWidgets()
|
||||
QVERIFY(lastEdit->hasFocus());
|
||||
}
|
||||
|
||||
static QList<QWidget *> getFocusChain(QWidget *start, bool bForward)
|
||||
{
|
||||
QList<QWidget *> ret;
|
||||
QWidget *cur = start;
|
||||
// detect infinite loop
|
||||
int count = 100;
|
||||
auto loopGuard = qScopeGuard([]{
|
||||
QFAIL("Inifinite loop detected in focus chain");
|
||||
});
|
||||
do {
|
||||
ret += cur;
|
||||
auto widgetPrivate = static_cast<QWidgetPrivate *>(qt_widget_private(cur));
|
||||
cur = bForward ? widgetPrivate->focus_next : widgetPrivate->focus_prev;
|
||||
if (!--count)
|
||||
return ret;
|
||||
} while (cur != start);
|
||||
loopGuard.dismiss();
|
||||
return ret;
|
||||
}
|
||||
|
||||
void tst_QWidget::tabOrderWithProxyOutOfOrder()
|
||||
{
|
||||
Container container;
|
||||
|
Loading…
x
Reference in New Issue
Block a user