53 #if QT_CONFIG(regularexpression)
57 #include <private/qthread_p.h>
68 #include <private/qorderedmutexlocker_p.h>
69 #include <private/qhooks_p.h>
70 #include <qtcore_tracepoints_p.h>
81 static int DIRECT_CONNECTION_ONLY = 0;
103 const auto parameterCount =
method.parameterCount();
104 int *typeIds =
new int[parameterCount + 1];
106 for (
int i = 0;
i < parameterCount; ++
i) {
109 typeIds[
i] = QMetaType::VoidStar;
111 typeIds[
i] = metaType.
id();
115 "QObject::connect: Cannot queue arguments of type '%s'\n"
116 "(Make sure '%s' is registered using qRegisterMetaType().)",
122 typeIds[parameterCount] = 0;
127 static int *queuedConnectionTypes(
const QArgumentType *argumentTypes,
int argc)
129 auto types = std::make_unique<int[]>(argc + 1);
130 for (
int i = 0;
i < argc; ++
i) {
134 else if (
type.name().endsWith(
'*'))
135 types[
i] = QMetaType::VoidStar;
141 "QObject::connect: Cannot queue arguments of type '%s'\n"
142 "(Make sure '%s' is registered using qRegisterMetaType().)",
143 type.name().constData(),
type.name().constData());
149 return types.release();
209 if (thisThreadData->hasEventDispatcher())
210 thisThreadData->eventDispatcher.loadRelaxed()->unregisterTimers(
q_ptr);
216 qWarning(
"QObject::~QObject: Timers cannot be stopped from another thread");
223 thisThreadData->deref();
235 static void computeOffsets(
const QMetaObject *metaobject,
int *signalOffset,
int *methodOffset)
237 *signalOffset = *methodOffset = 0;
241 *methodOffset +=
d->methodCount;
243 *signalOffset +=
d->signalCount;
254 if (signal_index < 0 || !cd)
257 if (signal_index < cd->signalVectorCount()) {
261 if (
c->receiver.loadRelaxed() == receiver)
263 c =
c->nextConnectionList.loadRelaxed();
275 if (signal_index < 0 || !cd)
277 if (signal_index < cd->signalVectorCount()) {
284 c =
c->nextConnectionList.loadRelaxed();
298 returnValue <<
c->sender;
321 if (connectionList.
last.loadRelaxed()) {
322 Q_ASSERT(connectionList.
last.loadRelaxed()->receiver.loadRelaxed());
323 connectionList.
last.loadRelaxed()->nextConnectionList.storeRelaxed(
c);
325 connectionList.
first.storeRelaxed(
c);
328 c->prevConnectionList = connectionList.
last.loadRelaxed();
329 connectionList.
last.storeRelaxed(
c);
332 rd->ensureConnectionData();
334 c->prev = &(
rd->connections.loadRelaxed()->senders);
338 c->next->prev = &
c->next;
345 c->receiver.storeRelaxed(
nullptr);
349 c->receiverThreadData.storeRelaxed(
nullptr);
353 for (
Connection *cc =
connections.first.loadRelaxed(); cc; cc = cc->nextConnectionList.loadRelaxed()) {
365 c->next->prev =
c->prev;
369 connections.first.storeRelaxed(
c->nextConnectionList.loadRelaxed());
378 n->prevConnectionList =
c->prevConnectionList;
379 if (
c->prevConnectionList)
380 c->prevConnectionList->nextConnectionList.storeRelaxed(
n);
381 c->prevConnectionList =
nullptr;
391 c->nextInOrphanList =
o;
396 for (
Connection *cc =
connections.first.loadRelaxed(); cc; cc = cc->nextConnectionList.loadRelaxed()) {
412 std::unique_lock<QBasicMutex>
lock(*senderMutex, std::defer_lock_t{});
413 if (lockPolicy == NeedToLock)
415 if (
ref.loadAcquire() > 1)
421 c = orphaned.fetchAndStoreRelaxed(
nullptr);
425 if (lockPolicy == AlreadyLockedAndTemporarilyReleasingLock) {
440 next =
v->nextInOrphanList;
444 next =
c->nextInOrphanList;
472 if (signalVector->
at(-1).
first.loadRelaxed())
478 if (
c->receiver.loadRelaxed())
480 c =
c->nextConnectionList.loadRelaxed();
495 if (signalVector->
at(-1).
first.loadAcquire())
510 #if QT_CONFIG(thread)
512 semaphore_->release();
519 inline void QMetaCallEvent::allocArgs()
524 constexpr
size_t each =
sizeof(
void*) +
sizeof(
QMetaType);
525 void *
const memory =
d.nargs_ * each >
sizeof(prealloc_) ?
526 calloc(
d.nargs_, each) : prealloc_;
529 d.args_ =
static_cast<void **
>(
memory);
540 const QObject *sender,
int signalId,
543 d({
nullptr,
args, callFunction, 0, method_offset, method_relative}),
555 const QObject *sender,
int signalId,
573 const QObject *sender,
int signalId,
576 d({
nullptr,
nullptr, callFunction, nargs, method_offset, method_relative}),
589 const QObject *sender,
int signalId,
592 d({slotO,
nullptr,
nullptr, nargs, 0,
ushort(-1)}),
607 for (
int i = 0;
i < d.nargs_; ++
i) {
608 if (
t[
i].isValid() && d.args_[
i])
609 t[
i].destroy(d.args_[
i]);
611 if (
reinterpret_cast<void *
>(d.args_) !=
reinterpret_cast<void *
>(prealloc_))
615 d.slotObj_->destroyIfLastRef();
624 d.slotObj_->call(
object, d.args_);
625 }
else if (d.callFunction_ && d.method_offset_ <=
object->metaObject()->methodOffset()) {
629 d.method_offset_ + d.method_relative_, d.args_);
882 if (
parent && parentThreadData != currentThreadData) {
885 qWarning(
"QObject: Cannot create children for a parent that is in a different thread.\n"
886 "(Parent is %s(%p), parent's thread is %s(%p), current thread is %s(%p)",
887 parent->metaObject()->className(),
889 parentThread ? parentThread->metaObject()->className() :
"QThread",
891 currentThread ? currentThread->metaObject()->className() :
"QThread",
930 d->threadData.storeRelaxed(threadData);
933 if (!check_parent_thread(
parent,
parent ?
parent->d_func()->threadData.loadRelaxed() :
nullptr, threadData))
938 d->parent->d_func()->children.append(
this);
986 d->wasDeleted =
true;
991 d->clearBindingStorage();
994 if (sharedRefcount) {
996 qWarning(
"QObject: shared QObject was deleted directly. The program is malformed and may crash.");
1003 delete sharedRefcount;
1006 if (!
d->isWidget &&
d->isSignalConnected(0)) {
1020 QBasicMutex *signalSlotMutex = signalSlotLock(
this);
1033 if (
c == connectionList.
first.loadAcquire() &&
c->receiver.loadAcquire()) {
1065 if (
node->isSlotObject) {
1066 slotObj =
node->slotObj;
1067 node->isSlotObject =
false;
1079 const bool locksAreTheSame = signalSlotMutex ==
m;
1080 if (!locksAreTheSame)
1089 if (locksAreTheSame)
1102 d->connections.storeRelaxed(
nullptr);
1104 if (!
d->children.isEmpty())
1105 d->deleteChildren();
1113 d->setParent_helper(
nullptr);
1120 if (
v != &DIRECT_CONNECTION_ONLY)
1246 #if QT_CONFIG(thread)
1248 return d->extraData ?
d->extraData->objectName.valueBypassingBindings() :
QString();
1255 return d->extraData ?
d->extraData->objectName :
QString();
1268 d->extraData->objectName.removeBindingUnlessInWrapper();
1270 if (
d->extraData->objectName !=
name) {
1271 d->extraData->objectName.setValueBypassingBindings(
name);
1272 d->extraData->objectName.notify();
1331 switch (
e->type()) {
1350 if (!d_func()->connections.loadRelaxed()) {
1352 d_func()->ensureConnectionData();
1364 if (eventDispatcher) {
1517 bool previous =
d->blockSig;
1529 return d_func()->threadData.loadRelaxed()->
thread.loadAcquire();
1576 if (
d->threadData.loadRelaxed()->thread.loadAcquire() == targetThread) {
1581 if (
d->parent !=
nullptr) {
1582 qWarning(
"QObject::moveToThread: Cannot move objects with a parent");
1586 qWarning(
"QObject::moveToThread: Widgets cannot be moved to a new thread");
1589 if (!
d->bindingStorage.isEmpty()) {
1590 qWarning(
"QObject::moveToThread: Can not move objects that contain bindings or are used in bindings to a new thread.");
1596 QThreadData *thisThreadData =
d->threadData.loadAcquire();
1599 currentData = thisThreadData;
1600 }
else if (thisThreadData != currentData) {
1601 qWarning(
"QObject::moveToThread: Current thread (%p) is not the object's thread (%p).\n"
1602 "Cannot move to target thread (%p)\n",
1606 qWarning(
"You might be loading two sets of Qt binaries into the same process. "
1607 "Check that all plugins are compiled against the right Qt binaries. Export "
1608 "DYLD_PRINT_LIBRARIES=1 and check that only one set of binaries are being loaded.");
1615 d->moveToThread_helper();
1630 d_func()->setThreadData_helper(currentData, targetData);
1635 currentData->
deref();
1645 child->d_func()->moveToThread_helper();
1654 int eventsMoved = 0;
1687 QThreadData *old =
c->receiverThreadData.loadRelaxed();
1690 c->receiverThreadData.storeRelaxed(targetData);
1707 child->d_func()->setThreadData_helper(currentData, targetData);
1716 for (
int i = 0;
i < timerList->
size(); ++
i) {
1770 qWarning(
"QObject::startTimer: Timers cannot have negative intervals");
1774 auto thisThreadData =
d->threadData.loadRelaxed();
1775 if (
Q_UNLIKELY(!thisThreadData->hasEventDispatcher())) {
1776 qWarning(
"QObject::startTimer: Timers can only be used with threads started with QThread");
1780 qWarning(
"QObject::startTimer: Timers cannot be started from another thread");
1783 int timerId = thisThreadData->eventDispatcher.loadRelaxed()->registerTimer(interval, timerType,
this);
1786 d->extraData->runningTimers.append(timerId);
1842 qWarning(
"QObject::killTimer: Timers cannot be stopped from another thread");
1846 int at =
d->extraData ?
d->extraData->runningTimers.indexOf(
id) : -1;
1849 qWarning(
"QObject::killTimer(): Error: timer id %d is not valid for object %p (%s, %ls), timer has not been killed",
1853 qUtf16Printable(objectName()));
1857 auto thisThreadData =
d->threadData.loadRelaxed();
1858 if (thisThreadData->hasEventDispatcher())
1859 thisThreadData->eventDispatcher.loadRelaxed()->unregisterTimer(
id);
1861 d->extraData->runningTimers.remove(
at);
2022 Qt::FindChildOptions options)
2063 #if QT_CONFIG(regularexpression)
2137 const auto checkForParentChildLoops =
qScopeGuard([&](){
2141 if (++
depth == CheckForParentChildLoopsWarnDepth) {
2142 qWarning(
"QObject %p (class: '%s', object name: '%s') may have a loop in its parent-child chain; "
2143 "this is undefined behavior",
2144 q,
q->metaObject()->className(), qPrintable(
q->objectName()));
2179 qWarning(
"QObject::setParent: Cannot set parent, new parent is in a different thread");
2240 if (
d->threadData.loadRelaxed() !=
obj->d_func()->threadData.loadRelaxed()) {
2241 qWarning(
"QObject::installEventFilter(): Cannot filter events for objects in a different thread.");
2249 d->extraData->eventFilters.removeAll((
QObject *)
nullptr);
2250 d->extraData->eventFilters.removeAll(
obj);
2251 d->extraData->eventFilters.prepend(
obj);
2271 for (
int i = 0;
i <
d->extraData->eventFilters.count(); ++
i) {
2272 if (
d->extraData->eventFilters.at(
i) ==
obj)
2273 d->extraData->eventFilters[
i] =
nullptr;
2323 qWarning(
"You are deferring the delete of QCoreApplication, this may not work as expected.");
2371 if (currentThreadData !=
nullptr)
2376 static int extract_code(
const char *member)
2379 return (((
int)(*member) -
'0') & 0x3);
2382 static const char *extract_location(
const char *member)
2393 static bool check_signal_macro(
const QObject *sender,
const char *
signal,
2394 const char *
func,
const char *
op)
2396 int sigcode = extract_code(
signal);
2399 qCWarning(lcConnect,
"QObject::%s: Attempt to %s non-signal %s::%s",
func,
op,
2400 sender->metaObject()->className(),
signal + 1);
2402 qCWarning(lcConnect,
"QObject::%s: Use the SIGNAL macro to %s %s::%s",
func,
op,
2403 sender->metaObject()->className(),
signal);
2409 static bool check_method_code(
int code,
const QObject *
object,
const char *
method,
const char *
func)
2413 "QObject::%s: Use the SLOT or SIGNAL macro to "
2422 static void err_method_notfound(
const QObject *
object,
2425 const char *
type =
"method";
2426 switch (extract_code(
method)) {
2430 const char *
loc = extract_location(
method);
2431 if (strchr(
method,
')') ==
nullptr)
2432 qCWarning(lcConnect,
"QObject::%s: Parentheses expected, %s %s::%s%s%s",
func,
type,
2440 static void err_info_about_objects(
const char *
func,
const QObject *sender,
const QObject *receiver)
2445 qCWarning(lcConnect,
"QObject::%s: (sender name: '%s')",
func,
a.toLocal8Bit().data());
2447 qCWarning(lcConnect,
"QObject::%s: (receiver name: '%s')",
func,
b.toLocal8Bit().data());
2562 if (!check_signal_macro(
this,
signal,
"receivers",
"bind"))
2566 int signal_index =
d->signalIndex(
signal);
2567 if (signal_index < 0) {
2569 err_method_notfound(
this,
signal - 1,
"receivers");
2574 if (!
d->isSignalConnected(signal_index))
2584 if (cd && signal_index < cd->signalVectorCount()) {
2587 receivers +=
c->receiver.loadRelaxed() ? 1 : 0;
2588 c =
c->nextConnectionList.loadRelaxed();
2620 "QObject::isSignalConnected" ,
"the parameter must be a signal member of the object");
2661 if (!
obj || !member.mobj)
2665 while (
m !=
nullptr &&
m != member.mobj)
2673 computeOffsets(
m, &signalOffset, &methodOffset);
2675 *methodIndex += methodOffset;
2690 qCWarning(lcConnect,
"QObject::connect: Connecting from COMPAT signal (%s::%s)",
2694 qCWarning(lcConnect,
"QObject::connect: Connecting from %s::%s to COMPAT slot (%s::%s)",
2696 method.methodSignature().constData());
2776 if (sender ==
nullptr || receiver ==
nullptr ||
signal ==
nullptr ||
method ==
nullptr) {
2777 qCWarning(lcConnect,
"QObject::connect: Cannot connect %s::%s to %s::%s",
2778 sender ? sender->metaObject()->className() :
"(nullptr)",
2780 receiver ? receiver->metaObject()->className() :
"(nullptr)",
2786 if (!check_signal_macro(sender,
signal,
"connect",
"bind"))
2789 const char *signal_arg =
signal;
2795 &smeta, signalName, signalTypes.
size(), signalTypes.
constData());
2796 if (signal_index < 0) {
2801 signalTypes.
clear();
2803 smeta = sender->metaObject();
2805 &smeta, signalName, signalTypes.
size(), signalTypes.
constData());
2807 if (signal_index < 0) {
2808 err_method_notfound(sender, signal_arg,
"connect");
2809 err_info_about_objects(
"connect", sender, receiver);
2816 int membcode = extract_code(
method);
2818 if (!check_method_code(membcode, receiver,
method,
"connect"))
2820 const char *method_arg =
method;
2825 const QMetaObject *rmeta = receiver->metaObject();
2826 int method_index_relative = -1;
2831 &rmeta, methodName, methodTypes.
size(), methodTypes.
constData());
2835 &rmeta, methodName, methodTypes.
size(), methodTypes.
constData());
2838 if (method_index_relative < 0) {
2843 methodTypes.
clear();
2846 rmeta = receiver->metaObject();
2850 &rmeta, methodName, methodTypes.
size(), methodTypes.
constData());
2854 &rmeta, methodName, methodTypes.
size(), methodTypes.
constData());
2859 if (method_index_relative < 0) {
2860 err_method_notfound(receiver, method_arg,
"connect");
2861 err_info_about_objects(
"connect", sender, receiver);
2868 "QObject::connect: Incompatible sender/receiver arguments"
2869 "\n %s::%s --> %s::%s",
2870 sender->metaObject()->className(),
signal, receiver->metaObject()->className(),
2875 int *
types =
nullptr;
2884 check_and_warn_compat(smeta, smethod, rmeta, rmethod);
2887 sender, signal_index, smeta, receiver, method_index_relative, rmeta ,
type,
types));
2915 if (sender ==
nullptr
2916 || receiver ==
nullptr
2919 qCWarning(lcConnect,
"QObject::connect: Cannot connect %s::%s to %s::%s",
2920 sender ? sender->metaObject()->className() :
"(nullptr)",
2921 signal.methodSignature().constData(),
2922 receiver ? receiver->metaObject()->className() :
"(nullptr)",
2923 method.methodSignature().constData());
2936 const QMetaObject *rmeta = receiver->metaObject();
2937 if (signal_index == -1) {
2938 qCWarning(lcConnect,
"QObject::connect: Can't find signal %s on instance of class %s",
2942 if (method_index == -1) {
2943 qCWarning(lcConnect,
"QObject::connect: Can't find method %s on instance of class %s",
2949 method.methodSignature().constData())) {
2951 "QObject::connect: Incompatible sender/receiver arguments"
2952 "\n %s::%s --> %s::%s",
2954 method.methodSignature().constData());
2958 int *
types =
nullptr;
2966 sender, signal_index,
signal.enclosingMetaObject(), receiver, method_index,
nullptr,
type,
types));
3051 if (sender ==
nullptr || (receiver ==
nullptr &&
method !=
nullptr)) {
3052 qCWarning(lcConnect,
"QObject::disconnect: Unexpected nullptr parameter");
3056 const char *signal_arg =
signal;
3058 bool signal_found =
false;
3063 } QT_CATCH (
const std::bad_alloc &) {
3065 if (sender->metaObject()->indexOfSignal(
signal + 1) == -1)
3069 if (!check_signal_macro(sender,
signal,
"disconnect",
"unbind"))
3075 const char *method_arg =
method;
3077 bool method_found =
false;
3082 } QT_CATCH(
const std::bad_alloc &) {
3084 if (receiver->metaObject()->indexOfMethod(
method + 1) == -1)
3088 membcode = extract_code(
method);
3089 if (!check_method_code(membcode, receiver,
method,
"disconnect"))
3111 int signal_index = -1;
3114 &smeta, signalName, signalTypes.
size(), signalTypes.
constData());
3115 if (signal_index < 0)
3119 signal_found =
true;
3125 const QMetaObject *rmeta = receiver->metaObject();
3128 rmeta, methodName, methodTypes.
size(), methodTypes.
constData());
3129 if (method_index >= 0)
3130 while (method_index < rmeta->methodOffset())
3132 if (method_index < 0)
3135 method_found =
true;
3140 if (
signal && !signal_found) {
3141 err_method_notfound(sender, signal_arg,
"disconnect");
3142 err_info_about_objects(
"disconnect", sender, receiver);
3143 }
else if (
method && !method_found) {
3144 err_method_notfound(receiver, method_arg,
"disconnect");
3145 err_info_about_objects(
"disconnect", sender, receiver);
3188 if (sender ==
nullptr || (receiver ==
nullptr &&
method.mobj !=
nullptr)) {
3189 qCWarning(lcConnect,
"QObject::disconnect: Unexpected nullptr parameter");
3194 qCWarning(lcConnect,
"QObject::%s: Attempt to %s non-signal %s::%s",
3195 "disconnect",
"unbind",
3196 sender->metaObject()->className(),
signal.methodSignature().constData());
3202 qCWarning(lcConnect,
"QObject::disconnect: cannot use constructor as argument %s::%s",
3203 receiver->metaObject()->className(),
method.methodSignature().constData());
3217 if (
signal.mobj && signal_index == -1) {
3218 qCWarning(lcConnect,
"QObject::disconnect: signal %s not found on class %s",
3219 signal.methodSignature().constData(), sender->metaObject()->className());
3223 if (receiver &&
method.mobj && method_index == -1) {
3224 qCWarning(lcConnect,
"QObject::disconnect: method %s not found on class %s",
3225 method.methodSignature().constData(), receiver->metaObject()->className());
3335 static int methodIndexToSignalIndex(
const QMetaObject **
base,
int signal_index)
3337 if (signal_index < 0)
3338 return signal_index;
3344 int signalOffset, methodOffset;
3345 computeOffsets(
metaObject, &signalOffset, &methodOffset);
3346 if (signal_index < metaObject->methodCount())
3349 signal_index = signal_index - methodOffset + signalOffset;
3352 return signal_index;
3364 const QObject *receiver,
int method_index,
int type,
3368 signal_index = methodIndexToSignalIndex(&smeta, signal_index);
3370 receiver, method_index,
3385 const QObject *receiver,
int method_index,
3396 signalSlotLock(receiver));
3403 int method_index_absolute = method_index + method_offset;
3406 if (!
c2->isSlotObject &&
c2->receiver.loadRelaxed() == receiver &&
c2->method() == method_index_absolute)
3408 c2 =
c2->nextConnectionList.loadRelaxed();
3422 c->signal_index = signal_index;
3423 c->receiver.storeRelaxed(
r);
3426 c->receiverThreadData.storeRelaxed(td);
3427 c->method_relative = method_index;
3428 c->method_offset = method_offset;
3429 c->connectionType =
type;
3430 c->isSlotObject =
false;
3431 c->argumentTypes.storeRelaxed(
types);
3432 c->callFunction = callFunction;
3433 c->isSingleShot = isSingleShot;
3440 s->connectNotify(smethod);
3449 const QObject *receiver,
int method_index)
3452 signal_index = methodIndexToSignalIndex(&smeta, signal_index);
3454 receiver, method_index,
nullptr);
3465 const QObject *receiver,
int method_index)
3468 signal_index = methodIndexToSignalIndex(&smeta, signal_index);
3470 receiver, method_index,
nullptr,
3479 const QObject *receiver,
int method_index,
void **slot,
3482 bool success =
false;
3485 auto *
c = connectionList.first.loadRelaxed();
3488 if (
r && (receiver ==
nullptr || (
r == receiver
3489 && (method_index < 0 || (!
c->isSlotObject &&
c->method() == method_index))
3490 && (slot ==
nullptr || (
c->isSlotObject &&
c->slotObj->compare(slot)))))) {
3491 bool needToUnlock =
false;
3494 receiverMutex = signalSlotLock(
r);
3498 if (
c->receiver.loadRelaxed())
3506 if (disconnectType == DisconnectOne)
3509 c =
c->nextConnectionList.loadRelaxed();
3520 const QObject *receiver,
int method_index,
void **slot,
3528 QBasicMutex *senderMutex = signalSlotLock(sender);
3535 bool success =
false;
3540 if (signal_index < 0) {
3543 if (disconnectHelper(
connections.data(), sig_index, receiver, method_index, slot, senderMutex, disconnectType))
3546 }
else if (signal_index < scd->signalVectorCount()) {
3547 if (disconnectHelper(
connections.data(), signal_index, receiver, method_index, slot, senderMutex, disconnectType))
3558 s->disconnectNotify(smethod);
3569 const int openParen =
signature.indexOf(
'(');
3570 const bool hasParameters = openParen >= 0 && openParen <
signature.size() - 2;
3572 if (hasParameters) {
3586 const auto receiverMo = receiver->metaObject();
3587 const auto slot = receiverMo->method(receiverIndex);
3589 + senderName +
", " + formatConnectionSignature(senderMo->
className(),
signal)
3591 + formatConnectionSignature(receiverMo->className(), slot) +
");";
3625 for (
int i = 0;
i <
mo->methodCount(); ++
i) {
3626 const QByteArray slotSignature =
mo->method(
i).methodSignature();
3627 const char *slot = slotSignature.
constData();
3631 if (slot[0] !=
'o' || slot[1] !=
'n' || slot[2] !=
'_')
3635 bool foundIt =
false;
3636 for (
int j = 0;
j <
list.count(); ++
j) {
3644 const char *
signal = slot + coName.
size() + 4;
3648 int sigIndex = co->d_func()->signalIndex(
signal, &smeta);
3660 smeta =
method.enclosingMetaObject();
3665 if (compatibleSignals.
size() > 1)
3666 qCWarning(lcConnectSlotsByName) <<
"QMetaObject::connectSlotsByName: Connecting slot" << slot
3667 <<
"with the first of the following compatible signals:" << compatibleSignals;
3676 qCDebug(lcConnectSlotsByName,
"%s",
3691 int iParen = slotSignature.
indexOf(
'(');
3692 int iLastUnderscore = slotSignature.
lastIndexOf(
'_', iParen - 1);
3693 if (iLastUnderscore > 3)
3695 "QMetaObject::connectSlotsByName: No matching signal for %s", slot);
3711 : m_slotObject(slotObject)
3714 m_slotObject->
ref();
3718 {
return m_slotObject; }
3721 {
return m_slotObject; }
3725 m_slotObject->destroyIfLastRef();
3738 const int *argumentTypes =
c->argumentTypes.loadRelaxed();
3739 if (!argumentTypes) {
3741 argumentTypes = queuedConnectionTypes(
m);
3743 argumentTypes = &DIRECT_CONNECTION_ONLY;
3744 if (!
c->argumentTypes.testAndSetOrdered(
nullptr, argumentTypes)) {
3745 if (argumentTypes != &DIRECT_CONNECTION_ONLY)
3746 delete[] argumentTypes;
3747 argumentTypes =
c->argumentTypes.loadRelaxed();
3750 if (argumentTypes == &DIRECT_CONNECTION_ONLY)
3753 while (argumentTypes[nargs - 1])
3757 QObject *receiver =
c->receiver.loadRelaxed();
3777 for (
int n = 1;
n < nargs; ++
n)
3780 for (
int n = 1;
n < nargs; ++
n)
3790 if (!
c->isSingleShot && !
c->receiver.loadRelaxed()) {
3800 template <
bool callbacks_enabled>
3810 if (
sp->isDeclarativeSignalConnected(signal_index)
3812 Q_TRACE_SCOPE(QMetaObject_activate_declarative_signal, sender, signal_index);
3814 signal_index, argv);
3819 void *empty_argv[] = {
nullptr };
3823 if (!
sp->maybeSignalConnected(signal_index)) {
3835 bool senderDeleted =
false;
3842 if (signal_index < signalVector->
count())
3843 list = &signalVector->
at(signal_index);
3845 list = &signalVector->
at(-1);
3852 uint highestConnectionId =
connections->currentConnectionId.loadRelaxed();
3859 QObject *
const receiver =
c->receiver.loadRelaxed();
3867 bool receiverInSameThread;
3868 if (inSenderThread) {
3881 queued_activate(sender, signal_index,
c, argv);
3883 #if QT_CONFIG(thread)
3885 if (receiverInSameThread) {
3886 qWarning(
"Qt: Dead lock detected while activating a BlockingQueuedConnection: "
3887 "Sender is %s(%p), receiver is %s(%p)",
3888 sender->metaObject()->className(), sender,
3889 receiver->metaObject()->className(), receiver);
3898 if (!
c->isSingleShot && !
c->receiver.loadAcquire())
3901 new QMetaCallEvent(
c->slotObj, sender, signal_index, argv, &semaphore) :
3903 sender, signal_index, argv, &semaphore);
3916 if (
c->isSlotObject) {
3921 obj->call(receiver, argv);
3923 }
else if (
c->callFunction &&
c->method_offset <= receiver->metaObject()->methodOffset()) {
3925 const int method_relative =
c->method_relative;
3926 const auto callFunction =
c->callFunction;
3932 Q_TRACE_SCOPE(QMetaObject_activate_slot, receiver, methodIndex);
3939 const int method =
c->method_relative +
c->method_offset;
3953 }
while ((
c =
c->nextConnectionList.loadRelaxed()) !=
nullptr &&
c->id <= highestConnectionId);
3955 }
while (
list != &signalVector->
at(-1) &&
3957 ((
list = &signalVector->
at(-1)),
true));
3959 if (
connections->currentConnectionId.loadRelaxed() == 0)
3960 senderDeleted =
true;
3962 if (!senderDeleted) {
3963 sp->connections.loadRelaxed()->cleanOrphanedConnections(sender);
3979 doActivate<true>(sender, signal_index, argv);
3981 doActivate<false>(sender, signal_index, argv);
3989 int signal_index = signalOffset + local_signal_index;
3992 doActivate<true>(sender, signal_index, argv);
3994 doActivate<false>(sender, signal_index, argv);
4004 while (
mo->methodOffset() > signal_index)
4005 mo =
mo->superClass();
4006 activate(sender,
mo, signal_index -
mo->methodOffset(), argv);
4028 if (relative_index < 0)
4029 return relative_index;
4040 #ifndef QT_NO_PROPERTIES
4075 const int idx =
d->extraData->propertyNames.indexOf(
name);
4077 if (!
value.isValid()) {
4080 d->extraData->propertyNames.removeAt(
idx);
4081 d->extraData->propertyValues.removeAt(
idx);
4084 d->extraData->propertyNames.append(
name);
4085 d->extraData->propertyValues.append(
value);
4087 if (
value.userType() ==
d->extraData->propertyValues.at(
idx).userType()
4088 &&
value ==
d->extraData->propertyValues.at(
idx))
4090 d->extraData->propertyValues[
idx] =
value;
4101 if (!
p.isWritable())
4102 qWarning(
"%s::setProperty: Property \"%s\" invalid,"
4105 return p.write(
this,
value);
4129 const int i =
d->extraData->propertyNames.indexOf(
name);
4130 return d->extraData->propertyValues.value(
i);
4134 if (!
p.isReadable())
4135 qWarning(
"%s::property: Property \"%s\" invalid or does not exist",
4138 return p.read(
this);
4151 return d->extraData->propertyNames;
4165 const int indent =
level * 4;
4169 if (
qApp->focusWidget() ==
object)
4171 if (
object->isWidgetType()) {
4173 if (
w->isVisible()) {
4175 flags +=
t.arg(
w->x()).arg(
w->y()).arg(
w->width()).arg(
w->height());
4181 qDebug(
"%*s%s::%ls %ls", indent,
"",
object->metaObject()->className(),
4182 qUtf16Printable(
name), qUtf16Printable(
flags));
4214 objectName().isEmpty() ?
"unnamed" : objectName().toLocal8Bit().
data());
4225 for (
int signal_index = 0; signal_index < signalVector->
count(); ++signal_index) {
4230 qDebug(
" signal: %s",
signal.methodSignature().constData());
4234 if (!
c->receiver.loadRelaxed()) {
4235 qDebug(
" <Disconnected receiver>");
4236 c =
c->nextConnectionList.loadRelaxed();
4239 if (
c->isSlotObject) {
4240 qDebug(
" <functor or function pointer>");
4241 c =
c->nextConnectionList.loadRelaxed();
4244 const QMetaObject *receiverMetaObject =
c->receiver.loadRelaxed()->metaObject();
4248 c->receiver.loadRelaxed()->objectName().isEmpty() ?
"unnamed" : qPrintable(
c->receiver.loadRelaxed()->objectName()),
4249 method.methodSignature().constData());
4250 c =
c->nextConnectionList.loadRelaxed();
4263 if (!
s->isSlotObject) {
4268 s->sender->metaObject()->className(),
4269 s->sender->objectName().isEmpty() ?
"unnamed" : qPrintable(
s->sender->objectName()),
4278 #ifndef QT_NO_DEBUG_STREAM
4283 return dbg <<
"QObject(0x0)";
4284 dbg.
nospace() <<
o->metaObject()->className() <<
'(' << (
const void *)
o;
4285 if (!
o->objectName().isEmpty())
4286 dbg <<
", name = " <<
o->objectName();
4968 const QObject *receiver,
void **slot,
4973 qCWarning(lcConnect,
"QObject::connect: invalid nullptr parameter");
4979 int signal_index = -1;
4981 for (; senderMetaObject && signal_index < 0; senderMetaObject = senderMetaObject->
superClass()) {
4986 if (!senderMetaObject) {
4987 qCWarning(lcConnect,
"QObject::connect: signal not found in %s", sender->metaObject()->className());
4995 static void connectWarning(
const QObject *sender,
5000 const char *senderString = sender ? sender->metaObject()->className()
5001 : senderMetaObject ? senderMetaObject->
className()
5003 const char *receiverString = receiver ? receiver->metaObject()->className()
5005 qCWarning(lcConnect,
"QObject::connect(%s, %s): %s", senderString, receiverString,
message);
5016 const QObject *receiver,
void **slot,
5026 if (!sender || !receiver || !slotObj || !senderMetaObject) {
5027 connectWarning(sender, senderMetaObject, receiver,
"invalid nullptr parameter");
5032 connectWarning(sender, senderMetaObject, receiver,
"unique connections require a pointer to member function of a QObject subclass");
5036 connectFailureGuard.dismiss();
5042 signalSlotLock(receiver));
5046 if (
connections->signalVectorCount() > signal_index) {
5050 if (
c2->receiver.loadRelaxed() == receiver &&
c2->isSlotObject &&
c2->slotObj->compare(slot)) {
5054 c2 =
c2->nextConnectionList.loadRelaxed();
5068 c->signal_index = signal_index;
5071 c->receiverThreadData.storeRelaxed(td);
5072 c->receiver.storeRelaxed(
r);
5073 c->slotObj = slotObj;
5074 c->connectionType =
type;
5075 c->isSlotObject =
true;
5077 c->argumentTypes.storeRelaxed(
types);
5078 c->ownArgumentTypes =
false;
5080 c->isSingleShot = isSingleShot;
5109 return disconnected;
5175 if (sender ==
nullptr || (receiver ==
nullptr && slot !=
nullptr)) {
5176 qCWarning(lcConnect,
"QObject::disconnect: Unexpected nullptr parameter");
5180 int signal_index = -1;
5183 for (; senderMetaObject && signal_index < 0; senderMetaObject = senderMetaObject->
superClass()) {
5188 if (!senderMetaObject) {
5189 qCWarning(lcConnect,
"QObject::disconnect: signal not found in %s", sender->metaObject()->className());
5228 qCWarning(lcConnect,
"QObject::connect: invalid nullptr parameter");
5233 const QMetaObject *senderMetaObject = sender->metaObject();
5234 signal_index = methodIndexToSignalIndex(&senderMetaObject, signal_index);
5237 type,
nullptr, senderMetaObject);
5268 const QMetaObject *senderMetaObject = sender->metaObject();
5269 signal_index = methodIndexToSignalIndex(&senderMetaObject, signal_index);
5283 QObject *receiver =
c->receiver.loadRelaxed();
5288 QBasicMutex *receiverMutex = signalSlotLock(receiver);
5295 receiver =
c->receiver.loadRelaxed();
5307 if (receiverMutex != senderMutex) {
5344 if (
other.d_ptr != d_ptr) {
5347 d_ptr =
other.d_ptr;
5358 QMetaObject::Connection::Connection() : d_ptr(
nullptr) {}
5363 QMetaObject::Connection::~Connection()
5370 bool QMetaObject::Connection::isConnected_helper()
const
5391 #include "moc_qobject.cpp"
small capitals from c petite p scientific i
[1]
static bool(* isSignalConnected)(QAbstractDeclarativeData *, const QObject *, int)
static int(* receivers)(QAbstractDeclarativeData *, const QObject *, int)
static void(* destroyed)(QAbstractDeclarativeData *, QObject *)
static void(* signalEmitted)(QAbstractDeclarativeData *, QObject *, int, void **)
static void(* setWidgetParent)(QObject *, QObject *)
The QAbstractEventDispatcher class provides an interface to manage Qt's event queue.
virtual QList< TimerInfo > registeredTimers(QObject *object) const =0
virtual bool unregisterTimers(QObject *object)=0
static void releaseTimerId(int id)
void storeRelaxed(T newValue) noexcept
T loadRelaxed() const noexcept
Type loadAcquire() const noexcept
Type loadRelaxed() const noexcept
void storeRelease(Type newValue) noexcept
QBindable is a wrapper class around binding-enabled properties. It allows type-safe operations while ...
The QByteArray class provides an array of bytes.
qsizetype size() const noexcept
const char * constData() const noexcept
qsizetype indexOf(char c, qsizetype from=0) const
bool isEmpty() const noexcept
qsizetype lastIndexOf(char c, qsizetype from=-1) const
The QChildEvent class contains event parameters for child object events.
static bool sendEvent(QObject *receiver, QEvent *event)
static void removePostedEvents(QObject *receiver, int eventType=0)
static void postEvent(QObject *receiver, QEvent *event, int priority=Qt::NormalEventPriority)
The QDebug class provides an output stream for debugging information.
Convenience class for custom QDebug operators.
The QDynamicPropertyChangeEvent class contains event parameters for dynamic property change events.
The QEvent class is the base class of all event classes. Event objects contain event parameters.
The QExplicitlySharedDataPointer class represents a pointer to an explicitly shared object.
qsizetype size() const noexcept
bool isEmpty() const noexcept
void removeAt(qsizetype i)
const_reference at(qsizetype i) const noexcept
qsizetype count() const noexcept
void prepend(rvalue_ref t)
void append(parameter_type t)
The QMutex class provides access serialization between threads.
The QMutexLocker class is a convenience class that simplifies locking and unlocking mutexes.
QDynamicMetaObjectData * metaObject
QMetaObject * dynamicMetaObject() const
QBindingStorage bindingStorage
The QObject class is the base class of all Qt objects.
int senderSignalIndex() const
int startTimer(int interval, Qt::TimerType timerType=Qt::CoarseTimer)
Q_INVOKABLE QObject(QObject *parent=nullptr)
bool isSignalConnected(const QMetaMethod &signal) const
void installEventFilter(QObject *filterObj)
const QObjectList & children() const
void dumpObjectTree() const
virtual void connectNotify(const QMetaMethod &signal)
void dumpObjectInfo() const
void moveToThread(QThread *thread)
static QMetaObject::Connection connect(const QObject *sender, const char *signal, const QObject *receiver, const char *member, Qt::ConnectionType=Qt::AutoConnection)
virtual void childEvent(QChildEvent *event)
QString objectName
the name of this object
virtual bool event(QEvent *event)
void setParent(QObject *parent)
virtual bool eventFilter(QObject *watched, QEvent *event)
static bool disconnect(const QObject *sender, const char *signal, const QObject *receiver, const char *member)
void removeEventFilter(QObject *obj)
virtual void timerEvent(QTimerEvent *event)
QScopedPointer< QObjectData > d_ptr
bool blockSignals(bool b) noexcept
QList< QByteArray > dynamicPropertyNames() const
int receivers(const char *signal) const
QVariant property(const char *name) const
void setObjectName(const QString &name)
bool setProperty(const char *name, const QVariant &value)
QBindable< QString > bindableObjectName()
void destroyed(QObject *=nullptr)
virtual void disconnectNotify(const QMetaMethod &signal)
virtual void customEvent(QEvent *event)
static QMetaObject::Connection connectImpl(const QObject *sender, int signal_index, const QObject *receiver, void **slot, QtPrivate::QSlotObjectBase *slotObj, int type, const int *types, const QMetaObject *senderMetaObject)
bool isSignalConnected(uint signalIdx, bool checkDeclarative=true) const
void ensureConnectionData()
void moveToThread_helper()
void checkForIncompatibleLibraryVersion(int version) const
QObjectPrivate(int version=QObjectPrivateVersion)
QAtomicPointer< ConnectionData > connections
static QMetaObject::Connection connect(const typename QtPrivate::FunctionPointer< Func1 >::Object *sender, Func1 signal, const typename QtPrivate::FunctionPointer< Func2 >::Object *receiverPrivate, Func2 slot, Qt::ConnectionType type=Qt::AutoConnection)
void(* StaticMetaCallFunction)(QObject *, QMetaObject::Call, int, void **)
void addConnection(int signal, Connection *c)
QObject * currentChildBeingDeleted
void clearBindingStorage()
QObjectList receiverList(const char *signal) const
virtual ~QObjectPrivate()
void setParent_helper(QObject *)
static bool disconnect(const typename QtPrivate::FunctionPointer< Func1 >::Object *sender, Func1 signal, const typename QtPrivate::FunctionPointer< Func2 >::Object *receiverPrivate, Func2 slot)
void disconnectNotify(const QMetaMethod &signal)
void setThreadData_helper(QThreadData *currentData, QThreadData *targetData)
void _q_reregisterTimers(void *pointer)
bool maybeSignalConnected(uint signalIndex) const
int signalIndex(const char *signalName, const QMetaObject **meta=nullptr) const
QObjectList senderList() const
static QObjectPrivate * get(QObject *o)
QAtomicPointer< QThreadData > threadData
bool isSender(const QObject *receiver, const char *signal) const
bool isDeclarativeSignalConnected(uint signalIdx) const
void addEvent(const QPostEvent &ev)
The QRegularExpression class provides pattern matching using regular expressions.
QRegularExpressionMatch match(const QString &subject, qsizetype offset=0, MatchType matchType=NormalMatch, MatchOptions matchOptions=NoMatchOption) const
The QRegularExpressionMatch class provides the results of a matching a QRegularExpression against a s...
The QSemaphore class provides a general counting semaphore.
The QString class provides a Unicode character string.
QByteArray toLatin1() const &
void store(const char *method)
static Q_AUTOTEST_EXPORT QThreadData * current(bool createIfNecessary=true)
QAtomicPointer< QAbstractEventDispatcher > eventDispatcher
static QThreadData * get2(QThread *thread)
QAtomicPointer< void > threadId
FlaggedDebugSignatures flaggedSignatures
QPostEventList postEventList
bool hasEventDispatcher() const
QAtomicPointer< QThread > thread
static Qt::HANDLE currentThreadId() noexcept Q_DECL_PURE_FUNCTION
static QThread * currentThread()
The QTimerEvent class contains parameters that describe a timer event.
constexpr size_type size() const noexcept
const T * constData() const
The QVariant class acts like a union for the most common Qt data types.
void destroyIfLastRef() noexcept
void(* AddQObjectCallback)(QObject *)
void(* RemoveQObjectCallback)(QObject *)
@ FindChildrenRecursively
@ BlockingQueuedConnection
bool isAnyBindingEvaluating()
set set set set set set set macro pixldst1 op
#define Q_BASIC_ATOMIC_INITIALIZER(a)
#define QByteArrayLiteral(str)
size_t qstrlen(const char *str)
int qstrncmp(const char *str1, const char *str2, size_t len)
#define Q_DECL_COLD_FUNCTION
DBusConnection * connection
DBusConnection const char DBusError DBusBusType DBusError return DBusConnection DBusHandleMessageFunction void DBusFreeFunction return DBusConnection return DBusConnection return const char DBusError return DBusConnection DBusMessage dbus_uint32_t return DBusConnection dbus_bool_t DBusConnection DBusAddWatchFunction DBusRemoveWatchFunction DBusWatchToggledFunction void DBusFreeFunction return DBusConnection DBusDispatchStatusFunction void DBusFreeFunction DBusTimeout return DBusTimeout return DBusWatch return DBusWatch unsigned int return DBusError const DBusError return const DBusMessage return DBusMessage return DBusMessage return DBusMessage return DBusMessage return DBusMessage return DBusMessageIter int const void return DBusMessageIter DBusMessageIter return DBusMessageIter void DBusMessageIter void int return DBusMessage DBusMessageIter return DBusMessageIter return DBusMessageIter DBusMessageIter const char const char const char const char * method
EGLOutputLayerEXT EGLint EGLAttrib value
#define Q_DISABLE_COPY_MOVE(Class)
QT_BEGIN_NAMESPACE quintptr Q_CORE_EXPORT qtHookData[]
#define Q_LOGGING_CATEGORY(name,...)
#define qCWarning(category,...)
#define qCDebug(category,...)
void qt_qFindChildren_helper(const QObject *parent, const QString &name, const QMetaObject &mo, QList< void * > *list, Qt::FindChildOptions options)
Q_CORE_EXPORT QBasicAtomicPointer< QSignalSpyCallbackSet > qt_signal_spy_callback_set
QDebug operator<<(QDebug dbg, const QObject *o)
void qDeleteInEventHandler(QObject *o)
const char * qFlagLocation(const char *method)
void doActivate(QObject *sender, int signal_index, void **argv)
void qt_register_signal_spy_callbacks(QSignalSpyCallbackSet *callback_set)
QObject * qt_qFindChild_helper(const QObject *parent, const QString &name, const QMetaObject &mo, Qt::FindChildOptions options)
#define Q_ARG(type, data)
GLenum GLuint GLenum GLsizei const GLchar * message
GLboolean GLboolean GLboolean b
GLsizei const GLfloat * v
[13]
GLuint64 GLenum void * handle
GLint GLenum GLsizei GLsizei GLsizei depth
GLenum GLuint GLint level
GLfloat GLfloat GLfloat w
[0]
GLboolean GLboolean GLboolean GLboolean a
[7]
GLsizei GLenum GLenum * types
GLenum GLenum GLsizei count
GLint GLsizei GLsizei GLenum GLenum GLsizei void * data
GLsizei GLenum GLsizei GLsizei GLuint memory
GLsizei const void * pointer
GLdouble GLdouble GLdouble GLdouble q
#define Q_ASSERT_X(cond, x, msg)
QScopeGuard< typename std::decay< F >::type > qScopeGuard(F &&f)
[qScopeGuard]
#define Q_HAS_TRACEPOINTS
#define Q_TRACE_SCOPE(x,...)
const char className[16]
[1]
QT_BEGIN_NAMESPACE void dumpRecursive(const QDir &dir, QTextStream &out)
Q_CHECK_PTR(a=new int[80])
QRandomGenerator64 rd
[10]
connect(quitButton, &QPushButton::clicked, &app, &QCoreApplication::quit, Qt::QueuedConnection)
qsizetype indexOf(const AT &t, qsizetype from=0) const noexcept
QAtomicInteger< uint > currentConnectionId
@ AlreadyLockedAndTemporarilyReleasingLock
QAtomicPointer< Connection > orphaned
int signalVectorCount() const
void removeConnection(Connection *c)
ConnectionList & connectionsForSignal(int signal)
void resizeSignalVector(uint size)
void cleanOrphanedConnections(QObject *sender, LockPolicy lockPolicy=NeedToLock)
static void deleteOrphaned(ConnectionOrSignalVector *c)
void cleanOrphanedConnectionsImpl(QObject *sender, LockPolicy lockPolicy)
QAtomicPointer< SignalVector > signalVector
QAtomicPointer< const int > argumentTypes
QAtomicPointer< Connection > nextConnectionList
QAtomicPointer< QObject > receiver
QtPrivate::QSlotObjectBase * slotObj
QAtomicPointer< Connection > last
QAtomicPointer< Connection > first
static SignalVector * asSignalVector(ConnectionOrSignalVector *c)
ConnectionList & at(int i)
BeginCallback slot_begin_callback
EndCallback slot_end_callback
EndCallback signal_end_callback
BeginCallback signal_begin_callback
QBasicAtomicInt strongref
QtPrivate::QSlotObjectBase const * operator->() const
QtPrivate::QSlotObjectBase * operator->()
SlotObjectGuard()=default
QThreadStorage< int * > dummy[8]
IUIAutomationTreeWalker __RPC__deref_out_opt IUIAutomationElement ** parent