(1)类 QObject 的简化源代码定义,删除了还没学到的:
class Q_CORE_EXPORT QObject
{
public: //Q_OBJECT 直接展开此宏定义得到此函数
static const QMetaObject staticMetaObject;
virtual const QMetaObject * metaObject() const;
Q_PROPERTY(QString objectName //定义了 objectName 属性
READ objectName
WRITE setObjectName
NOTIFY objectNameChanged
BINDABLE bindableObjectName)
QString objectName() const; //返回的是类生成的对象名
//const char * QMetaObject::className() const; 返回的是类名
void setObjectName(const QString &name);
Q_INVOKABLE explicit QObject(QObject * parent = nullptr);
virtual ~QObject();
template<typename T> //查找容器中孩子
inline T findChild(const QString & aName = QString(), //定义略
Qt::FindChildOptions options = Qt::FindChildrenRecursively) const { }
template<typename T>
inline QList<T> findChildren(const QString &aName = QString(),
Qt::FindChildOptions options = Qt::FindChildrenRecursively) const
{ QList<T> list; return list; }
#if QT_CONFIG(regularexpression)
template<typename T> //
inline QList<T> findChildren(const QRegularExpression & re,
Qt::FindChildOptions options = Qt::FindChildrenRecursively) const
{ QList<T> list; return list; }
#endif // QT_CONFIG(regularexpression)
//typedef QList<QObject *> QObjectList;
inline const QObjectList & children() const { return d_ptr->children; }
void setParent(QObject * parent); //此函数定义在这里,加入容器
static QMetaObject::Connection connect(
const QObject * sender , const char * signal,
const QObject * receiver, const char * member,
Qt::ConnectionType = Qt::AutoConnection);
static QMetaObject::Connection connect( //这俩是类的静态成员函数
const QObject * sender , const QMetaMethod & signal,
const QObject * receiver, const QMetaMethod & method,
Qt::ConnectionType type = Qt::AutoConnection);
inline QMetaObject::Connection connect( //基于对象的动态成员函数
const QObject * sender, const char * signal,
const char * member,
Qt::ConnectionType type = Qt::AutoConnection) const;
static bool disconnect( //解除信号与槽的静态成员函数
const QObject * sender , const char * signal,
const QObject * receiver, const char * member);
static bool disconnect(
const QObject * sender , const QMetaMethod &signal,
const QObject * receiver, const QMetaMethod &member);
inline bool disconnect( //动态函数默认由信号发送者调用
const char * signal = nullptr,
const QObject *receiver = nullptr,
const char * member = nullptr) const
{ return disconnect(this, signal, receiver, member); }
inline bool disconnect(
const QObject * receiver,
const char * member = nullptr) const
{ return disconnect(this, nullptr, receiver, member); }
static bool disconnect(const QMetaObject::Connection &);
void dumpObjectTree() const;
void dumpObjectInfo() const;
#ifndef QT_NO_PROPERTIES //这里出现了动态属性设置
bool setProperty (const char * name, const QVariant &value);
QVariant property(const char * name) const; //根据属性名获取属性值,形参是字符串
//作为对比 QMetaProperty QMetaObject::property(int index) const;
//根据属性索引返回值属性对象 QMetaProperty对象,形参是数字索引
QList<QByteArray> dynamicPropertyNames() const;
QBindingStorage *bindingStorage() { return &d_ptr->bindingStorage; }
const QBindingStorage *bindingStorage() const { return &d_ptr->bindingStorage; }
#endif // QT_NO_PROPERTIES
Q_SIGNALS:
void destroyed(QObject * = nullptr); //信号函数不需要实现
void objectNameChanged(const QString &objectName, QPrivateSignal);
public: //显示本对象所在的容器,或者说返回容器父类
inline QObject * parent() const { return d_ptr->parent; }
//而 QMetaObject :: superClass() 则返回继承父类
//用于判断本对象是否是形参类及其子类的实现
inline bool inherits(const char * classname) const
{ return const_cast<QObject *>(this)->qt_metacast(classname) != nullptr; }
//bool QMetaObject :: inherits(const QMetaObject * metaObject) 用于判断类的继承关系
public Q_SLOTS:
void deleteLater();
protected:
QObject * sender() const; //判断信号的发送者
int senderSignalIndex() const;
int receivers(const char *signal) const;
bool isSignalConnected(const QMetaMethod &signal) const;
protected:
QObject(QObjectPrivate &dd, QObject *parent = nullptr);
protected: //定义了本类的数据成员
QScopedPointer<QObjectData> d_ptr;
friend struct QMetaObject; //定义本类的友元类,不止一个,略
private:
Q_DISABLE_COPY(QObject) //禁止对本类的复制操作
Q_PRIVATE_SLOT(d_func(), void _q_reregisterTimers(void *))
};
(2)类 QMetaObject 的源码简化版,删除了没学到的,与用不上的,重在快速查找到常用的成员函数并确认其功能:
struct Q_CORE_EXPORT QMetaObject
{
class Connection;
//QString QObject::objectName() const; 返回值不一样
const char * className() const;
const QMetaObject * superClass() const; //返回继承父类
//而 QObject :: parent() 则返回容器父类,用于内存管理
bool inherits(const QMetaObject *metaObject) const noexcept;
//判断本类是否继承于形参类。
//而 QObject::inherits(const char *)用于判断本对象是否是形参类及其子类的实现
QObject * cast(QObject *obj) const //用于类型转换,类似于 C++的 dynamic_cast
{ return const_cast<QObject *>(cast(const_cast<const QObject *>(obj))); }
const QObject *cast(const QObject * obj) const; //常量版本
//功能一样的更好版本是全局模板函数 T * qobject_cast<T *>(A * ptrA)
QMetaType metaType() const; //获取类型的元类型信息
//bool QObject::setProperty (const char * name, const QVariant & value);作为对比
//QVariant QObject::property(const char * name) const; //根据属性名获取属性值,形参是字符串
int propertyOffset () const;//返回此类的属性偏移量;即此类的第一个属性的索引位置。
//偏移量是该类的所有基类中所有属性的总和(由于Q0bject具有name()属性,因此总是正数)
int propertyCount () const;//返回该类中属性的数量,包括每个基类提供的属性的数量。
int indexOfProperty(const char * name) const;//返回具有此名的属性的索引,找不到返-1
//indexOfProperty 的索引基址是 0,搜索范围包括当前类及其所有基类的属性。
QMetaProperty property(int index) const;//返回具有此索引的属性 QMetaProperty对象
int classInfoOffset() const;//返回此类的第一个类信息项的偏移量,即索引位置。
//如果类中没有具有类信息的基类,则偏移量为 0;否则,偏移量为类中所有基类中类信息项的总和。
int classInfoCount () const;//返回的是当前类及其所有基类的类信息总数。
int indexOfClassInfo(const char *name) const;//找不到则返-1
//根据类信息名称返回其在元对象中的类信息索引
//indexOfClassInfo 的索引基址是 0,搜索范围包括当前类及其所有基类的类信息。
QMetaClassInfo classInfo(int index) const; //根据索引返回类信息
// internal index-based connect 内部的基于索引的信号连接,形参有很大区别
static Connection connect(const QObject *sender, int signal_index,
const QObject *receiver, int method_index,
int type = 0, int *types = nullptr);
// internal index-based disconnect j
static bool disconnect(const QObject *sender, int signal_index,
const QObject *receiver, int method_index);
// internal slot-name based connect
static void connectSlotsByName(QObject *o);
// 使用形式,在窗体的构造函数里这样用 QMetaObject::connectSlotsByName(Widget);
// internal index-based signal activation 内部用的函数
static void activate(QObject *sender, int signal_index, void **argv);
static void activate(QObject *sender, const QMetaObject *,
int local_signal_index, void **argv);
//似乎是为了处理函数调用的问题。
//毕竟类的静态函数、动态函数,全局函数、对象函数的调用方式是不一样的
//本函数有好几个重载形式,全部删除
static bool invokeMethod(QObject *obj, const char *member,
Qt::ConnectionType,
QGenericReturnArgument ret,
QGenericArgument val0 = QGenericArgument(nullptr),
QGenericArgument val1 = QGenericArgument(),
QGenericArgument val2 = QGenericArgument(),
QGenericArgument val3 = QGenericArgument(),
QGenericArgument val4 = QGenericArgument(),
QGenericArgument val5 = QGenericArgument(),
QGenericArgument val6 = QGenericArgument(),
QGenericArgument val7 = QGenericArgument(),
QGenericArgument val8 = QGenericArgument(),
QGenericArgument val9 = QGenericArgument());
// 本函数似乎是要创建一个对象,QObect 类型或其子类
QObject * newInstance(QGenericArgument val0 = QGenericArgument(nullptr),
QGenericArgument val1 = QGenericArgument(),
QGenericArgument val2 = QGenericArgument(),
QGenericArgument val3 = QGenericArgument(),
QGenericArgument val4 = QGenericArgument(),
QGenericArgument val5 = QGenericArgument(),
QGenericArgument val6 = QGenericArgument(),
QGenericArgument val7 = QGenericArgument(),
QGenericArgument val8 = QGenericArgument(),
QGenericArgument val9 = QGenericArgument()) const;
enum Call { //定义了这么一个枚举类,似乎是定义函数的功能与类型
InvokeMetaMethod,
ReadProperty,
WriteProperty,
ResetProperty,
CreateInstance,
IndexOfMethod,
RegisterPropertyMetaType,
RegisterMethodArgumentMetaType,
BindableProperty
};
template <const QMetaObject & MO> //模板成员函数
static constexpr const QMetaObject * staticMetaObject() { return & MO; }
struct Data { // private data
SuperData superdata;
const uint *stringdata;
const uint *data;
typedef void (*StaticMetacallFunction)
(QObject *, QMetaObject::Call, int, void **);
StaticMetacallFunction static_metacall;
const SuperData *relatedMetaObjects;
const QtPrivate::QMetaTypeInterface * const * metaTypes;
void *extradata; //reserved for future use
} d; //本类的数据成员
};
(3)补充记录 QObject 的完整精简版源码 :
#ifndef QOBJECT_H
#define QOBJECT_H
#ifndef QT_NO_QOBJECT
#include <QtCore/qobjectdefs.h>
#include <QtCore/qstring.h>
#include <QtCore/qbytearray.h>
#include <QtCore/qlist.h>
#ifdef QT_INCLUDE_COMPAT
#include <QtCore/qcoreevent.h>
#endif
#include <QtCore/qscopedpointer.h>
#include <QtCore/qmetatype.h>
#include <QtCore/qobject_impl.h>
#include <QtCore/qbindingstorage.h>
#if __has_include(<chrono>)
# include <chrono>
#endif
QT_BEGIN_NAMESPACE
template <typename T> class QBindable;
class QEvent;
class QTimerEvent;
class QChildEvent;
struct QMetaObject;
class QVariant;
class QObjectPrivate;
class QObject;
class QThread;
class QWidget;
class QAccessibleWidget;
#if QT_CONFIG(regularexpression)
class QRegularExpression;
#endif
struct QDynamicMetaObjectData;
typedef QList<QObject*> QObjectList;
Q_CORE_EXPORT void qt_qFindChildren_helper(const QObject *parent, const QString &name,
const QMetaObject &mo, QList<void *> *list, Qt::FindChildOptions options);
Q_CORE_EXPORT void qt_qFindChildren_helper(const QObject *parent, const QRegularExpression &re,
const QMetaObject &mo, QList<void *> *list, Qt::FindChildOptions options);
Q_CORE_EXPORT QObject *qt_qFindChild_helper(const QObject *parent, const QString &name, const QMetaObject &mo, Qt::FindChildOptions options);
class Q_CORE_EXPORT QObjectData
{
Q_DISABLE_COPY(QObjectData) //该宏表示禁止定义 copy 构造与 copy 赋值运算符函数
public:
QObjectData() = default;
virtual ~QObjectData() = 0;
QObject * q_ptr ; //该成员指出本类描述的是哪个 QObject 对象,回指向 QObject
QObject * parent; //记录本 QObject 类的所属容器。该功能又继承给 QObject 的所有子类
QObjectList children; //记录本 QObject 容器包含的所有 QObject 类对象
//typedef QList< QObject * > QObjectList; 类型定义
//基于此,为了处理 QT中的类对象析构,似宜将所有的类都继承 QObject并将之加入到某个容器中。
uint isWidget : 1; //以下是记录 QObject 对象应具备的其它属性,看不懂,略
uint blockSig : 1;
uint wasDeleted : 1;
uint isDeletingChildren : 1;
uint sendChildEvents : 1;
uint receiveChildEvents : 1;
uint isWindow : 1; // for QWindow
uint deleteLaterCalled : 1;
uint unused : 24;
int postedEvents;
QDynamicMetaObjectData *metaObject;
QBindingStorage bindingStorage;
QMetaObject *dynamicMetaObject() const;
enum { CheckForParentChildLoopsWarnDepth = 4096 };
};
class Q_CORE_EXPORT QObject
{
Q_OBJECT
Q_PROPERTY(QString objectName //定义了 objectName 属性
READ objectName
WRITE setObjectName
NOTIFY objectNameChanged
BINDABLE bindableObjectName)
Q_DECLARE_PRIVATE(QObject) // 声明私有类
private:
Q_DISABLE_COPY(QObject) //禁止对本类的复制操作
Q_PRIVATE_SLOT(d_func(), void _q_reregisterTimers(void *))
static QMetaObject::Connection connectImpl(
const QObject * sender , void ** signal,
const QObject * receiver, void ** slotPtr,
QtPrivate::QSlotObjectBase * slot, Qt::ConnectionType type,
const int *types, const QMetaObject *senderMetaObject);
static bool disconnectImpl(const QObject * sender , void ** signal,
const QObject * receiver, void ** slot ,
const QMetaObject * senderMetaObject);
protected:
virtual void connectNotify(const QMetaMethod & signal);
virtual void disconnectNotify(const QMetaMethod & signal);
bool isSignalConnected (const QMetaMethod & signal) const;
int receivers(const char * signal) const;
friend struct QMetaObject; //友元类很多,略
QObject * sender() const; //判断信号的发送者
int senderSignalIndex() const;
QScopedPointer<QObjectData> d_ptr; //此保护权限的数据成员可被子类使用。
//这里定义了本类的数据成员,被智能指针包裹
QObject(QObjectPrivate & dd, QObject * parent = nullptr);
public:
Q_INVOKABLE explicit QObject(QObject *parent = nullptr);
virtual ~QObject();
//返回源文本的翻译版本,
static QString tr(const char * sourceText, //从 ascii码字符串返回 QString字符串
const char * disambiguation = nullptr, int n = -1)
{
return QString::fromUtf8(sourceText);
}
// Q_PROPERTY(QString objectName //定义了 objectName 属性
// READ objectName
// WRITE setObjectName
// NOTIFY objectNameChanged
// BINDABLE bindableObjectName)
//这俩函数是上面的 objectName 属性的读写函数,
//名称由程序员自定义,在 setupUi()函数里被频繁调用
QString objectName() const; //返回的是类生成的对象名
//const char * QMetaObject::className() const; 返回的是类名
void setObjectName(const QString & name);
QBindable<QString> bindableObjectName(); //无官方注释
Q_SIGNALS: //信号函数不需要实现
void objectNameChanged(const QString & objectName,
QPrivateSignal );
//这是属性的信号函数
//此信号在对象obj被销毁之前立即发出,在任何QPointer实例通知之后,并且不能被阻塞。
//在发出此信号后,所有对象的子对象将立即被销毁。
void destroyed(QObject * obj = nullptr);
public Q_SLOTS:
void deleteLater(); //Note: This function is thread-safe.
/*
计划删除此对象。当控制返回事件循环时,该对象将被删除。如果在调用此函数时事件循环并未运行,
(例如,在调用deleteLater()`之前对象尚未通过`QCoreApplication:exec()'启动),
那么在启动事件循环后该对象才会被删除。
如果在主事件循环已停止后调用`deleteLater(),则该对象将不会被删除。
自Qt 4.8版本起,
如果在没有运行事件循环的线程中调用`deleteLater()、,该对象将在该线程执行完毕时被销毁。
请注意,进入和离开一个新的事件循环(例如通过打开一个模态对话框)将不会执行延迟删除;
要删除该对象,该控件必须从调用deleteLater()的事件循环中返回到事件循环。
这并不适用于在先前嵌套的事件循环仍在运行时就被删除的对象.
一旦新的嵌套事件循环启动,Qt事件循环将立即删除这些对象。
注:安全起见,可以多次调用此函数;
当第一个延迟删除事件被发送时,该对象的所有待处理事件都会被从事件队列中移除。
*/
public:
#ifndef QT_NO_PROPERTIES //这里出现了动态属性设置
//根据属性名获取属性值,形参是字符串
QVariant property(const char * name) const;
bool setProperty(const char * name, const QVariant & value);
QList<QByteArray> dynamicPropertyNames() const;
//作为对比 QMetaProperty QMetaObject::property(int index) const;
//根据属性索引返回值属性对象 QMetaProperty对象,形参是数字索引
QBindingStorage * bindingStorage()
{ return &d_ptr->bindingStorage; }
const
QBindingStorage * bindingStorage() const
{ return &d_ptr->bindingStorage; }
#endif // QT_NO_PROPERTIES
void dumpObjectTree() const;
void dumpObjectInfo() const;
inline bool isWidgetType() const { return d_ptr->isWidget; }
inline bool isWindowType() const { return d_ptr->isWindow; }
inline
bool signalsBlocked () const noexcept { return d_ptr->blockSig; }
bool blockSignals(bool b) noexcept;
QThread * thread() const;
void moveToThread(QThread * thread);
// CoarseTimer 粗调定时器
int startTimer(int interval, Qt::TimerType timerType = Qt::CoarseTimer);
Q_ALWAYS_INLINE //这是 c++ STL 库里的 chrono 命名空间
int startTimer(std::chrono::milliseconds time,
Qt::TimerType timerType = Qt::CoarseTimer)
{ return startTimer(int(time.count()), timerType); }
void killTimer(int id);
//用于判断本对象是否是形参类及其子类的实现
inline
bool inherits(const char * classname) const
{ return const_cast<QObject *>(this)->qt_metacast(classname) != nullptr; }
//bool QMetaObject :: inherits(const QMetaObject * metaObject) 用于判断类的继承关系
//显示本对象所在的容器,或者说返回容器父类
inline
QObject * parent() const { return d_ptr->parent; }
//而 QMetaObject :: superClass() 则返回继承父类
void setParent(QObject * parent); //此函数定义在这里,加入容器
//Returns a list of child objects.
//typedef QList<QObject *> QObjectList;
inline const
QObjectList & children() const { return d_ptr->children; }
//举例: QPushButton *button = pWidget->findChild<QPushButton *>("button1");
template<typename T> //默认按照递归查找容器中的孩子。模板参数 T应是对象指针类型
inline
T findChild(const QString & aName = QString(), //按名字查找
Qt::FindChildOptions options = Qt::FindChildrenRecursively) const
{
typedef typename std::remove_cv<
typename std::remove_pointer<T>::type
>::type ObjType;
return static_cast<T>(
qt_qFindChild_helper(this, aName, ObjType::staticMetaObject, options)
);
}
//举例: QList<QWidget *> widgets = p.findChildren<QWidget *>("widgetname");
template<typename T> // 模板参数 T 是指针类型
inline
QList<T> findChildren(const QString & aName = QString(),
Qt::FindChildOptions options = Qt::FindChildrenRecursively) const
{
typedef typename std::remove_cv<
typename std::remove_pointer<T>::type
>::type ObjType;
QList<T> list;
qt_qFindChildren_helper(this, aName, ObjType::staticMetaObject,
reinterpret_cast<QList<void *> *>(&list), options);
return list;
}
template<typename T>
inline
QList<T> findChildren(const QRegularExpression &re,
Qt::FindChildOptions options = Qt::FindChildrenRecursively) const
{
typedef typename std::remove_cv<
typename std::remove_pointer<T>::type>::type ObjType;
QList<T> list;
qt_qFindChildren_helper(this, re, ObjType::staticMetaObject,
reinterpret_cast<QList<void *> *>(&list), options);
return list;
}
virtual
bool event ( QEvent * event);
virtual
bool eventFilter(QObject * watched, QEvent * event);
void installEventFilter(QObject * filterObj);
void removeEventFilter(QObject * obj);
protected:
virtual void timerEvent(QTimerEvent * event);
virtual void childEvent(QChildEvent * event);
virtual void customEvent(QEvent * event);
public: //以下全是冗长的信号的连接与断开成员函数,带定义,所以长。
static QMetaObject::Connection connect(
const QObject * sender , const char * signal,
const QObject * receiver, const char * member,
Qt::ConnectionType = Qt::AutoConnection);
static QMetaObject::Connection connect( //这俩是类的静态成员函数
const QObject * sender , const QMetaMethod & signal,
const QObject * receiver, const QMetaMethod & method,
Qt::ConnectionType type = Qt::AutoConnection);
inline QMetaObject::Connection connect( //基于对象的动态成员函数
const QObject * sender, const char * signal,
const char * member,
Qt::ConnectionType type = Qt::AutoConnection) const;
#ifdef Q_CLANG_QDOC
template<typename PointerToMemberFunction>
static QMetaObject::Connection connect(const QObject *sender, PointerToMemberFunction signal, const QObject *receiver, PointerToMemberFunction method, Qt::ConnectionType type = Qt::AutoConnection);
template<typename PointerToMemberFunction, typename Functor>
static QMetaObject::Connection connect(const QObject *sender, PointerToMemberFunction signal, Functor functor);
template<typename PointerToMemberFunction, typename Functor>
static QMetaObject::Connection connect(const QObject *sender, PointerToMemberFunction signal, const QObject *context, Functor functor, Qt::ConnectionType type = Qt::AutoConnection);
#else
//Connect a signal to a pointer to qobject member function
template <typename Func1, typename Func2>
static inline QMetaObject::Connection connect( //暂时不细看了
const typename QtPrivate::FunctionPointer<Func1>::Object * sender,
Func1 signal,
const typename QtPrivate::FunctionPointer<Func2>::Object *receiver,
Func2 slot,
Qt::ConnectionType type = Qt::AutoConnection)
{
typedef QtPrivate::FunctionPointer<Func1> SignalType;
typedef QtPrivate::FunctionPointer<Func2> SlotType;
static_assert(QtPrivate::HasQ_OBJECT_Macro<typename SignalType::Object>::Value,
"No Q_OBJECT in the class with the signal");
//compilation error if the arguments does not match.
static_assert(int(SignalType::ArgumentCount) >= int(SlotType::ArgumentCount),
"The slot requires more arguments than the signal provides.");
static_assert((QtPrivate::CheckCompatibleArguments<typename SignalType::Arguments, typename SlotType::Arguments>::value),
"Signal and slot arguments are not compatible.");
static_assert((QtPrivate::AreArgumentsCompatible<typename SlotType::ReturnType, typename SignalType::ReturnType>::value),
"Return type of the slot is not compatible with the return type of the signal.");
const int *types = nullptr;
if (type == Qt::QueuedConnection || type == Qt::BlockingQueuedConnection)
types = QtPrivate::ConnectionTypes<typename SignalType::Arguments>::types();
return connectImpl(sender, reinterpret_cast<void **>(&signal),
receiver, reinterpret_cast<void **>(&slot),
new QtPrivate::QSlotObject<Func2, typename QtPrivate::List_Left<typename SignalType::Arguments, SlotType::ArgumentCount>::Value,
typename SignalType::ReturnType>(slot),
type, types, &SignalType::Object::staticMetaObject);
}
//connect to a function pointer (not a member)
template <typename Func1, typename Func2>
static inline
typename std::enable_if<
int(QtPrivate::FunctionPointer<Func2>::ArgumentCount) >= 0,
QMetaObject::Connection
>::type //这是函数的返回值
connect(const typename QtPrivate::FunctionPointer<Func1>::Object *sender,
Func1 signal, Func2 slot)
{
return connect(sender, signal, sender, slot, Qt::DirectConnection);
}
//connect to a function pointer (not a member)
template <typename Func1, typename Func2>
static inline
typename std::enable_if< //这里的 if 的判断条件是个 && 运算
int(QtPrivate::FunctionPointer<Func2>::ArgumentCount) >= 0 &&
!QtPrivate::FunctionPointer<Func2>::IsPointerToMemberFunction,
QMetaObject::Connection //这一行决定了本函的返回值
>::type
connect(const typename QtPrivate::FunctionPointer<Func1>::Object *sender,
Func1 signal,
const QObject *context, Func2 slot,
Qt::ConnectionType type = Qt::AutoConnection)
{
typedef QtPrivate::FunctionPointer<Func1> SignalType;
typedef QtPrivate::FunctionPointer<Func2> SlotType;
static_assert(QtPrivate::HasQ_OBJECT_Macro<typename SignalType::Object>::Value,
"No Q_OBJECT in the class with the signal");
//compilation error if the arguments does not match.
static_assert(int(SignalType::ArgumentCount) >= int(SlotType::ArgumentCount),
"The slot requires more arguments than the signal provides.");
static_assert((QtPrivate::CheckCompatibleArguments<typename SignalType::Arguments, typename SlotType::Arguments>::value),
"Signal and slot arguments are not compatible.");
static_assert((QtPrivate::AreArgumentsCompatible<typename SlotType::ReturnType, typename SignalType::ReturnType>::value),
"Return type of the slot is not compatible with the return type of the signal.");
const int *types = nullptr;
if (type == Qt::QueuedConnection || type == Qt::BlockingQueuedConnection)
types = QtPrivate::ConnectionTypes<typename SignalType::Arguments>::types();
return connectImpl(sender, reinterpret_cast<void **>(&signal), context, nullptr,
new QtPrivate::QStaticSlotObject<Func2,
typename QtPrivate::List_Left<typename SignalType::Arguments, SlotType::ArgumentCount>::Value,
typename SignalType::ReturnType>(slot),
type, types, &SignalType::Object::staticMetaObject);
}
//connect to a functor
template <typename Func1, typename Func2>
static inline
typename std::enable_if<
QtPrivate::FunctionPointer<Func2>::ArgumentCount == -1,
QMetaObject::Connection
>::type
connect(const typename QtPrivate::FunctionPointer<Func1>::Object *sender,
Func1 signal, Func2 slot)
{
return connect(sender, signal,
sender, std::move(slot), Qt::DirectConnection);
}
//connect to a functor,
//with a "context" object defining in which
//event loop is going to be executed
template <typename Func1, typename Func2>
static inline
typename std::enable_if<
QtPrivate::FunctionPointer<Func2>::ArgumentCount == -1,
QMetaObject::Connection
>::type
connect(const typename QtPrivate::FunctionPointer<Func1>::Object *sender,
Func1 signal, const QObject *context, Func2 slot,
Qt::ConnectionType type = Qt::AutoConnection)
{
typedef QtPrivate::FunctionPointer<Func1> SignalType;
const int FunctorArgumentCount = QtPrivate::ComputeFunctorArgumentCount<Func2 , typename SignalType::Arguments>::Value;
static_assert((FunctorArgumentCount >= 0),
"Signal and slot arguments are not compatible.");
const int SlotArgumentCount = (FunctorArgumentCount >= 0) ? FunctorArgumentCount : 0;
typedef typename QtPrivate::FunctorReturnType<Func2, typename QtPrivate::List_Left<typename SignalType::Arguments, SlotArgumentCount>::Value>::Value SlotReturnType;
static_assert((QtPrivate::AreArgumentsCompatible<SlotReturnType, typename SignalType::ReturnType>::value),
"Return type of the slot is not compatible with the return type of the signal.");
static_assert(QtPrivate::HasQ_OBJECT_Macro<typename SignalType::Object>::Value,
"No Q_OBJECT in the class with the signal");
const int *types = nullptr;
if (type == Qt::QueuedConnection || type == Qt::BlockingQueuedConnection)
types = QtPrivate::ConnectionTypes<typename SignalType::Arguments>::types();
return connectImpl(sender, reinterpret_cast<void **>(&signal), context, nullptr,
new QtPrivate::QFunctorSlotObject<Func2, SlotArgumentCount,
typename QtPrivate::List_Left<typename SignalType::Arguments, SlotArgumentCount>::Value,
typename SignalType::ReturnType>(std::move(slot)),
type, types, &SignalType::Object::staticMetaObject);
}
#endif //Q_CLANG_QDOC
static bool disconnect( //解除信号与槽的静态成员函数
const QObject * sender , const char * signal,
const QObject * receiver, const char * member);
static bool disconnect(
const QObject * sender , const QMetaMethod & signal,
const QObject * receiver, const QMetaMethod & member);
inline bool disconnect( //动态函数默认由信号发送者调用
const char * signal = nullptr,
const QObject * receiver = nullptr,
const char * member = nullptr) const
{ return disconnect(this, signal, receiver, member); }
inline bool disconnect(
const QObject * receiver,
const char * member = nullptr) const
{ return disconnect(this, nullptr, receiver, member); }
static bool disconnect(const QMetaObject::Connection &);
#ifdef Q_CLANG_QDOC
template<typename PointerToMemberFunction>
static bool disconnect(const QObject *sender, PointerToMemberFunction signal, const QObject *receiver, PointerToMemberFunction method);
#else
template <typename Func1, typename Func2>
static inline bool disconnect(
const typename QtPrivate::FunctionPointer<Func1>::Object * sender,
Func1 signal,
const typename QtPrivate::FunctionPointer<Func2>::Object * receiver,
Func2 slot )
{
typedef QtPrivate::FunctionPointer<Func1> SignalType;
typedef QtPrivate::FunctionPointer<Func2> SlotType;
static_assert(QtPrivate::HasQ_OBJECT_Macro<typename SignalType::Object>::Value,
"No Q_OBJECT in the class with the signal");
//compilation error if the arguments does not match.
static_assert((QtPrivate::CheckCompatibleArguments<typename SignalType::Arguments, typename SlotType::Arguments>::value),
"Signal and slot arguments are not compatible.");
return disconnectImpl(sender, reinterpret_cast<void **>(&signal), receiver, reinterpret_cast<void **>(&slot),
&SignalType::Object::staticMetaObject);
}
template <typename Func1>
static inline bool disconnect(
const typename QtPrivate::FunctionPointer<Func1>::Object * sender,
Func1 signal, const QObject * receiver, void ** zero)
{
// This is the overload for when one wish to disconnect a signal from any slot. (slot=nullptr)
// Since the function template parameter cannot be deduced from '0', we use a
// dummy void ** parameter that must be equal to 0
Q_ASSERT(!zero);
typedef QtPrivate::FunctionPointer<Func1> SignalType;
return disconnectImpl(sender, reinterpret_cast<void **>(&signal), receiver, zero,
&SignalType::Object::staticMetaObject);
}
#endif //Q_CLANG_QDOC
}; //结束 class QObject 的定义
inline QMetaObject::Connection
QObject::connect(const QObject *asender, const char *asignal,
const char *amember, Qt::ConnectionType atype) const
{ return connect(asender, asignal, this, amember, atype); }
template <class T>
inline T qobject_cast(QObject *object)
{
typedef typename std::remove_cv<typename std::remove_pointer<T>::type>::type ObjType;
static_assert(QtPrivate::HasQ_OBJECT_Macro<ObjType>::Value,
"qobject_cast requires the type to have a Q_OBJECT macro");
return static_cast<T>(ObjType::staticMetaObject.cast(object));
}
template <class T>
inline T qobject_cast(const QObject *object)
{
typedef typename std::remove_cv<typename std::remove_pointer<T>::type>::type ObjType;
static_assert(QtPrivate::HasQ_OBJECT_Macro<ObjType>::Value,
"qobject_cast requires the type to have a Q_OBJECT macro");
return static_cast<T>(ObjType::staticMetaObject.cast(object));
}
template <class T> inline const char * qobject_interface_iid()
{ return nullptr; }
inline const QBindingStorage *qGetBindingStorage(const QObject *o)
{
return o->bindingStorage();
}
inline QBindingStorage *qGetBindingStorage(QObject *o)
{
return o->bindingStorage();
}
#if defined(Q_CLANG_QDOC)
# define Q_DECLARE_INTERFACE(IFace, IId)
#elif !defined(Q_MOC_RUN)
# define Q_DECLARE_INTERFACE(IFace, IId) \
template <> inline const char *qobject_interface_iid<IFace *>() \
{ return IId; } \
template <> inline IFace *qobject_cast<IFace *>(QObject *object) \
{ return reinterpret_cast<IFace *>((object ? object->qt_metacast(IId) : nullptr)); } \
template <> inline IFace *qobject_cast<IFace *>(const QObject *object) \
{ return reinterpret_cast<IFace *>((object ? const_cast<QObject *>(object)->qt_metacast(IId) : nullptr)); }
#endif // Q_MOC_RUN
#ifndef QT_NO_DEBUG_STREAM
Q_CORE_EXPORT QDebug operator<<(QDebug, const QObject *);
#endif
class QSignalBlocker
{
public:
inline explicit QSignalBlocker(QObject *o) noexcept;
inline explicit QSignalBlocker(QObject &o) noexcept;
inline ~QSignalBlocker();
inline QSignalBlocker(QSignalBlocker &&other) noexcept;
inline QSignalBlocker &operator=(QSignalBlocker &&other) noexcept;
inline void reblock() noexcept;
inline void unblock() noexcept;
private:
Q_DISABLE_COPY(QSignalBlocker)
QObject *m_o;
bool m_blocked;
bool m_inhibited;
};
QSignalBlocker::QSignalBlocker(QObject *o) noexcept
: m_o(o),
m_blocked(o && o->blockSignals(true)),
m_inhibited(false)
{}
QSignalBlocker::QSignalBlocker(QObject &o) noexcept
: m_o(&o),
m_blocked(o.blockSignals(true)),
m_inhibited(false)
{}
QSignalBlocker::QSignalBlocker(QSignalBlocker &&other) noexcept
: m_o(other.m_o),
m_blocked(other.m_blocked),
m_inhibited(other.m_inhibited)
{
other.m_o = nullptr;
}
QSignalBlocker &QSignalBlocker::operator=(QSignalBlocker &&other) noexcept
{
if (this != &other) {
// if both *this and other block the same object's signals:
// unblock *this iff our dtor would unblock, but other's wouldn't
if (m_o != other.m_o || (!m_inhibited && other.m_inhibited))
unblock();
m_o = other.m_o;
m_blocked = other.m_blocked;
m_inhibited = other.m_inhibited;
// disable other:
other.m_o = nullptr;
}
return *this;
}
QSignalBlocker::~QSignalBlocker()
{
if (m_o && !m_inhibited)
m_o->blockSignals(m_blocked);
}
void QSignalBlocker::reblock() noexcept
{
if (m_o)
m_o->blockSignals(true);
m_inhibited = false;
}
void QSignalBlocker::unblock() noexcept
{
if (m_o)
m_o->blockSignals(m_blocked);
m_inhibited = true;
}
namespace QtPrivate {
inline QObject & deref_for_methodcall(QObject &o) { return o; }
inline QObject & deref_for_methodcall(QObject *o) { return *o; }
}
#define Q_SET_OBJECT_NAME(obj) QT_PREPEND_NAMESPACE(QtPrivate)::deref_for_methodcall(obj).setObjectName(QLatin1String(#obj))
QT_END_NAMESPACE
#endif
#endif // QOBJECT_H
(4)
谢谢
351

被折叠的 条评论
为什么被折叠?



