summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorVolker Hilsheimer <volker.hilsheimer@qt.io>2023-03-08 20:05:01 +0100
committerVolker Hilsheimer <volker.hilsheimer@qt.io>2023-04-11 12:58:58 +0200
commitcf5d9e9eb5c4ad77f68aa2787bfb81550ded9c23 (patch)
tree64435f40b10f072c49789612a2a70e1a7065a0a7
parentce5fb1e709a7fb5594271f2aeb376fd64c5b07d8 (diff)
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>
-rw-r--r--src/widgets/doc/snippets/code/src_gui_kernel_qwidget.cpp5
-rw-r--r--src/widgets/kernel/qwidget.cpp24
-rw-r--r--src/widgets/kernel/qwidget.h13
-rw-r--r--tests/auto/widgets/kernel/qwidget/tst_qwidget.cpp52
4 files changed, 74 insertions, 20 deletions
diff --git a/src/widgets/doc/snippets/code/src_gui_kernel_qwidget.cpp b/src/widgets/doc/snippets/code/src_gui_kernel_qwidget.cpp
index 8f0c296873..603ce14f80 100644
--- a/src/widgets/doc/snippets/code/src_gui_kernel_qwidget.cpp
+++ b/src/widgets/doc/snippets/code/src_gui_kernel_qwidget.cpp
@@ -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
diff --git a/src/widgets/kernel/qwidget.cpp b/src/widgets/kernel/qwidget.cpp
index cb432c84bc..cde0542eee 100644
--- a/src/widgets/kernel/qwidget.cpp
+++ b/src/widgets/kernel/qwidget.cpp
@@ -6919,6 +6919,30 @@ bool QWidget::isActiveWindow() const
}
/*!
+ \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.
It effectively removes the \a second widget from its focus chain and
diff --git a/src/widgets/kernel/qwidget.h b/src/widgets/kernel/qwidget.h
index a0a1ca5300..a17803cabc 100644
--- a/src/widgets/kernel/qwidget.h
+++ b/src/widgets/kernel/qwidget.h
@@ -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)
diff --git a/tests/auto/widgets/kernel/qwidget/tst_qwidget.cpp b/tests/auto/widgets/kernel/qwidget/tst_qwidget.cpp
index 69b385f95b..8e497bbb30 100644
--- a/tests/auto/widgets/kernel/qwidget/tst_qwidget.cpp
+++ b/tests/auto/widgets/kernel/qwidget/tst_qwidget.cpp
@@ -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;