diff options
Diffstat (limited to 'src/corelib/kernel/qobject.h')
-rw-r--r-- | src/corelib/kernel/qobject.h | 225 |
1 files changed, 109 insertions, 116 deletions
diff --git a/src/corelib/kernel/qobject.h b/src/corelib/kernel/qobject.h index 7fa2790208..06cfefd61b 100644 --- a/src/corelib/kernel/qobject.h +++ b/src/corelib/kernel/qobject.h @@ -19,10 +19,9 @@ #include <QtCore/qobject_impl.h> #include <QtCore/qbindingstorage.h> +#include <QtCore/qtcoreexports.h> -#if __has_include(<chrono>) -# include <chrono> -#endif +#include <chrono> QT_BEGIN_NAMESPACE @@ -45,13 +44,24 @@ struct QDynamicMetaObjectData; typedef QList<QObject*> QObjectList; +#if QT_CORE_REMOVED_SINCE(6, 7) Q_CORE_EXPORT void qt_qFindChildren_helper(const QObject *parent, const QString &name, const QMetaObject &mo, QList<void *> *list, Qt::FindChildOptions options); +#endif +Q_CORE_EXPORT void qt_qFindChildren_helper(const QObject *parent, QAnyStringView name, + const QMetaObject &mo, QList<void *> *list, + Qt::FindChildOptions options); +#if QT_CORE_REMOVED_SINCE(6, 7) Q_CORE_EXPORT void qt_qFindChildren_helper(const QObject *parent, const QMetaObject &mo, QList<void *> *list, Qt::FindChildOptions options); +#endif Q_CORE_EXPORT void qt_qFindChildren_helper(const QObject *parent, const QRegularExpression &re, const QMetaObject &mo, QList<void *> *list, Qt::FindChildOptions options); +#if QT_CORE_REMOVED_SINCE(6, 7) Q_CORE_EXPORT QObject *qt_qFindChild_helper(const QObject *parent, const QString &name, const QMetaObject &mo, Qt::FindChildOptions options); +#endif +Q_CORE_EXPORT QObject *qt_qFindChild_helper(const QObject *parent, QAnyStringView name, + const QMetaObject &mo, Qt::FindChildOptions options); class Q_CORE_EXPORT QObjectData { @@ -74,7 +84,8 @@ public: uint isQuickItem : 1; uint willBeWidget : 1; // for handling widget-specific bits in QObject's ctor uint wasWidget : 1; // for properly cleaning up in QObject's dtor - uint unused : 21; + uint receiveParentEvents: 1; + uint unused : 20; QAtomicInt postedEvents; QDynamicMetaObjectData *metaObject; QBindingStorage bindingStorage; @@ -103,7 +114,7 @@ public: virtual bool event(QEvent *event); virtual bool eventFilter(QObject *watched, QEvent *event); -#if defined(QT_NO_TRANSLATION) || defined(Q_CLANG_QDOC) +#if defined(QT_NO_TRANSLATION) || defined(Q_QDOC) static QString tr(const char *sourceText, const char * = nullptr, int = -1) { return QString::fromUtf8(sourceText); } #endif // QT_NO_TRANSLATION @@ -125,29 +136,36 @@ public: bool blockSignals(bool b) noexcept; QThread *thread() const; +#if QT_CORE_REMOVED_SINCE(6, 7) void moveToThread(QThread *thread); +#endif + bool moveToThread(QThread *thread QT6_DECL_NEW_OVERLOAD_TAIL); int startTimer(int interval, Qt::TimerType timerType = Qt::CoarseTimer); -#if __has_include(<chrono>) - Q_ALWAYS_INLINE - int startTimer(std::chrono::milliseconds time, Qt::TimerType timerType = Qt::CoarseTimer) - { - return startTimer(int(time.count()), timerType); - } + +#if QT_CORE_REMOVED_SINCE(6, 8) + int startTimer(std::chrono::milliseconds time, Qt::TimerType timerType = Qt::CoarseTimer); #endif + int startTimer(std::chrono::nanoseconds time, Qt::TimerType timerType = Qt::CoarseTimer); + void killTimer(int id); + void killTimer(Qt::TimerId id); template<typename T> - inline T findChild(const QString &aName = QString(), Qt::FindChildOptions options = Qt::FindChildrenRecursively) const + T findChild(QAnyStringView aName, Qt::FindChildOptions options = Qt::FindChildrenRecursively) const { typedef typename std::remove_cv<typename std::remove_pointer<T>::type>::type ObjType; + static_assert(QtPrivate::HasQ_OBJECT_Macro<ObjType>::Value, + "No Q_OBJECT in the class passed to QObject::findChild"); return static_cast<T>(qt_qFindChild_helper(this, aName, ObjType::staticMetaObject, options)); } template<typename T> - inline QList<T> findChildren(const QString &aName, Qt::FindChildOptions options = Qt::FindChildrenRecursively) const + QList<T> findChildren(QAnyStringView aName, Qt::FindChildOptions options = Qt::FindChildrenRecursively) const { typedef typename std::remove_cv<typename std::remove_pointer<T>::type>::type ObjType; + static_assert(QtPrivate::HasQ_OBJECT_Macro<ObjType>::Value, + "No Q_OBJECT in the class passed to QObject::findChildren"); QList<T> list; qt_qFindChildren_helper(this, aName, ObjType::staticMetaObject, reinterpret_cast<QList<void *> *>(&list), options); @@ -155,13 +173,15 @@ public: } template<typename T> + T findChild(Qt::FindChildOptions options = Qt::FindChildrenRecursively) const + { + return findChild<T>({}, options); + } + + template<typename T> QList<T> findChildren(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, ObjType::staticMetaObject, - reinterpret_cast<QList<void *> *>(&list), options); - return list; + return findChildren<T>(QAnyStringView{}, options); } #if QT_CONFIG(regularexpression) @@ -169,6 +189,8 @@ public: 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; + static_assert(QtPrivate::HasQ_OBJECT_Macro<ObjType>::Value, + "No Q_OBJECT in the class passed to QObject::findChildren"); QList<T> list; qt_qFindChildren_helper(this, re, ObjType::staticMetaObject, reinterpret_cast<QList<void *> *>(&list), options); @@ -192,7 +214,7 @@ public: inline QMetaObject::Connection connect(const QObject *sender, const char *signal, const char *member, Qt::ConnectionType type = Qt::AutoConnection) const; -#ifdef Q_CLANG_QDOC +#ifdef Q_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> @@ -200,54 +222,28 @@ public: 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 + //connect with context 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) + static inline QMetaObject::Connection + connect(const typename QtPrivate::FunctionPointer<Func1>::Object *sender, Func1 signal, + const typename QtPrivate::ContextTypeForFunctor<Func2>::ContextType *context, Func2 &&slot, + Qt::ConnectionType type = Qt::AutoConnection) { typedef QtPrivate::FunctionPointer<Func1> SignalType; - typedef QtPrivate::FunctionPointer<Func2> SlotType; + typedef QtPrivate::FunctionPointer<std::decay_t<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); - } + if constexpr (SlotType::ArgumentCount != -1) { + 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."); + } else { + constexpr int FunctorArgumentCount = QtPrivate::ComputeFunctorArgumentCount<std::decay_t<Func2>, typename SignalType::Arguments>::Value; + [[maybe_unused]] + constexpr int SlotArgumentCount = (FunctorArgumentCount >= 0) ? FunctorArgumentCount : 0; + typedef typename QtPrivate::FunctorReturnType<std::decay_t<Func2>, typename QtPrivate::List_Left<typename SignalType::Arguments, SlotArgumentCount>::Value>::Value SlotReturnType; - //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 && - !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::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"); @@ -255,67 +251,35 @@ public: //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), + void **pSlot = nullptr; + if constexpr (std::is_member_function_pointer_v<std::decay_t<Func2>>) { + pSlot = const_cast<void **>(reinterpret_cast<void *const *>(&slot)); + } else { + Q_ASSERT_X((type & Qt::UniqueConnection) == 0, "", + "QObject::connect: Unique connection requires the slot to be a pointer to " + "a member function of a QObject subclass."); + } + + return connectImpl(sender, reinterpret_cast<void **>(&signal), context, pSlot, + QtPrivate::makeCallableObject<Func1>(std::forward<Func2>(slot)), type, types, &SignalType::Object::staticMetaObject); } - //connect to a functor +#ifndef QT_NO_CONTEXTLESS_CONNECT + //connect without context template <typename Func1, typename Func2> - static inline typename std::enable_if< - QtPrivate::FunctionPointer<Func2>::ArgumentCount == -1 && - !std::is_convertible_v<Func2, const char*>, // don't match old-style connect - QMetaObject::Connection>::type - connect(const typename QtPrivate::FunctionPointer<Func1>::Object *sender, Func1 signal, Func2 slot) + static inline QMetaObject::Connection + 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 && - !std::is_convertible_v<Func2, const char*>, // don't match old-style connect - 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); + return connect(sender, signal, sender, std::forward<Func2>(slot), Qt::DirectConnection); } -#endif //Q_CLANG_QDOC +#endif // QT_NO_CONTEXTLESS_CONNECT +#endif //Q_QDOC static bool disconnect(const QObject *sender, const char *signal, const QObject *receiver, const char *member); @@ -328,7 +292,7 @@ public: { return disconnect(this, nullptr, receiver, member); } static bool disconnect(const QMetaObject::Connection &); -#ifdef Q_CLANG_QDOC +#ifdef Q_QDOC template<typename PointerToMemberFunction> static bool disconnect(const QObject *sender, PointerToMemberFunction signal, const QObject *receiver, PointerToMemberFunction method); #else @@ -361,12 +325,14 @@ public: return disconnectImpl(sender, reinterpret_cast<void **>(&signal), receiver, zero, &SignalType::Object::staticMetaObject); } -#endif //Q_CLANG_QDOC +#endif //Q_QDOC void dumpObjectTree() const; void dumpObjectInfo() const; + QT_CORE_INLINE_SINCE(6, 6) bool setProperty(const char *name, const QVariant &value); + inline bool setProperty(const char *name, QVariant &&value); QVariant property(const char *name) const; QList<QByteArray> dynamicPropertyNames() const; QBindingStorage *bindingStorage() { return &d_ptr->bindingStorage; } @@ -419,8 +385,9 @@ protected: private: void doSetObjectName(const QString &name); + bool doSetProperty(const char *name, const QVariant *lvalue, QVariant *rvalue); + Q_DISABLE_COPY(QObject) - Q_PRIVATE_SLOT(d_func(), void _q_reregisterTimers(void *)) private: static QMetaObject::Connection connectImpl(const QObject *sender, void **signal, @@ -437,9 +404,22 @@ inline QMetaObject::Connection QObject::connect(const QObject *asender, const ch const char *amember, Qt::ConnectionType atype) const { return connect(asender, asignal, this, amember, atype); } +#if QT_CORE_INLINE_IMPL_SINCE(6, 6) +bool QObject::setProperty(const char *name, const QVariant &value) +{ + return doSetProperty(name, &value, nullptr); +} +#endif // inline since 6.6 +bool QObject::setProperty(const char *name, QVariant &&value) +{ + return doSetProperty(name, &value, &value); +} + template <class T> inline T qobject_cast(QObject *object) { + static_assert(std::is_pointer_v<T>, + "qobject_cast requires to cast towards a pointer type"); 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"); @@ -449,6 +429,10 @@ inline T qobject_cast(QObject *object) template <class T> inline T qobject_cast(const QObject *object) { + static_assert(std::is_pointer_v<T>, + "qobject_cast requires to cast towards a pointer type"); + static_assert(std::is_const_v<std::remove_pointer_t<T>>, + "qobject_cast cannot cast away constness (use const_cast)"); 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"); @@ -470,7 +454,7 @@ qobject_iid_cast(const QObject *object) return qobject_iid_cast<std::remove_cv_t<T>>(o); } -#if defined(Q_CLANG_QDOC) +#if defined(Q_QDOC) # define Q_DECLARE_INTERFACE(IFace, IId) #elif !defined(Q_MOC_RUN) # define Q_DECLARE_INTERFACE(IFace, IId) \ @@ -498,15 +482,19 @@ Q_CORE_EXPORT QDebug operator<<(QDebug, const QObject *); class QSignalBlocker { public: + Q_NODISCARD_CTOR inline explicit QSignalBlocker(QObject *o) noexcept; + Q_NODISCARD_CTOR inline explicit QSignalBlocker(QObject &o) noexcept; inline ~QSignalBlocker(); + Q_NODISCARD_CTOR inline QSignalBlocker(QSignalBlocker &&other) noexcept; inline QSignalBlocker &operator=(QSignalBlocker &&other) noexcept; inline void reblock() noexcept; inline void unblock() noexcept; + inline void dismiss() noexcept; private: Q_DISABLE_COPY(QSignalBlocker) @@ -571,6 +559,11 @@ void QSignalBlocker::unblock() noexcept m_inhibited = true; } +void QSignalBlocker::dismiss() noexcept +{ + m_o = nullptr; +} + namespace QtPrivate { inline QObject & deref_for_methodcall(QObject &o) { return o; } inline QObject & deref_for_methodcall(QObject *o) { return *o; } |