当前位置:网站首页>Qt源码分析--QObject(2)
Qt源码分析--QObject(2)
2022-06-24 07:01:00 【天天进步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;
}
//把signal从字符转成整型数
static int extract_code(const char *member)
{
// extract code, ensure QMETHOD_CODE <= code <= QSIGNAL_CODE
return (((int)(*member) - '0') & 0x3);
}
//解析signal签名
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);
}
//返回signal的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;
}
//如果 local_method_index 是克隆方法,则返回原始方法的索引。
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;
}
//如果 signalTypes 和 methodTypes 是兼容的,则返回true
; 否则返回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()函数检查signal是不是信号。
整个流程如下:
1.先检查输入参数是否正确
2.然后遍历slots函数,检查是否存在。
3.最后生成一个connection返回。
边栏推荐
- WPS的JS宏实现图片正文在同一段落的分离方法
- Use cpulimit to free up your CPU
- 【毕业季】你好陌生人,这是一封粉色信笺
- 问题4 — DatePicker日期选择器,2个日期选择器(开始、结束日期)的禁用
- ZUCC_编译语言原理与编译_实验08 语法分析 LR 分析
- [graduation season] Hello stranger, this is a pink letter
- 【关于运维和网工的差别,一文说透】
- 2022年制冷与空调设备运行操作上岗证题库及模拟考试
- 中国芯片独角兽公司
- Easydss anonymous live channel data volume instability optimization scheme sharing
猜你喜欢
io模型初探
成为IEEE学生会员
5 minutes, excellent customer service chat handling skills
中国芯片独角兽公司
LabVIEW finds prime numbers in an array of n elements
2022年流动式起重机司机特种作业证考试题库及在线模拟考试
Longhorn installation and use
【关于运维和网工的差别,一文说透】
12--合并两个有序链表
New technology practice, encapsulating the permission application library step by step with the activity results API
随机推荐
How to implement approval function in Tekton
OpenCV get(propId) 常用的值
Easydss anonymous live channel data volume instability optimization scheme sharing
Paper notes: multi label learning dm2l
Catégorie de prêt 5
WPS的JS宏实现图片正文在同一段落的分离方法
Question 4 - datepicker date selector, disabling two date selectors (start and end dates)
11-- longest substring without repeated characters
根据网络上的视频的m3u8文件通过ffmpeg进行合成视频
Ordinary token
WCF TCP protocol transmission
Building a static website with eleventy
ZUCC_编译语言原理与编译_实验01 语言分析与简介
Nodejs redlock notes
【关于运维和网工的差别,一文说透】
2022 mobile crane driver special operation certificate examination question bank and online simulation examination
13 -- remove invalid parentheses
PAT 1157:校庆
ZUCC_编译语言原理与编译_实验03 编译器入门
How to configure networkpolicy for nodeport in kubernetes