From e608bc019232f6956c4520be1a6103a1845c6991 Mon Sep 17 00:00:00 2001 From: Rym Bouabid Date: Fri, 6 Oct 2023 18:34:57 +0200 Subject: [PATCH] QObject: port findChild/ren() to QAnyStringView Change the object's name type in QObject::findChild/ren() to QAnyStringView, because they are only used for comparison against objectName property. qt_qFindChild{,ren}_helper() functions taking an objectname as QString have to stay in the ABI as they were exported in inline methods before Qt 6.7. Unlike QString, constructing a null QAnyStringView doesn't involve any code-size overhead. So, get rid of the split in qt_qFindChildren_helper that was introduced for QString. Remove unneeded qt_qFindChildren_with_name helper function and qt_qFindChildren_helper overload without a name. findChildren(options) method used to call qt_qFindChildren_helper overload. Instead, call findChildren overload with name argument and pass QAnyStringView{} as the object name. [ChangeLog][QtCore][QObject] Ported QObject::findChild/ren() and their helper functions to QAnyStringView. Task-number: QTBUG-103986 Change-Id: I68bda0e581f984ae48b7581ad86cc1b95008c1b0 Reviewed-by: Ivan Solovev --- src/corelib/compat/removed_api.cpp | 14 +++++ src/corelib/kernel/qobject.cpp | 52 +++++++------------ src/corelib/kernel/qobject.h | 19 ++++--- .../corelib/kernel/qobject/tst_qobject.cpp | 34 ++++++++++++ 4 files changed, 79 insertions(+), 40 deletions(-) diff --git a/src/corelib/compat/removed_api.cpp b/src/corelib/compat/removed_api.cpp index 964597a2da..9fe3827d86 100644 --- a/src/corelib/compat/removed_api.cpp +++ b/src/corelib/compat/removed_api.cpp @@ -773,6 +773,20 @@ QString QLocale::bcp47Name() const return bcp47Name(TagSeparator::Dash); } +#include "qobject.h" + +void qt_qFindChildren_helper(const QObject *parent, const QString &name, const QMetaObject &mo, + QList *list, Qt::FindChildOptions options) +{ + qt_qFindChildren_helper(parent, QAnyStringView{name}, mo, list, options); +} + +QObject *qt_qFindChild_helper(const QObject *parent, const QString &name, const QMetaObject &mo, + Qt::FindChildOptions options) +{ + return qt_qFindChild_helper(parent, QAnyStringView{name}, mo, options); +} + #include "qobjectdefs.h" int QMetaObject::indexOfEnumerator(const char *name) const diff --git a/src/corelib/kernel/qobject.cpp b/src/corelib/kernel/qobject.cpp index 88e928044b..1319402839 100644 --- a/src/corelib/kernel/qobject.cpp +++ b/src/corelib/kernel/qobject.cpp @@ -1982,7 +1982,7 @@ void QObject::killTimer(int id) /*! - \fn template T *QObject::findChild(const QString &name, Qt::FindChildOptions options) const + \fn template T *QObject::findChild(QAnyStringView name, Qt::FindChildOptions options) const Returns the child of this object that can be cast into type T and that is called \a name, or \nullptr if there is no such object. @@ -2016,11 +2016,14 @@ void QObject::killTimer(int id) \snippet code/src_corelib_kernel_qobject.cpp 42 + \note In Qt versions prior to 6.7, this function took \a name as + \c{QString}, not \c{QAnyStringView}. + \sa findChildren() */ /*! - \fn template QList QObject::findChildren(const QString &name, Qt::FindChildOptions options) const + \fn template QList QObject::findChildren(QAnyStringView name, Qt::FindChildOptions options) const Returns all children of this object with the given \a name that can be cast to type T, or an empty list if there are no such objects. @@ -2042,6 +2045,9 @@ void QObject::killTimer(int id) \snippet code/src_corelib_kernel_qobject.cpp 43 + \note In Qt versions prior to 6.7, this function took \a name as + \c{QString}, not \c{QAnyStringView}. + \sa findChild() */ @@ -2103,46 +2109,26 @@ void QObject::killTimer(int id) \sa QObject::findChildren() */ -static void qt_qFindChildren_with_name(const QObject *parent, const QString &name, - const QMetaObject &mo, QList *list, - Qt::FindChildOptions options) +static bool matches_objectName_non_null(QObject *obj, QAnyStringView name) { - Q_ASSERT(parent); - Q_ASSERT(list); - Q_ASSERT(!name.isNull()); - for (QObject *obj : parent->children()) { - if (mo.cast(obj) && obj->objectName() == name) - list->append(obj); - if (options & Qt::FindChildrenRecursively) - qt_qFindChildren_with_name(obj, name, mo, list, options); - } + if (auto ext = QObjectPrivate::get(obj)->extraData) + return ext ->objectName.valueBypassingBindings() == name; + return name.isEmpty(); } /*! \internal */ -void qt_qFindChildren_helper(const QObject *parent, const QString &name, +void qt_qFindChildren_helper(const QObject *parent, QAnyStringView name, const QMetaObject &mo, QList *list, Qt::FindChildOptions options) -{ - if (name.isNull()) - return qt_qFindChildren_helper(parent, mo, list, options); - else - return qt_qFindChildren_with_name(parent, name, mo, list, options); -} - -/*! - \internal -*/ -void qt_qFindChildren_helper(const QObject *parent, const QMetaObject &mo, - QList *list, Qt::FindChildOptions options) { Q_ASSERT(parent); Q_ASSERT(list); for (QObject *obj : parent->children()) { - if (mo.cast(obj)) + if (mo.cast(obj) && (name.isNull() || matches_objectName_non_null(obj, name))) list->append(obj); if (options & Qt::FindChildrenRecursively) - qt_qFindChildren_helper(obj, mo, list, options); + qt_qFindChildren_helper(obj, name, mo, list, options); } } @@ -2169,13 +2155,13 @@ void qt_qFindChildren_helper(const QObject *parent, const QRegularExpression &re /*! \internal - */ -QObject *qt_qFindChild_helper(const QObject *parent, const QString &name, const QMetaObject &mo, Qt::FindChildOptions options) +*/ +QObject *qt_qFindChild_helper(const QObject *parent, QAnyStringView name, const QMetaObject &mo, Qt::FindChildOptions options) { Q_ASSERT(parent); for (QObject *obj : parent->children()) { - if (mo.cast(obj) && (name.isNull() || obj->objectName() == name)) - return obj; + if (mo.cast(obj) && (name.isNull() || matches_objectName_non_null(obj, name))) + return obj; } if (options & Qt::FindChildrenRecursively) { for (QObject *child : parent->children()) { diff --git a/src/corelib/kernel/qobject.h b/src/corelib/kernel/qobject.h index 824a29a5a4..3660a5b3c4 100644 --- a/src/corelib/kernel/qobject.h +++ b/src/corelib/kernel/qobject.h @@ -43,13 +43,22 @@ struct QDynamicMetaObjectData; typedef QList QObjectList; +#if QT_CORE_REMOVED_SINCE(6, 7) Q_CORE_EXPORT void qt_qFindChildren_helper(const QObject *parent, const QString &name, const QMetaObject &mo, QList *list, Qt::FindChildOptions options); +#endif +Q_CORE_EXPORT void qt_qFindChildren_helper(const QObject *parent, QAnyStringView name, + const QMetaObject &mo, QList *list, + Qt::FindChildOptions options); Q_CORE_EXPORT void qt_qFindChildren_helper(const QObject *parent, const QMetaObject &mo, QList *list, Qt::FindChildOptions options); Q_CORE_EXPORT void qt_qFindChildren_helper(const QObject *parent, const QRegularExpression &re, const QMetaObject &mo, QList *list, Qt::FindChildOptions options); +#if QT_CORE_REMOVED_SINCE(6, 7) Q_CORE_EXPORT QObject *qt_qFindChild_helper(const QObject *parent, const QString &name, const QMetaObject &mo, Qt::FindChildOptions options); +#endif +Q_CORE_EXPORT QObject *qt_qFindChild_helper(const QObject *parent, QAnyStringView name, + const QMetaObject &mo, Qt::FindChildOptions options); class Q_CORE_EXPORT QObjectData { @@ -131,14 +140,14 @@ public: void killTimer(int id); template - inline T findChild(const QString &aName = QString(), Qt::FindChildOptions options = Qt::FindChildrenRecursively) const + T findChild(QAnyStringView aName = {}, Qt::FindChildOptions options = Qt::FindChildrenRecursively) const { typedef typename std::remove_cv::type>::type ObjType; return static_cast(qt_qFindChild_helper(this, aName, ObjType::staticMetaObject, options)); } template - inline QList findChildren(const QString &aName, Qt::FindChildOptions options = Qt::FindChildrenRecursively) const + QList findChildren(QAnyStringView aName, Qt::FindChildOptions options = Qt::FindChildrenRecursively) const { typedef typename std::remove_cv::type>::type ObjType; QList list; @@ -150,11 +159,7 @@ public: template QList findChildren(Qt::FindChildOptions options = Qt::FindChildrenRecursively) const { - typedef typename std::remove_cv::type>::type ObjType; - QList list; - qt_qFindChildren_helper(this, ObjType::staticMetaObject, - reinterpret_cast *>(&list), options); - return list; + return findChildren(QAnyStringView{}, options); } #if QT_CONFIG(regularexpression) diff --git a/tests/auto/corelib/kernel/qobject/tst_qobject.cpp b/tests/auto/corelib/kernel/qobject/tst_qobject.cpp index deb8c542dd..33ecb869b3 100644 --- a/tests/auto/corelib/kernel/qobject/tst_qobject.cpp +++ b/tests/auto/corelib/kernel/qobject/tst_qobject.cpp @@ -39,6 +39,8 @@ #include +using namespace Qt::StringLiterals; + class tst_QObject : public QObject { Q_OBJECT @@ -520,6 +522,10 @@ void tst_QObject::findChildren() QTimer t1(&o); QTimer t121(&o12); QTimer emptyname(&o); + QObject oo; + QObject o21(&oo); + QObject o22(&oo); + QObject o23(&oo); Q_SET_OBJECT_NAME(o); Q_SET_OBJECT_NAME(o1); @@ -530,6 +536,13 @@ void tst_QObject::findChildren() Q_SET_OBJECT_NAME(t1); Q_SET_OBJECT_NAME(t121); emptyname.setObjectName(""); + Q_SET_OBJECT_NAME(oo); + const QUtf8StringView utf8_name = u8"utf8 ⁎ obj"; + o21.setObjectName(utf8_name); + const QStringView utf16_name = u"utf16 ⁎ obj"; + o22.setObjectName(utf16_name); + constexpr QLatin1StringView L1_name("L1 ⁎ obj"); + o23.setObjectName(L1_name); QObject *op = nullptr; @@ -560,6 +573,27 @@ void tst_QObject::findChildren() op = o.findChild("o1"); QCOMPARE(op, &o1); + op = oo.findChild(utf8_name); + QCOMPARE(op, &o21); + op = oo.findChild(utf8_name.chopped(1)); + QCOMPARE(op, nullptr); + const QUtf8StringView utf8_name_with_trailing_data = u8"utf8 ⁎ obj_data"; + op = oo.findChild(utf8_name_with_trailing_data.chopped(5)); + QCOMPARE(op, &o21); + op = oo.findChild(utf16_name); + QCOMPARE(op, &o22); + op = oo.findChild(utf16_name.chopped(1)); + QCOMPARE(op, nullptr); + const QStringView utf16_name_with_trailing_data = u"utf16 ⁎ obj_data"; + op = oo.findChild(utf16_name_with_trailing_data.chopped(5)); + QCOMPARE(op, &o22); + op = oo.findChild(L1_name); + QCOMPARE(op, &o23); + op = oo.findChild(L1_name.chopped(1)); + QCOMPARE(op, nullptr); + op = oo.findChild((L1_name + "_data"_L1).chopped(5)); + QCOMPARE(op, &o23); + QList l; QList tl;