diff options
| author | Ahmad Samir <a.samirh78@gmail.com> | 2025-08-10 20:47:44 +0300 |
|---|---|---|
| committer | Ahmad Samir <a.samirh78@gmail.com> | 2025-10-02 01:40:00 +0300 |
| commit | 0090ad0fa442de91fb87486baa951511eae0c399 (patch) | |
| tree | de3a931eda94a512558a30d9861664fe43e1ee09 /src/corelib/kernel/qobject.cpp | |
| parent | 7f6d53808964140e9606be372883427053e5523b (diff) | |
QObject: disconnect(): don't normalize signatures unconditionally
First try the method signatures as-is, and only if that doesn't work,
try normalizing them.
Remove the `try` blocks because now they are redundant, catching to just
rethrow isn't useful (as pointed out in the code review):
if (sender->metaObject()->indexOfSignal(signal) == -1) {
try {
pinnedSignal = QMetaObject::normalizedSignature(signal);
signal = pinnedSignal.constData();
} catch (const std::bad_alloc &) {
rethrow;
}
...
}
Call err_method_notfound() and co. earlier; if the signal or slot isn't
found in the metaobject, it won't be found in its super-classes.
Using normalized signatures has always been the recommended way of using
string-based {dis,}connect(), so if you still don't use normalized
signatures in your code, you pay the extra overhead.
Task-number: QTBUG-135819
Task-number: QTBUG-135572
Change-Id: I38d545ecd0589493cfb3532b17917afee192f212
Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
Diffstat (limited to 'src/corelib/kernel/qobject.cpp')
| -rw-r--r-- | src/corelib/kernel/qobject.cpp | 62 |
1 files changed, 33 insertions, 29 deletions
diff --git a/src/corelib/kernel/qobject.cpp b/src/corelib/kernel/qobject.cpp index 4c99a8ae470..85bba774af6 100644 --- a/src/corelib/kernel/qobject.cpp +++ b/src/corelib/kernel/qobject.cpp @@ -3338,19 +3338,26 @@ bool QObject::disconnect(const QObject *sender, const char *signal, } QByteArray pinnedSignal; - bool signal_found = false; const QMetaObject *smeta = sender->metaObject(); Q_ASSERT(QMetaObjectPrivate::get(smeta)->revision >= 7); + int signal_index = -1; QByteArrayView signalName; QArgumentTypeArray signalTypes; if (signal) { - QT_TRY { + signalName = QMetaObjectPrivate::decodeMethodSignature(signal, signalTypes); + signal_index = QMetaObjectPrivate::indexOfSignalRelative(&smeta, signalName, signalTypes); + if (signal_index == -1) { pinnedSignal = QMetaObject::normalizedSignature(signal); signal = pinnedSignal.constData(); - } QT_CATCH (const std::bad_alloc &) { - // if the signal is already normalized, we can continue. - if (smeta->indexOfSignal(signal) == -1) - QT_RETHROW; + signalTypes.clear(); + signalName = QMetaObjectPrivate::decodeMethodSignature(signal, signalTypes); + signal_index = QMetaObjectPrivate::indexOfSignalRelative(&smeta, signalName, + signalTypes); + } + if (signal_index == -1) { + err_method_notfound(sender, signal_arg, "disconnect"); + err_info_about_objects("disconnect", sender, receiver); + return false; } } @@ -3366,19 +3373,25 @@ bool QObject::disconnect(const QObject *sender, const char *signal, }; QByteArray pinnedMethod; - bool method_found = false; const QMetaObject *rmeta = receiver ? receiver->metaObject() : nullptr; Q_ASSERT(!rmeta || QMetaObjectPrivate::get(rmeta)->revision >= 7); + int method_index = -1; QByteArrayView methodName; QArgumentTypeArray methodTypes; if (method) { - QT_TRY { + methodName = QMetaObjectPrivate::decodeMethodSignature(method, methodTypes); + method_index = getMethodIndex(membcode, rmeta, methodName, methodTypes); + if (method_index == -1) { pinnedMethod = QMetaObject::normalizedSignature(method); method = pinnedMethod.constData(); - } QT_CATCH(const std::bad_alloc &) { - // if the method is already normalized, we can continue. - if (rmeta->indexOfMethod(method) == -1) - QT_RETHROW; + methodTypes.clear(); + methodName = QMetaObjectPrivate::decodeMethodSignature(method, methodTypes); + method_index = getMethodIndex(membcode, rmeta, methodName, methodTypes); + } + if (method_index == -1) { + err_method_notfound(receiver, method_arg, "disconnect"); + err_info_about_objects("disconnect", sender, receiver); + return false; } } @@ -3387,45 +3400,36 @@ bool QObject::disconnect(const QObject *sender, const char *signal, * and slots with the same signature. */ bool res = false; - if (signal) - signalName = QMetaObjectPrivate::decodeMethodSignature(signal, signalTypes); - if (method) - methodName = QMetaObjectPrivate::decodeMethodSignature(method, methodTypes); do { - int signal_index = -1; if (signal) { - signal_index = QMetaObjectPrivate::indexOfSignalRelative( - &smeta, signalName, signalTypes); + // Already computed the signal_index for `smeta` above + if (smeta != sender->metaObject()) { + signal_index = QMetaObjectPrivate::indexOfSignalRelative(&smeta, signalName, + signalTypes); + } if (signal_index < 0) break; signal_index = QMetaObjectPrivate::originalClone(smeta, signal_index); signal_index += QMetaObjectPrivate::signalOffset(smeta); - signal_found = true; } if (!method) { res |= QMetaObjectPrivate::disconnect(sender, signal_index, smeta, receiver, -1, nullptr); } else { do { - int method_index = getMethodIndex(membcode, rmeta, methodName, methodTypes); + // Already computed the method_index for receiver->metaObject() above + if (rmeta != receiver->metaObject()) + method_index = getMethodIndex(membcode, rmeta, methodName, methodTypes); if (method_index >= 0) while (method_index < rmeta->methodOffset()) rmeta = rmeta->superClass(); if (method_index < 0) break; res |= QMetaObjectPrivate::disconnect(sender, signal_index, smeta, receiver, method_index, nullptr); - method_found = true; } while ((rmeta = rmeta->superClass())); } } while (signal && (smeta = smeta->superClass())); - if (signal && !signal_found) { - err_method_notfound(sender, signal_arg, "disconnect"); - err_info_about_objects("disconnect", sender, receiver); - } else if (method && !method_found) { - err_method_notfound(receiver, method_arg, "disconnect"); - err_info_about_objects("disconnect", sender, receiver); - } if (res) { if (!signal) const_cast<QObject *>(sender)->disconnectNotify(QMetaMethod()); |
