当前位置:网站首页>QT source code analysis -- QObject (4)
QT source code analysis -- QObject (4)
2022-07-29 02:09:00 【Progress every day 2015】
Catalog
1.staticbooldisconnect(constQObject *sender, constchar *signal,constQObject *receiver, constchar *member);
bool QObject::disconnect(const QObject *sender, const char *signal,
const QObject *receiver, const char *method)
{
if (sender == 0 || (receiver == 0 && method != 0)) {
qWarning("QObject::disconnect: Unexpected null parameter");
return false;
}
const char *signal_arg = signal;
QByteArray signal_name;
bool signal_found = false;
if (signal) {
QT_TRY {
signal_name = QMetaObject::normalizedSignature(signal);
signal = signal_name.constData();
} QT_CATCH (const std::bad_alloc &) {
// if the signal is already normalized, we can continue.
if (sender->metaObject()->indexOfSignal(signal + 1) == -1)
QT_RETHROW;
}
if (!check_signal_macro(sender, signal, "disconnect", "unbind"))
return false;
signal++; // skip code
}
QByteArray method_name;
const char *method_arg = method;
int membcode = -1;
bool method_found = false;
if (method) {
QT_TRY {
method_name = QMetaObject::normalizedSignature(method);
method = method_name.constData();
} QT_CATCH(const std::bad_alloc &) {
// if the method is already normalized, we can continue.
if (receiver->metaObject()->indexOfMethod(method + 1) == -1)
QT_RETHROW;
}
membcode = extract_code(method);
if (!check_method_code(membcode, receiver, method, "disconnect"))
return false;
method++; // skip code
}
/* We now iterate through all the sender's and receiver's meta
* objects in order to also disconnect possibly shadowed signals
* and slots with the same signature.
*/
bool res = false;
const QMetaObject *smeta = sender->metaObject();
QByteArray signalName;
QArgumentTypeArray signalTypes;
Q_ASSERT(QMetaObjectPrivate::get(smeta)->revision >= 7);
if (signal)
signalName = QMetaObjectPrivate::decodeMethodSignature(signal, signalTypes);
QByteArray methodName;
QArgumentTypeArray methodTypes;
Q_ASSERT(!receiver || QMetaObjectPrivate::get(receiver->metaObject())->revision >= 7);
if (method)
methodName = QMetaObjectPrivate::decodeMethodSignature(method, methodTypes);
do {
int signal_index = -1;
if (signal) {
signal_index = QMetaObjectPrivate::indexOfSignalRelative(
&smeta, signalName, signalTypes.size(), signalTypes.constData());
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, 0);
} else {
const QMetaObject *rmeta = receiver->metaObject();
do {
int method_index = QMetaObjectPrivate::indexOfMethod(
rmeta, methodName, methodTypes.size(), methodTypes.constData());
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, 0);
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());
}
return res;
}Disconnect the signal in the object sender from the method in the object receiver . If Connecton Successfully disconnected , Then return to true; Otherwise return to false.
When any object involved is destroyed , Will delete the signal slot connection .
disconnect() It is usually used in three ways , This is shown in the following example .
1. Disconnect everything connected to the object signal :
disconnect(myObject, nullptr, nullptr, nullptr);Equate to
myObject->disconnect();2. Disconnect everything connected to a particular signal
disconnect(myObject, SIGNAL(mySignal()), nullptr, nullptr);Equate to
myObject->disconnect(SIGNAL(mySignal()));3. Disconnect the specific receiver
disconnect(myObject, nullptr, myReceiver, nullptr);Equate to
myObject->disconnect(myReceiver);Let's analyze the code :
if (signal) {
QT_TRY {
signal_name = QMetaObject::normalizedSignature(signal);
signal = signal_name.constData();
} QT_CATCH (const std::bad_alloc &) {
// if the signal is already normalized, we can continue.
if (sender->metaObject()->indexOfSignal(signal + 1) == -1)
QT_RETHROW;
}
if (!check_signal_macro(sender, signal, "disconnect", "unbind"))
return false;
signal++; // skip code
}If parameters signal Not empty , Then get signal The name of .
QByteArray method_name;
const char *method_arg = method;
int membcode = -1;
bool method_found = false;
if (method) {
QT_TRY {
method_name = QMetaObject::normalizedSignature(method);
method = method_name.constData();
} QT_CATCH(const std::bad_alloc &) {
// if the method is already normalized, we can continue.
if (receiver->metaObject()->indexOfMethod(method + 1) == -1)
QT_RETHROW;
}
membcode = extract_code(method);
if (!check_method_code(membcode, receiver, method, "disconnect"))
return false;
method++; // skip code
}If parameters method Not empty , Then get method The name of .
Next , Traversal search sender and receiver Of meta objects.
do {
int signal_index = -1;
if (signal) {
signal_index = QMetaObjectPrivate::indexOfSignalRelative(
&smeta, signalName, signalTypes.size(), signalTypes.constData());
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, 0);
} else {
const QMetaObject *rmeta = receiver->metaObject();
do {
int method_index = QMetaObjectPrivate::indexOfMethod(
rmeta, methodName, methodTypes.size(), methodTypes.constData());
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, 0);
method_found = true;
} while ((rmeta = rmeta->superClass()));
}
} while (signal && (smeta = smeta->superClass()));call QMetaObjectPrivate::disconnect
bool QMetaObjectPrivate::disconnect(const QObject *sender,
int signal_index, const QMetaObject *smeta,
const QObject *receiver, int method_index, void **slot,
DisconnectType disconnectType)
{
if (!sender)
return false;
QObject *s = const_cast<QObject *>(sender);
QBasicMutex *senderMutex = signalSlotLock(sender);
QBasicMutexLocker locker(senderMutex);
QObjectPrivate::ConnectionData *scd = QObjectPrivate::get(s)->connections.loadRelaxed();
if (!scd)
return false;
bool success = false;
{
// prevent incoming connections changing the connections->receivers while unlocked
QObjectPrivate::ConnectionDataPointer connections(scd);
if (signal_index < 0) {
// remove from all connection lists
for (int sig_index = -1; sig_index < scd->signalVectorCount(); ++sig_index) {
if (disconnectHelper(connections.data(), sig_index, receiver, method_index, slot, senderMutex, disconnectType))
success = true;
}
} else if (signal_index < scd->signalVectorCount()) {
if (disconnectHelper(connections.data(), signal_index, receiver, method_index, slot, senderMutex, disconnectType))
success = true;
}
}
locker.unlock();
if (success) {
scd->cleanOrphanedConnections(s);
QMetaMethod smethod = QMetaObjectPrivate::signal(smeta, signal_index);
if (smethod.isValid())
s->disconnectNotify(smethod);
}
return success;
}First , obtain ConnectionData *scd.
after , according to scd Remove the corresponding connections.
From function QMetaObjectPrivate::disconnect return , The return value is stored in res.
If signal perhaps method Did not find , Then the prompt is wrong .
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 The value of is true, call sender Of disconnectNotify function .
2.dumpObjectInfo()
Dump the signal connection and other information about this object for debugging output .
void QObject::dumpObjectInfo()
{
const_cast<const QObject *>(this)->dumpObjectInfo();
}void QObject::dumpObjectInfo() const
{
qDebug("OBJECT %s::%s", metaObject()->className(),
objectName().isEmpty() ? "unnamed" : objectName().toLocal8Bit().data());
Q_D(const QObject);
QBasicMutexLocker locker(signalSlotLock(this));
// first, look for connections where this object is the sender
qDebug(" SIGNALS OUT");
QObjectPrivate::ConnectionData *cd = d->connections.loadRelaxed();
if (cd && cd->signalVectorCount()) {
QObjectPrivate::SignalVector *signalVector = cd->signalVector.loadRelaxed();
for (int signal_index = 0; signal_index < signalVector->count(); ++signal_index) {
const QObjectPrivate::Connection *c = signalVector->at(signal_index).first.loadRelaxed();
if (!c)
continue;
const QMetaMethod signal = QMetaObjectPrivate::signal(metaObject(), signal_index);
qDebug(" signal: %s", signal.methodSignature().constData());
// receivers
while (c) {
if (!c->receiver.loadRelaxed()) {
qDebug(" <Disconnected receiver>");
c = c->nextConnectionList.loadRelaxed();
continue;
}
if (c->isSlotObject) {
qDebug(" <functor or function pointer>");
c = c->nextConnectionList.loadRelaxed();
continue;
}
const QMetaObject *receiverMetaObject = c->receiver.loadRelaxed()->metaObject();
const QMetaMethod method = receiverMetaObject->method(c->method());
qDebug(" --> %s::%s %s",
receiverMetaObject->className(),
c->receiver.loadRelaxed()->objectName().isEmpty() ? "unnamed" : qPrintable(c->receiver.loadRelaxed()->objectName()),
method.methodSignature().constData());
c = c->nextConnectionList.loadRelaxed();
}
}
} else {
qDebug( " <None>" );
}
// now look for connections where this object is the receiver
qDebug(" SIGNALS IN");
if (cd && cd->senders) {
for (QObjectPrivate::Connection *s = cd->senders; s; s = s->next) {
QByteArray slotName = QByteArrayLiteral("<unknown>");
if (!s->isSlotObject) {
const QMetaMethod slot = metaObject()->method(s->method());
slotName = slot.methodSignature();
}
qDebug(" <-- %s::%s %s",
s->sender->metaObject()->className(),
s->sender->objectName().isEmpty() ? "unnamed" : qPrintable(s->sender->objectName()),
slotName.constData());
}
} else {
qDebug(" <None>");
}
}First , Looking for this object is the sender's connection
then , Find the connection where this object is the recipient
3.dumpObjectTree()
Dump the subtree to the debug output .
void QObject::dumpObjectTree()
{
const_cast<const QObject *>(this)->dumpObjectTree();
}/*!
Dumps a tree of children to the debug output.
\note before Qt 5.9, this function was not const.
\sa dumpObjectInfo()
*/
void QObject::dumpObjectTree() const
{
dumpRecursive(0, this);
}
static void dumpRecursive(int level, const QObject *object)
{
if (object) {
QByteArray buf;
buf.fill(' ', level / 2 * 8);
if (level % 2)
buf += " ";
QString name = object->objectName();
QString flags = QLatin1String("");
#if 0
if (qApp->focusWidget() == object)
flags += 'F';
if (object->isWidgetType()) {
QWidget * w = (QWidget *)object;
if (w->isVisible()) {
QString t("<%1,%2,%3,%4>");
flags += t.arg(w->x()).arg(w->y()).arg(w->width()).arg(w->height());
} else {
flags += 'I';
}
}
#endif
qDebug("%s%s::%s %s", (const char*)buf, object->metaObject()->className(), name.toLocal8Bit().data(),
flags.toLatin1().data());
QObjectList children = object->children();
if (!children.isEmpty()) {
for (int i = 0; i < children.size(); ++i)
dumpRecursive(level+1, children.at(i));
}
}
}
Recursive output object Of meta Information .
Indentation uses a technique :
QByteArray buf;
buf.fill(' ', level / 2 * 8);
if (level % 2)
buf += " ";according to level Hierarchy , Calculate indent size .
边栏推荐
- h5背景音乐通过触摸自动播放
- Nine days later, we are together to focus on the new development of audio and video and mystery technology
- Comprehensive explanation of "search engine crawl"
- LeetCode 练习——剑指 Offer 45. 把数组排成最小的数
- 在Qt中如何编写插件,加载插件和卸载插件
- Dynamic memory and smart pointer
- What is browser fingerprint recognition
- [the road of Exile - Chapter 2]
- (CVPR-2019)选择性的内核网络
- [UE4] replay game playback for ue4.26
猜你喜欢

druid. io index_ Realtime real-time query

(CVPR-2019)选择性的内核网络

12.< tag-动态规划和子序列, 子数组>lt.72. 编辑距离

Use POI to export excel file, image URL to export file, image and excel file to export compressed package

Verilog procedure assignment statements: blocking & non blocking

MySQL安装常见报错处理大全

What is browser fingerprint recognition

Mathematical modeling -- cold proof simulation of low temperature protective clothing with phase change materials

Mathematical modeling -- bus scheduling optimization
![[public class preview]: application exploration of Kwai gpu/fpga/asic heterogeneous platform](/img/e7/1d06eba0e50eeb91d2d5da7524f4af.png)
[public class preview]: application exploration of Kwai gpu/fpga/asic heterogeneous platform
随机推荐
Comprehensive explanation of "search engine crawl"
Use POI to export excel file, image URL to export file, image and excel file to export compressed package
[7.21-26] code source - [good sequence] [social circle] [namonamo]
Sigma-DSP-OUTPUT
Day01 job
What is a proxy server? [2022 guide]
Mysql存储json格式数据
Why does stonedb dare to call it the only open source MySQL native HTAP database in the industry?
Wonderful use of data analysis
【流放之路-第六章】
试着换个角度理解低代码平台设计的本质
Mathematical modeling -- red wine quality classification
iVX低代码平台系列详解 -- 概述篇(二)
Leetcode exercise - Sword finger offer 45. arrange the array into the smallest number
ciscn 2022 华中赛区 misc
Introduction to shared data center agent
Cookie和Session
数学建模——派出所选址
给LaTeX公式添加优美的注解;日更『数据科学』面试题集锦;大学生『计算机』自学指南;个人防火墙;前沿资料/论文 | ShowMeAI资讯日报
Comprehensive use method of C treeview control