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]
|
||||||
|
|
||||||
|
|
||||||
|
//! [9.list]
|
||||||
|
setTabOrder({a, b, c, d}); // a to b to c to d
|
||||||
|
//! [9.list]
|
||||||
|
|
||||||
|
|
||||||
//! [10]
|
//! [10]
|
||||||
// WRONG
|
// WRONG
|
||||||
setTabOrder(c, d); // c to d
|
setTabOrder(c, d); // c to d
|
||||||
|
@ -6918,6 +6918,30 @@ bool QWidget::isActiveWindow() const
|
|||||||
return false;
|
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.
|
Puts the \a second widget after the \a first widget in the focus order.
|
||||||
|
|
||||||
|
@ -432,6 +432,7 @@ public:
|
|||||||
void setFocusPolicy(Qt::FocusPolicy policy);
|
void setFocusPolicy(Qt::FocusPolicy policy);
|
||||||
bool hasFocus() const;
|
bool hasFocus() const;
|
||||||
static void setTabOrder(QWidget *, QWidget *);
|
static void setTabOrder(QWidget *, QWidget *);
|
||||||
|
static inline void setTabOrder(std::initializer_list<QWidget *> widgets);
|
||||||
void setFocusProxy(QWidget *);
|
void setFocusProxy(QWidget *);
|
||||||
QWidget *focusProxy() const;
|
QWidget *focusProxy() const;
|
||||||
Qt::ContextMenuPolicy contextMenuPolicy() const;
|
Qt::ContextMenuPolicy contextMenuPolicy() const;
|
||||||
@ -916,6 +917,18 @@ inline bool QWidget::testAttribute(Qt::WidgetAttribute attribute) const
|
|||||||
return testAttribute_helper(attribute);
|
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)
|
#define QWIDGETSIZE_MAX ((1<<24)-1)
|
||||||
|
|
||||||
|
@ -173,6 +173,7 @@ private slots:
|
|||||||
void appFocusWidgetWhenLosingFocusProxy();
|
void appFocusWidgetWhenLosingFocusProxy();
|
||||||
void explicitTabOrderWithComplexWidget();
|
void explicitTabOrderWithComplexWidget();
|
||||||
void explicitTabOrderWithSpinBox_QTBUG81097();
|
void explicitTabOrderWithSpinBox_QTBUG81097();
|
||||||
|
void tabOrderList();
|
||||||
#if defined(Q_OS_WIN)
|
#if defined(Q_OS_WIN)
|
||||||
void activation();
|
void activation();
|
||||||
#endif
|
#endif
|
||||||
@ -1929,6 +1930,26 @@ public:
|
|||||||
QLineEdit *lineEdit3;
|
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()
|
void tst_QWidget::defaultTabOrder()
|
||||||
{
|
{
|
||||||
if (QGuiApplication::platformName().startsWith(QLatin1String("wayland"), Qt::CaseInsensitive))
|
if (QGuiApplication::platformName().startsWith(QLatin1String("wayland"), Qt::CaseInsensitive))
|
||||||
@ -2048,6 +2069,17 @@ void tst_QWidget::reverseTabOrder()
|
|||||||
QVERIFY(firstEdit->hasFocus());
|
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()
|
void tst_QWidget::tabOrderWithProxy()
|
||||||
{
|
{
|
||||||
if (QGuiApplication::platformName().startsWith(QLatin1String("wayland"), Qt::CaseInsensitive))
|
if (QGuiApplication::platformName().startsWith(QLatin1String("wayland"), Qt::CaseInsensitive))
|
||||||
@ -2269,26 +2301,6 @@ void tst_QWidget::tabOrderWithCompoundWidgets()
|
|||||||
QVERIFY(lastEdit->hasFocus());
|
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()
|
void tst_QWidget::tabOrderWithProxyOutOfOrder()
|
||||||
{
|
{
|
||||||
Container container;
|
Container container;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user