diff options
author | Lars Knoll <lars.knoll@qt.io> | 2020-08-22 10:39:42 +0200 |
---|---|---|
committer | Lars Knoll <lars.knoll@qt.io> | 2020-09-02 22:44:28 +0200 |
commit | ee96d705ccfe5c27a24b63100b8352987dbb0ae4 (patch) | |
tree | 14a005bcc8b5f6e8813f94e96b3ce70211828c53 /src/corelib/kernel/qproperty.h | |
parent | e3ea8768fc3bfed088f70b5d7308e3dd94e93c32 (diff) |
Move QPropertyObserver further up in the header file
Reorder source code to make the follow-up work easier. Also clean up
retrieving the pointer to the aliased property.
Make setSource(QPropertyBindingData) public, it'll be needed later on.
Change-Id: I784fdceac8722c7df756b2d7c35e08c7ab3a2074
Reviewed-by: Ulf Hermann <ulf.hermann@qt.io>
Diffstat (limited to 'src/corelib/kernel/qproperty.h')
-rw-r--r-- | src/corelib/kernel/qproperty.h | 231 |
1 files changed, 112 insertions, 119 deletions
diff --git a/src/corelib/kernel/qproperty.h b/src/corelib/kernel/qproperty.h index 7b63a46665..02d1c1eb94 100644 --- a/src/corelib/kernel/qproperty.h +++ b/src/corelib/kernel/qproperty.h @@ -213,6 +213,86 @@ namespace Qt { } } +struct QPropertyObserverPrivate; +struct QPropertyObserverPointer; + +class Q_CORE_EXPORT QPropertyObserver +{ +public: + // Internal + enum ObserverTag { + ObserverNotifiesBinding, + ObserverNotifiesChangeHandler, + ObserverNotifiesAlias, + }; + + QPropertyObserver() = default; + QPropertyObserver(QPropertyObserver &&other); + QPropertyObserver &operator=(QPropertyObserver &&other); + ~QPropertyObserver(); + + template<typename Property, typename = typename Property::InheritsQUntypedPropertyData> + void setSource(const Property &property) + { setSource(property.bindingData()); } + void setSource(const QtPrivate::QPropertyBindingData &property); + +protected: + using ChangeHandler = void (*)(QPropertyObserver*, QUntypedPropertyData *); + QPropertyObserver(ChangeHandler changeHandler); + QPropertyObserver(QUntypedPropertyData *aliasedPropertyPtr); + + QUntypedPropertyData *aliasedProperty() const + { + return aliasedPropertyData; + } + +private: + + QTaggedPointer<QPropertyObserver, ObserverTag> next; + // prev is a pointer to the "next" element within the previous node, or to the "firstObserverPtr" if it is the + // first node. + QtPrivate::QTagPreservingPointerToPointer<QPropertyObserver, ObserverTag> prev; + + union { + QPropertyBindingPrivate *bindingToMarkDirty = nullptr; + ChangeHandler changeHandler; + QUntypedPropertyData *aliasedPropertyData; + }; + + QPropertyObserver(const QPropertyObserver &) = delete; + QPropertyObserver &operator=(const QPropertyObserver &) = delete; + + friend struct QPropertyObserverPointer; + friend struct QPropertyBindingDataPointer; + friend class QPropertyBindingPrivate; +}; + +template <typename Functor> +class QPropertyChangeHandler : public QPropertyObserver +{ + Functor m_handler; +public: + QPropertyChangeHandler(Functor handler) + : QPropertyObserver([](QPropertyObserver *self, QUntypedPropertyData *) { + auto This = static_cast<QPropertyChangeHandler<Functor>*>(self); + This->m_handler(); + }) + , m_handler(handler) + { + } + + template<typename Property, typename = typename Property::InheritsQUntypedPropertyData> + QPropertyChangeHandler(const Property &property, Functor handler) + : QPropertyObserver([](QPropertyObserver *self, QUntypedPropertyData *) { + auto This = static_cast<QPropertyChangeHandler<Functor>*>(self); + This->m_handler(); + }) + , m_handler(handler) + { + setSource(property); + } +}; + template <typename T> class QProperty : public QPropertyData<T> { @@ -362,9 +442,19 @@ public: } template<typename Functor> - QPropertyChangeHandler<Functor> onValueChanged(Functor f); + QPropertyChangeHandler<Functor> onValueChanged(Functor f) + { + static_assert(std::is_invocable_v<Functor>, "Functor callback must be callable without any parameters"); + return QPropertyChangeHandler<Functor>(*this, f); + } + template<typename Functor> - QPropertyChangeHandler<Functor> subscribe(Functor f); + QPropertyChangeHandler<Functor> subscribe(Functor f) + { + static_assert(std::is_invocable_v<Functor>, "Functor callback must be callable without any parameters"); + f(); + return onValueChanged(f); + } const QtPrivate::QPropertyBindingData &bindingData() const { return d; } private: @@ -386,112 +476,15 @@ namespace Qt { } } -struct QPropertyObserverPrivate; -struct QPropertyObserverPointer; - -class Q_CORE_EXPORT QPropertyObserver -{ -public: - // Internal - enum ObserverTag { - ObserverNotifiesBinding, - ObserverNotifiesChangeHandler, - ObserverNotifiesAlias, - }; - - QPropertyObserver() = default; - QPropertyObserver(QPropertyObserver &&other); - QPropertyObserver &operator=(QPropertyObserver &&other); - ~QPropertyObserver(); - - template<typename Property, typename = std::enable_if_t<std::is_same_v<decltype(std::declval<Property>().bindingData()), QtPrivate::QPropertyBindingData &>>> - void setSource(const Property &property) - { setSource(property.bindingData()); } - -protected: - using ChangeHandler = void (*)(QPropertyObserver*, QUntypedPropertyData *); - QPropertyObserver(ChangeHandler changeHandler); - QPropertyObserver(QUntypedPropertyData *aliasedPropertyPtr); - - template<typename PropertyType> - QProperty<PropertyType> *aliasedProperty() const - { - return static_cast<QProperty<PropertyType> *>(aliasedPropertyData); - } - -private: - void setSource(const QtPrivate::QPropertyBindingData &property); - - QTaggedPointer<QPropertyObserver, ObserverTag> next; - // prev is a pointer to the "next" element within the previous node, or to the "firstObserverPtr" if it is the - // first node. - QtPrivate::QTagPreservingPointerToPointer<QPropertyObserver, ObserverTag> prev; - - union { - QPropertyBindingPrivate *bindingToMarkDirty = nullptr; - ChangeHandler changeHandler; - QUntypedPropertyData *aliasedPropertyData; - }; - - QPropertyObserver(const QPropertyObserver &) = delete; - QPropertyObserver &operator=(const QPropertyObserver &) = delete; - - friend struct QPropertyObserverPointer; - friend struct QPropertyBindingDataPointer; - friend class QPropertyBindingPrivate; -}; - -template <typename Functor> -class QPropertyChangeHandler : public QPropertyObserver -{ - Functor m_handler; -public: - QPropertyChangeHandler(Functor handler) - : QPropertyObserver([](QPropertyObserver *self, QUntypedPropertyData *) { - auto This = static_cast<QPropertyChangeHandler<Functor>*>(self); - This->m_handler(); - }) - , m_handler(handler) - { - } - - template<typename Property, typename = typename Property::InheritsQUntypedPropertyData> - QPropertyChangeHandler(const Property &property, Functor handler) - : QPropertyObserver([](QPropertyObserver *self, QUntypedPropertyData *) { - auto This = static_cast<QPropertyChangeHandler<Functor>*>(self); - This->m_handler(); - }) - , m_handler(handler) - { - setSource(property); - } -}; - -template <typename T> -template<typename Functor> -QPropertyChangeHandler<Functor> QProperty<T>::onValueChanged(Functor f) -{ -#if defined(__cpp_lib_is_invocable) && (__cpp_lib_is_invocable >= 201703L) - static_assert(std::is_invocable_v<Functor>, "Functor callback must be callable without any parameters"); -#endif - return QPropertyChangeHandler<Functor>(*this, f); -} - -template <typename T> -template<typename Functor> -QPropertyChangeHandler<Functor> QProperty<T>::subscribe(Functor f) -{ -#if defined(__cpp_lib_is_invocable) && (__cpp_lib_is_invocable >= 201703L) - static_assert(std::is_invocable_v<Functor>, "Functor callback must be callable without any parameters"); -#endif - f(); - return onValueChanged(f); -} - template<typename T> class QPropertyAlias : public QPropertyObserver { Q_DISABLE_COPY_MOVE(QPropertyAlias) + QProperty<T> *aliasedProperty() const + { + return static_cast<QProperty<T> *>(QPropertyObserver::aliasedProperty()); + } + public: QPropertyAlias(QProperty<T> *property) : QPropertyObserver(property) @@ -501,12 +494,12 @@ public: } QPropertyAlias(QPropertyAlias<T> *alias) - : QPropertyAlias(alias->aliasedProperty<T>()) + : QPropertyAlias(alias->aliasedProperty()) {} T value() const { - if (auto *p = aliasedProperty<T>()) + if (auto *p = aliasedProperty()) return p->value(); return T(); } @@ -515,26 +508,26 @@ public: void setValue(T &&newValue) { - if (auto *p = aliasedProperty<T>()) + if (auto *p = aliasedProperty()) p->setValue(std::move(newValue)); } void setValue(const T &newValue) { - if (auto *p = aliasedProperty<T>()) + if (auto *p = aliasedProperty()) p->setValue(newValue); } QPropertyAlias<T> &operator=(T &&newValue) { - if (auto *p = aliasedProperty<T>()) + if (auto *p = aliasedProperty()) *p = std::move(newValue); return *this; } QPropertyAlias<T> &operator=(const T &newValue) { - if (auto *p = aliasedProperty<T>()) + if (auto *p = aliasedProperty()) *p = newValue; return *this; } @@ -553,21 +546,21 @@ public: QPropertyBinding<T> setBinding(const QPropertyBinding<T> &newBinding) { - if (auto *p = aliasedProperty<T>()) + if (auto *p = aliasedProperty()) return p->setBinding(newBinding); return QPropertyBinding<T>(); } QPropertyBinding<T> setBinding(QPropertyBinding<T> &&newBinding) { - if (auto *p = aliasedProperty<T>()) + if (auto *p = aliasedProperty()) return p->setBinding(std::move(newBinding)); return QPropertyBinding<T>(); } bool setBinding(const QUntypedPropertyBinding &newBinding) { - if (auto *p = aliasedProperty<T>()) + if (auto *p = aliasedProperty()) return p->setBinding(newBinding); return false; } @@ -587,21 +580,21 @@ public: bool hasBinding() const { - if (auto *p = aliasedProperty<T>()) + if (auto *p = aliasedProperty()) return p->hasBinding(); return false; } QPropertyBinding<T> binding() const { - if (auto *p = aliasedProperty<T>()) + if (auto *p = aliasedProperty()) return p->binding(); return QPropertyBinding<T>(); } QPropertyBinding<T> takeBinding() { - if (auto *p = aliasedProperty<T>()) + if (auto *p = aliasedProperty()) return p->takeBinding(); return QPropertyBinding<T>(); } @@ -609,7 +602,7 @@ public: template<typename Functor> QPropertyChangeHandler<Functor> onValueChanged(Functor f) { - if (auto *p = aliasedProperty<T>()) + if (auto *p = aliasedProperty()) return p->onValueChanged(f); return QPropertyChangeHandler<Functor>(f); } @@ -617,14 +610,14 @@ public: template<typename Functor> QPropertyChangeHandler<Functor> subscribe(Functor f) { - if (auto *p = aliasedProperty<T>()) + if (auto *p = aliasedProperty()) return p->subscribe(f); return QPropertyChangeHandler<Functor>(f); } bool isValid() const { - return aliasedProperty<T>() != nullptr; + return aliasedProperty() != nullptr; } }; QT_END_NAMESPACE |