当前位置:网站首页>QT source code analysis -- QObject (2)
QT source code analysis -- QObject (2)
2022-06-24 08:42:00 【Progress every day 2015】
1.boolblockSignals(bool b) noexcept;
bool QObject::blockSignals(bool block) noexcept
{
Q_D(QObject);
bool previous = d->blockSig;
d->blockSig = block;
return previous;
}2.children()
inline const QObjectList &children() const { return d_ptr->children; }
3.staticQMetaObject::Connectionconnect(constQObject *sender, constchar *signal,constQObject *receiver, constchar *member, Qt::ConnectionType = Qt::AutoConnection);
QMetaObject::Connection QObject::connect(const QObject *sender, const char *signal,
const QObject *receiver, const char *method,
Qt::ConnectionType type)
{
if (sender == 0 || receiver == 0 || signal == 0 || method == 0) {
qWarning("QObject::connect: Cannot connect %s::%s to %s::%s",
sender ? sender->metaObject()->className() : "(null)",
(signal && *signal) ? signal+1 : "(null)",
receiver ? receiver->metaObject()->className() : "(null)",
(method && *method) ? method+1 : "(null)");
return QMetaObject::Connection(0);
}
QByteArray tmp_signal_name;
if (!check_signal_macro(sender, signal, "connect", "bind"))
return QMetaObject::Connection(0);
const QMetaObject *smeta = sender->metaObject();
const char *signal_arg = signal;
++signal; //skip code
QArgumentTypeArray signalTypes;
Q_ASSERT(QMetaObjectPrivate::get(smeta)->revision >= 7);
QByteArray signalName = QMetaObjectPrivate::decodeMethodSignature(signal, signalTypes);
int signal_index = QMetaObjectPrivate::indexOfSignalRelative(
&smeta, signalName, signalTypes.size(), signalTypes.constData());
if (signal_index < 0) {
// check for normalized signatures
tmp_signal_name = QMetaObject::normalizedSignature(signal - 1);
signal = tmp_signal_name.constData() + 1;
signalTypes.clear();
signalName = QMetaObjectPrivate::decodeMethodSignature(signal, signalTypes);
smeta = sender->metaObject();
signal_index = QMetaObjectPrivate::indexOfSignalRelative(
&smeta, signalName, signalTypes.size(), signalTypes.constData());
}
if (signal_index < 0) {
err_method_notfound(sender, signal_arg, "connect");
err_info_about_objects("connect", sender, receiver);
return QMetaObject::Connection(0);
}
signal_index = QMetaObjectPrivate::originalClone(smeta, signal_index);
signal_index += QMetaObjectPrivate::signalOffset(smeta);
QByteArray tmp_method_name;
int membcode = extract_code(method);
if (!check_method_code(membcode, receiver, method, "connect"))
return QMetaObject::Connection(0);
const char *method_arg = method;
++method; // skip code
QArgumentTypeArray methodTypes;
QByteArray methodName = QMetaObjectPrivate::decodeMethodSignature(method, methodTypes);
const QMetaObject *rmeta = receiver->metaObject();
int method_index_relative = -1;
Q_ASSERT(QMetaObjectPrivate::get(rmeta)->revision >= 7);
switch (membcode) {
case QSLOT_CODE:
method_index_relative = QMetaObjectPrivate::indexOfSlotRelative(
&rmeta, methodName, methodTypes.size(), methodTypes.constData());
break;
case QSIGNAL_CODE:
method_index_relative = QMetaObjectPrivate::indexOfSignalRelative(
&rmeta, methodName, methodTypes.size(), methodTypes.constData());
break;
}
if (method_index_relative < 0) {
// check for normalized methods
tmp_method_name = QMetaObject::normalizedSignature(method);
method = tmp_method_name.constData();
methodTypes.clear();
methodName = QMetaObjectPrivate::decodeMethodSignature(method, methodTypes);
// rmeta may have been modified above
rmeta = receiver->metaObject();
switch (membcode) {
case QSLOT_CODE:
method_index_relative = QMetaObjectPrivate::indexOfSlotRelative(
&rmeta, methodName, methodTypes.size(), methodTypes.constData());
break;
case QSIGNAL_CODE:
method_index_relative = QMetaObjectPrivate::indexOfSignalRelative(
&rmeta, methodName, methodTypes.size(), methodTypes.constData());
break;
}
}
if (method_index_relative < 0) {
err_method_notfound(receiver, method_arg, "connect");
err_info_about_objects("connect", sender, receiver);
return QMetaObject::Connection(0);
}
if (!QMetaObjectPrivate::checkConnectArgs(signalTypes.size(), signalTypes.constData(),
methodTypes.size(), methodTypes.constData())) {
qWarning("QObject::connect: Incompatible sender/receiver arguments"
"\n %s::%s --> %s::%s",
sender->metaObject()->className(), signal,
receiver->metaObject()->className(), method);
return QMetaObject::Connection(0);
}
int *types = 0;
if ((type == Qt::QueuedConnection)
&& !(types = queuedConnectionTypes(signalTypes.constData(), signalTypes.size()))) {
return QMetaObject::Connection(0);
}
#ifndef QT_NO_DEBUG
QMetaMethod smethod = QMetaObjectPrivate::signal(smeta, signal_index);
QMetaMethod rmethod = rmeta->method(method_index_relative + rmeta->methodOffset());
check_and_warn_compat(smeta, smethod, rmeta, rmethod);
#endif
QMetaObject::Connection handle = QMetaObject::Connection(QMetaObjectPrivate::connect(
sender, signal_index, smeta, receiver, method_index_relative, rmeta ,type, types));
return handle;
}
static bool check_signal_macro(const QObject *sender, const char *signal,
const char *func, const char *op)
{
int sigcode = extract_code(signal);
if (sigcode != QSIGNAL_CODE) {
if (sigcode == QSLOT_CODE)
qWarning("QObject::%s: Attempt to %s non-signal %s::%s",
func, op, sender->metaObject()->className(), signal+1);
else
qWarning("QObject::%s: Use the SIGNAL macro to %s %s::%s",
func, op, sender->metaObject()->className(), signal);
return false;
}
return true;
}
// hold signal From character to integer
static int extract_code(const char *member)
{
// extract code, ensure QMETHOD_CODE <= code <= QSIGNAL_CODE
return (((int)(*member) - '0') & 0x3);
}
// analysis signal Signature
QByteArray QMetaObjectPrivate::decodeMethodSignature(
const char *signature, QArgumentTypeArray &types)
{
Q_ASSERT(signature != 0);
const char *lparens = strchr(signature, '(');
if (!lparens)
return QByteArray();
const char *rparens = strrchr(lparens + 1, ')');
if (!rparens || *(rparens+1))
return QByteArray();
int nameLength = lparens - signature;
argumentTypesFromString(lparens + 1, rparens, types);
return QByteArray::fromRawData(signature, nameLength);
}
// return signal Of index
int QMetaObjectPrivate::indexOfSignalRelative(const QMetaObject **baseObject,
const QByteArray &name, int argc,
const QArgumentType *types)
{
int i = indexOfMethodRelative<MethodSignal>(baseObject, name, argc, types);
#ifndef QT_NO_DEBUG
const QMetaObject *m = *baseObject;
if (i >= 0 && m && m->d.superdata) {
int conflict = indexOfMethod(m->d.superdata, name, argc, types);
if (conflict >= 0) {
QMetaMethod conflictMethod = m->d.superdata->method(conflict);
qWarning("QMetaObject::indexOfSignal: signal %s from %s redefined in %s",
conflictMethod.methodSignature().constData(),
objectClassName(m->d.superdata), objectClassName(m));
}
}
#endif
return i;
}
// If local_method_index Is a cloning method , Returns the index of the original method .
int QMetaObjectPrivate::originalClone(const QMetaObject *mobj, int local_method_index)
{
Q_ASSERT(local_method_index < get(mobj)->methodCount);
int handle = get(mobj)->methodData + 5 * local_method_index;
while (mobj->d.data[handle + 4] & MethodCloned) {
Q_ASSERT(local_method_index > 0);
handle -= 5;
local_method_index--;
}
return local_method_index;
}
int QMetaObjectPrivate::signalOffset(const QMetaObject *m)
{
Q_ASSERT(m != 0);
int offset = 0;
for (m = m->d.superdata; m; m = m->d.superdata)
offset += priv(m->d.data)->signalCount;
return offset;
}
static int extract_code(const char *member)
{
// extract code, ensure QMETHOD_CODE <= code <= QSIGNAL_CODE
return (((int)(*member) - '0') & 0x3);
}
static bool check_method_code(int code, const QObject *object,
const char *method, const char *func)
{
if (code != QSLOT_CODE && code != QSIGNAL_CODE) {
qWarning("QObject::%s: Use the SLOT or SIGNAL macro to "
"%s %s::%s", func, func, object->metaObject()->className(), method);
return false;
}
return true;
}
// If signalTypes and methodTypes Is compatible , Then return to true
; Otherwise return to false
bool QMetaObjectPrivate::checkConnectArgs(int signalArgc, const QArgumentType *signalTypes,
int methodArgc, const QArgumentType *methodTypes)
{
if (signalArgc < methodArgc)
return false;
for (int i = 0; i < methodArgc; ++i) {
if (signalTypes[i] != methodTypes[i])
return false;
}
return true;
}
static int *queuedConnectionTypes(const QArgumentType *argumentTypes, int argc)
{
QScopedArrayPointer<int> types(new int [argc + 1]);
for (int i = 0; i < argc; ++i) {
const QArgumentType &type = argumentTypes[i];
if (type.type())
types[i] = type.type();
else if (type.name().endsWith('*'))
types[i] = QMetaType::VoidStar;
else
types[i] = QMetaType::type(type.name());
if (!types[i]) {
qWarning("QObject::connect: Cannot queue arguments of type '%s'\n"
"(Make sure '%s' is registered using qRegisterMetaType().)",
type.name().constData(), type.name().constData());
return 0;
}
}
types[argc] = 0;
return types.take();
}
QObjectPrivate::Connection *QMetaObjectPrivate::connect(const QObject *sender,
int signal_index, const QMetaObject *smeta,
const QObject *receiver, int method_index,
const QMetaObject *rmeta, int type, int *types)
{
QObject *s = const_cast<QObject *>(sender);
QObject *r = const_cast<QObject *>(receiver);
int method_offset = rmeta ? rmeta->methodOffset() : 0;
Q_ASSERT(!rmeta || QMetaObjectPrivate::get(rmeta)->revision >= 6);
QObjectPrivate::StaticMetaCallFunction callFunction = rmeta ? rmeta->d.static_metacall : nullptr;
QOrderedMutexLocker locker(signalSlotLock(sender),
signalSlotLock(receiver));
QObjectPrivate::ConnectionData *scd = QObjectPrivate::get(s)->connections.loadRelaxed();
if (type & Qt::UniqueConnection && scd) {
if (scd->signalVectorCount() > signal_index) {
const QObjectPrivate::Connection *c2 = scd->signalVector.loadRelaxed()->at(signal_index).first.loadRelaxed();
int method_index_absolute = method_index + method_offset;
while (c2) {
if (!c2->isSlotObject && c2->receiver.loadRelaxed() == receiver && c2->method() == method_index_absolute)
return nullptr;
c2 = c2->nextConnectionList.loadRelaxed();
}
}
type &= Qt::UniqueConnection - 1;
}
std::unique_ptr<QObjectPrivate::Connection> c{new QObjectPrivate::Connection};
c->sender = s;
c->signal_index = signal_index;
c->receiver.storeRelaxed(r);
QThreadData *td = r->d_func()->threadData;
td->ref();
c->receiverThreadData.storeRelaxed(td);
c->method_relative = method_index;
c->method_offset = method_offset;
c->connectionType = type;
c->isSlotObject = false;
c->argumentTypes.storeRelaxed(types);
c->callFunction = callFunction;
QObjectPrivate::get(s)->addConnection(signal_index, c.get());
locker.unlock();
QMetaMethod smethod = QMetaObjectPrivate::signal(smeta, signal_index);
if (smethod.isValid())
s->connectNotify(smethod);
return c.release();
}check_signal_macro() Function check signal Is it a signal .
The whole process is as follows :
1. First, check whether the input parameters are correct
2. Then traverse slots function , Check for presence .
3. And then finally generate a connection return .
边栏推荐
- One development skill a day: how to establish P2P communication based on webrtc?
- 更改SSH端口号
- [xinliu-s6 new model +sa 3-star Xinghai] the new two-way server of the third generation chip was launched and the product was updated~
- Video Fusion communication has become an inevitable trend of emergency command communication. How to realize it based on easyrtc?
- pymysql 向MySQL 插入数据无故报错
- 图片工具
- ZUCC_编译语言原理与编译_大作业
- 【力扣10天SQL入门】Day3
- The JS macro of WPS implements the separation method of picture text in the same paragraph
- Fund raising, trading and registration
猜你喜欢
随机推荐
Send custom events in QT
(pkcs1) RSA public private key PEM file parsing
什么是SRE?一文详解SRE运维体系
Introduction to data platform
os. path. Pits encountered during the use of join()
jwt(json web token)
PHP代码加密的几种方案
Glusterfs replacement failure brick
App Startup
liunx服务器 telnet 带用户名 端口登陆方法
After interviewing and tutoring several children, I found some problems!
Fundamentals of 3D mathematics [17] inverse square theorem
orb slam build bug: undefined reference to symbol ‘_ZN5boost6system15system_categoryEv‘
相机投影矩阵计算
rsync做文件备份
一文详解|增长那些事儿
2021-06-25: a batch of strings consisting only of lowercase letters (a~z) are put
[life thinking] planning and self-discipline
RuntimeError: Missing dependencies:XXX
成为IEEE学生会员









