diff options
author | Marc Mutz <marc.mutz@kdab.com> | 2021-07-02 08:32:09 +0200 |
---|---|---|
committer | Marc Mutz <marc.mutz@kdab.com> | 2021-07-13 16:57:31 +0200 |
commit | 2b50c8bec086ae975ac5152e08f6b3dcf76306a0 (patch) | |
tree | 656fded2be7e3e7d8d7d7c9336da8e1bad0d7ac7 /src/corelib/kernel/qobject.cpp | |
parent | 1edb51a315c4ab307878d6620d8d7484cc080d09 (diff) |
QObject: optimize the common case of findChildren(QString())
Outside tests, all in-tree callers of QObject::findChildren() pass no
name to match, and in my experience that is also true for the vast
majority of out-of-tree users.
Avoid the temporary QString creation in the caller and the repeated
QString::isNull() checks in the implementation by overloading
findChildren() without a name argument and checking for name.isNull()
only once, forking off into separate helper functions.
Adjust in-tree callers that used an explicit `QString()` argument in
order to pass options, which goes to show that `name` should never
have been the first argument of findChilden() in the first place, even
though I appreciate the symmetry with findChild() (the use-cases of
which, however, are radically different).
Change a `findChildren().size() == 0` call found while scanning for
findChildren() calls to `!findChild()` as a drive-by.
Modernize loops in the various qt_qFindChild{,ren}_helper() overloads
to match how the new code looks.
[ChangeLog][QtCore][QObject] Added findChildren() overload taking no
name (thus optimizing this common case).
Change-Id: Ifc56e5438023d079b40c67f11ae274a3e128ad5e
Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
Reviewed-by: MÃ¥rten Nordheim <marten.nordheim@qt.io>
Diffstat (limited to 'src/corelib/kernel/qobject.cpp')
-rw-r--r-- | src/corelib/kernel/qobject.cpp | 74 |
1 files changed, 51 insertions, 23 deletions
diff --git a/src/corelib/kernel/qobject.cpp b/src/corelib/kernel/qobject.cpp index 8eb2af0c61..d524fd4305 100644 --- a/src/corelib/kernel/qobject.cpp +++ b/src/corelib/kernel/qobject.cpp @@ -1947,7 +1947,8 @@ void QObject::killTimer(int id) 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. - Omitting the \a name argument causes all object names to be matched. + A null \a name argument causes all objects to be matched, an empty one + only those whose objectName is empty. The search is performed recursively, unless \a options specifies the option FindDirectChildrenOnly. @@ -1968,6 +1969,19 @@ void QObject::killTimer(int id) */ /*! + \fn template<typename T> QList<T> QObject::findChildren(Qt::FindChildOptions options) const + \overload + \since 6.3 + + Returns all children of this object that can be cast to type T, or + an empty list if there are no such objects. + The search is performed recursively, unless \a options specifies the + option FindDirectChildrenOnly. + + \sa findChild() +*/ + +/*! \fn QList<T> QObject::findChildren(const QRegularExpression &re, Qt::FindChildOptions options) const \overload findChildren() @@ -2012,24 +2026,46 @@ void QObject::killTimer(int id) \sa QObject::findChildren() */ +static void qt_qFindChildren_with_name(const QObject *parent, const QString &name, + const QMetaObject &mo, QList<void *> *list, + Qt::FindChildOptions options) +{ + 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); + } +} + /*! \internal */ void qt_qFindChildren_helper(const QObject *parent, const QString &name, const QMetaObject &mo, QList<void*> *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<void*> *list, Qt::FindChildOptions options) +{ Q_ASSERT(parent); Q_ASSERT(list); - const QObjectList &children = parent->children(); - QObject *obj; - for (int i = 0; i < children.size(); ++i) { - obj = children.at(i); - if (mo.cast(obj)) { - if (name.isNull() || obj->objectName() == name) - list->append(obj); - } + for (QObject *obj : parent->children()) { + if (mo.cast(obj)) + list->append(obj); if (options & Qt::FindChildrenRecursively) - qt_qFindChildren_helper(obj, name, mo, list, options); + qt_qFindChildren_helper(obj, mo, list, options); } } @@ -2042,10 +2078,7 @@ void qt_qFindChildren_helper(const QObject *parent, const QRegularExpression &re { Q_ASSERT(parent); Q_ASSERT(list); - const QObjectList &children = parent->children(); - QObject *obj; - for (int i = 0; i < children.size(); ++i) { - obj = children.at(i); + for (QObject *obj : parent->children()) { if (mo.cast(obj)) { QRegularExpressionMatch m = re.match(obj->objectName()); if (m.hasMatch()) @@ -2063,18 +2096,13 @@ void qt_qFindChildren_helper(const QObject *parent, const QRegularExpression &re QObject *qt_qFindChild_helper(const QObject *parent, const QString &name, const QMetaObject &mo, Qt::FindChildOptions options) { Q_ASSERT(parent); - const QObjectList &children = parent->children(); - QObject *obj; - int i; - for (i = 0; i < children.size(); ++i) { - obj = children.at(i); + for (QObject *obj : parent->children()) { if (mo.cast(obj) && (name.isNull() || obj->objectName() == name)) return obj; } if (options & Qt::FindChildrenRecursively) { - for (i = 0; i < children.size(); ++i) { - obj = qt_qFindChild_helper(children.at(i), name, mo, options); - if (obj) + for (QObject *child : parent->children()) { + if (QObject *obj = qt_qFindChild_helper(child, name, mo, options)) return obj; } } @@ -3593,7 +3621,7 @@ void QMetaObject::connectSlotsByName(QObject *o) const QMetaObject *mo = o->metaObject(); Q_ASSERT(mo); const QObjectList list = // list of all objects to look for matching signals including... - o->findChildren<QObject *>(QString()) // all children of 'o'... + o->findChildren<QObject *>() // all children of 'o'... << o; // and the object 'o' itself // for each method/slot of o ... |