diff options
Diffstat (limited to 'src/corelib')
-rw-r--r-- | src/corelib/kernel/qproperty.cpp | 230 | ||||
-rw-r--r-- | src/corelib/kernel/qproperty.h | 203 | ||||
-rw-r--r-- | src/corelib/kernel/qtmetamacros.h | 35 |
3 files changed, 0 insertions, 468 deletions
diff --git a/src/corelib/kernel/qproperty.cpp b/src/corelib/kernel/qproperty.cpp index 17dd10e108..e3724f8f4a 100644 --- a/src/corelib/kernel/qproperty.cpp +++ b/src/corelib/kernel/qproperty.cpp @@ -801,236 +801,6 @@ QString QPropertyBindingError::description() const /*! - \class QNotifiedProperty - \inmodule QtCore - \brief The QNotifiedProperty class is a template class that enables automatic property bindings - and invokes a callback function on the surrounding class when the value changes. - - \ingroup tools - - QNotifiedProperty\<T, Callback\> is a generic container that holds an - instance of T and behaves mostly like \l QProperty. The extra template - parameter is used to identify the surrounding class and a member function of - that class. The member function will be called whenever the value held by the - property changes. - - You can use QNotifiedProperty to port code that uses Q_PROPERTY. The getter - and setter are trivial to adapt for accessing a \l QProperty rather than the - plain value. In order to invoke the change signal on property changes, use - QNotifiedProperty and pass the change signal as callback. - - \code - class MyClass : public QObject - { - \Q_OBJECT - // Replacing: Q_PROPERTY(int x READ x WRITE setX NOTIFY xChanged) - public: - int x() const { return xProp; } - void setX(int x) { xProp = x; } - - signals: - void xChanged(); - - private: - // Now you can set bindings on xProp and use it in other bindings. - QNotifiedProperty<int, &MyClass::xChanged> xProp; - }; - \endcode -*/ - -/*! - \fn template <typename T, typename Class, void(Class::*Callback)()> QNotifiedProperty<T, Callback>::QNotifiedProperty() - - Constructs a property with a default constructed instance of T. -*/ - -/*! - \fn template <typename T, typename Class, void(Class::*Callback)()> explicit QNotifiedProperty<T, Callback>::QNotifiedProperty(const T &initialValue) - - Constructs a property with the provided \a initialValue. -*/ - -/*! - \fn template <typename T, typename Class, void(Class::*Callback)()> explicit QNotifiedProperty<T, Callback>::QNotifiedProperty(T &&initialValue) - - Move-Constructs a property with the provided \a initialValue. -*/ - -/*! - \fn template <typename T, typename Class, void(Class::*Callback)()> QNotifiedProperty<T, Callback>::QNotifiedProperty(Class *owner, const QPropertyBinding<T> &binding) - - Constructs a property that is tied to the provided \a binding expression. The - first time the property value is read, the binding is evaluated. Whenever a - dependency of the binding changes, the binding will be re-evaluated the next - time the value of this property is read. When the property value changes \a - owner is notified via the Callback function. -*/ - -/*! - \fn template <typename T, typename Class, void(Class::*Callback)()> QNotifiedProperty<T, Callback>::QNotifiedProperty(Class *owner, QPropertyBinding<T> &&binding) - - Constructs a property that is tied to the provided \a binding expression. The - first time the property value is read, the binding is evaluated. Whenever a - dependency of the binding changes, the binding will be re-evaluated the next - time the value of this property is read. When the property value changes \a - owner is notified via the Callback function. -*/ - - -/*! - \fn template <typename T, typename Class, void(Class::*Callback)()> template <typename Functor> QNotifiedProperty<T, Callback>::QNotifiedProperty(Class *owner, Functor &&f) - - Constructs a property that is tied to the provided binding expression \a f. The - first time the property value is read, the binding is evaluated. Whenever a - dependency of the binding changes, the binding will be re-evaluated the next - time the value of this property is read. When the property value changes \a - owner is notified via the Callback function. -*/ - -/*! - \fn template <typename T, typename Class, void(Class::*Callback)()> QNotifiedProperty<T, Callback>::~QNotifiedProperty() - - Destroys the property. -*/ - -/*! - \fn template <typename T, typename Class, void(Class::*Callback)()> T QNotifiedProperty<T, Callback>::value() const - - Returns the value of the property. This may evaluate a binding expression that - is tied to this property, before returning the value. -*/ - -/*! - \fn template <typename T, typename Class, void(Class::*Callback)()> QNotifiedProperty<T, Callback>::operator T() const - - Returns the value of the property. This may evaluate a binding expression that - is tied to this property, before returning the value. -*/ - -/*! - \fn template <typename T, typename Class, void(Class::*Callback)()> void QNotifiedProperty<T, Callback>::setValue(Class *owner, const T &newValue) - - Assigns \a newValue to this property and removes the property's associated - binding, if present. If the property value changes as a result, calls the - Callback function on \a owner. -*/ - -/*! - \fn template <typename T, typename Class, void(Class::*Callback)()> void QNotifiedProperty<T, Callback>::setValue(Class *owner, T &&newValue) - \overload - - Assigns \a newValue to this property and removes the property's associated - binding, if present. If the property value changes as a result, calls the - Callback function on \a owner. -*/ - -/*! - \fn template <typename T, typename Class, void(Class::*Callback)()> QPropertyBinding<T> QNotifiedProperty<T, Callback>::setBinding(Class *owner, const QPropertyBinding<T> &newBinding) - - Associates the value of this property with the provided \a newBinding - expression and returns the previously associated binding. The first time the - property value is read, the binding is evaluated. Whenever a dependency of the - binding changes, the binding will be re-evaluated the next time the value of - this property is read. When the property value changes \a owner is notified - via the Callback function. -*/ - -/*! - \fn template <typename T, typename Class, void(Class::*Callback)()> template <typename Functor> QPropertyBinding<T> QNotifiedProperty<T, Callback>::setBinding(Class *owner, Functor f) - \overload - - Associates the value of this property with the provided functor \a f and - returns the previously associated binding. The first time the property value - is read, the binding is evaluated by invoking the call operator () of \a f. - Whenever a dependency of the binding changes, the binding will be re-evaluated - the next time the value of this property is read. When the property value - changes \a owner is notified via the Callback function. -*/ - -/*! - \fn template <typename T, typename Class, void(Class::*Callback)()> QPropertyBinding<T> QNotifiedProperty<T, Callback>::setBinding(Class *owner, QPropertyBinding<T> &&newBinding) - \overload - - Associates the value of this property with the provided \a newBinding - expression and returns the previously associated binding. The first time the - property value is read, the binding is evaluated. Whenever a dependency of the - binding changes, the binding will be re-evaluated the next time the value of - this property is read. When the property value changes \a owner is notified - via the Callback function. -*/ - -/*! - \fn template <typename T, typename Class, void(Class::*Callback)()> QPropertyBinding<T> bool QNotifiedProperty<T, Callback>::setBinding(Class *owner, const QUntypedPropertyBinding &newBinding) - \overload - - Associates the value of this property with the provided \a newBinding - expression. The first time the property value is read, the binding is evaluated. - Whenever a dependency of the binding changes, the binding will be re-evaluated - the next time the value of this property is read. When the property value - changes \a owner is notified via the Callback function. - - Returns true if the type of this property is the same as the type the binding - function returns; false otherwise. -*/ - -/*! - \fn template <typename T, typename Class, void(Class::*Callback)()> bool QNotifiedProperty<T, Callback>::hasBinding() const - - Returns true if the property is associated with a binding; false otherwise. -*/ - - -/*! - \fn template <typename T, typename Class, void(Class::*Callback)()> QPropertyBinding<T> QNotifiedProperty<T, Callback>::binding() const - - Returns the binding expression that is associated with this property. A - default constructed QPropertyBinding<T> will be returned if no such - association exists. -*/ - -/*! - \fn template <typename T, typename Class, void(Class::*Callback)()> QPropertyBinding<T> QNotifiedProperty<T, Callback>::takeBinding() - - Disassociates the binding expression from this property and returns it. After - calling this function, the value of the property will only change if you - assign a new value to it, or when a new binding is set. -*/ - -/*! - \fn template <typename T, typename Class, void(Class::*Callback)()> template <typename Functor> QPropertyChangeHandler<T, Functor> QNotifiedProperty<T, Callback>::onValueChanged(Functor f) - - Registers the given functor \a f as a callback that shall be called whenever - the value of the property changes. - - The callback \a f is expected to be a type that has a plain call operator () without any - parameters. This means that you can provide a C++ lambda expression, an std::function - or even a custom struct with a call operator. - - The returned property change handler object keeps track of the registration. When it - goes out of scope, the callback is de-registered. -*/ - -/*! - \fn template <typename T, typename Class, void(Class::*Callback)()> template <typename Functor> QPropertyChangeHandler<T, Functor> QNotifiedProperty<T, Callback>::subscribe(Functor f) - - Subscribes the given functor \a f as a callback that is called immediately and whenever - the value of the property changes in the future. - - The callback \a f is expected to be a type that has a plain call operator () without any - parameters. This means that you can provide a C++ lambda expression, an std::function - or even a custom struct with a call operator. - - The returned property change handler object keeps track of the subscription. When it - goes out of scope, the callback is unsubscribed. -*/ - -/*! - \fn template <typename T> QtPrivate::QPropertyBindingData &QNotifiedProperty<T, Callback>::bindingData() const - \internal -*/ - - -/*! \class QPropertyChangeHandler \inmodule QtCore \brief The QPropertyChangeHandler class controls the lifecycle of change callback installed on a QProperty. diff --git a/src/corelib/kernel/qproperty.h b/src/corelib/kernel/qproperty.h index ef738ccc5a..ff2a5c883f 100644 --- a/src/corelib/kernel/qproperty.h +++ b/src/corelib/kernel/qproperty.h @@ -366,188 +366,6 @@ namespace Qt { } } -template <typename T, auto Callback, auto ValueGuard=nullptr> -class QNotifiedProperty -{ - T val = T(); - QtPrivate::QPropertyBindingData d; - bool is_equal(const T &v) - { - if constexpr (QTypeTraits::has_operator_equal_v<T>) { - if (v == val) - return true; - } - return false; - } - -public: - using value_type = T; - using Class = typename QtPrivate::detail::ExtractClassFromFunctionPointer<decltype(Callback)>::Class; -private: - static bool constexpr ValueGuardModifiesArgument = std::is_invocable_r_v<bool, decltype(ValueGuard), Class, T&>; - static bool constexpr CallbackAcceptsOldValue = std::is_invocable_v<decltype(Callback), Class, T>; - static bool constexpr HasValueGuard = !std::is_same_v<decltype(ValueGuard), std::nullptr_t>; -public: - static_assert(CallbackAcceptsOldValue || std::is_invocable_v<decltype(Callback), Class>); - static_assert( - std::is_invocable_r_v<bool, decltype(ValueGuard), Class, T> || - ValueGuardModifiesArgument || - !HasValueGuard, - "Guard has wrong signature"); -private: - static constexpr QtPrivate::QPropertyGuardFunction GuardTE = - QtPrivate::QPropertyGuardFunctionHelper<T, Class, ValueGuard>::guard; -public: - - QNotifiedProperty() = default; - - explicit QNotifiedProperty(const T &initialValue) : val(initialValue) {} - explicit QNotifiedProperty(T &&initialValue) : val(std::move(initialValue)) {} - - QNotifiedProperty(Class *owner, const QPropertyBinding<T> &binding) - : QNotifiedProperty() - { setBinding(owner, binding); } - QNotifiedProperty(Class *owner, QPropertyBinding<T> &&binding) - : QNotifiedProperty() - { setBinding(owner, std::move(binding)); } - -#ifndef Q_CLANG_QDOC - template <typename Functor> - explicit QNotifiedProperty(Class *owner, Functor &&f, const QPropertyBindingSourceLocation &location = QT_PROPERTY_DEFAULT_BINDING_LOCATION, - typename std::enable_if_t<std::is_invocable_r_v<T, Functor&>> * = 0) - : QNotifiedProperty(QPropertyBinding<T>(owner, std::forward<Functor>(f), location)) - {} -#else - template <typename Functor> - explicit QNotifiedProperty(Class *owner, Functor &&f); -#endif - - ~QNotifiedProperty() = default; - - T value() const - { - if (d.hasBinding()) - d.evaluateIfDirty(); - d.registerWithCurrentlyEvaluatingBinding(); - return val; - } - - operator T() const - { - return value(); - } - - template<typename S> - auto setValue(Class *owner, S &&newValue) -> std::enable_if_t<!ValueGuardModifiesArgument && std::is_same_v<S, T>, void> - { - if constexpr (HasValueGuard) { - if (!(owner->*ValueGuard)(newValue)) - return; - } - if (is_equal(newValue)) - return; - if constexpr (CallbackAcceptsOldValue) { - T oldValue = value(); - val = std::move(newValue); - notify(owner, &oldValue); - } else { - val = std::move(newValue); - notify(owner); - } - d.removeBinding(); - } - - void setValue(Class *owner, std::conditional_t<ValueGuardModifiesArgument, T, const T &> newValue) - { - if constexpr (HasValueGuard) { - if (!(owner->*ValueGuard)(newValue)) - return; - } - if (is_equal(newValue)) - return; - if constexpr (CallbackAcceptsOldValue) { - T oldValue = value(); - val = newValue; - notify(owner, &oldValue); - } else { - val = newValue; - notify(owner); - } - d.removeBinding(); - } - - QPropertyBinding<T> setBinding(Class *owner, const QPropertyBinding<T> &newBinding) - { - if constexpr (CallbackAcceptsOldValue) { - T oldValue = value(); - QPropertyBinding<T> oldBinding(d.setBinding(newBinding, &val, owner, [](void *o, void *oldVal) { - (reinterpret_cast<Class *>(o)->*Callback)(*reinterpret_cast<T *>(oldVal)); - }, GuardTE)); - notify(owner, &oldValue); - return oldBinding; - } else { - QPropertyBinding<T> oldBinding(d.setBinding(newBinding, &val, owner, [](void *o, void *) { - (reinterpret_cast<Class *>(o)->*Callback)(); - }, GuardTE)); - notify(owner); - return oldBinding; - } - } - - bool setBinding(Class *owner, const QUntypedPropertyBinding &newBinding) - { - if (newBinding.valueMetaType().id() != qMetaTypeId<T>()) - return false; - setBinding(owner, static_cast<const QPropertyBinding<T> &>(newBinding)); - return true; - } - -#ifndef Q_CLANG_QDOC - template <typename Functor> - QPropertyBinding<T> setBinding(Class *owner, Functor &&f, - const QPropertyBindingSourceLocation &location = QT_PROPERTY_DEFAULT_BINDING_LOCATION, - std::enable_if_t<std::is_invocable_v<Functor>> * = nullptr) - { - return setBinding(owner, Qt::makePropertyBinding(std::forward<Functor>(f), location)); - } -#else - template <typename Functor> - QPropertyBinding<T> setBinding(Class *owner, Functor f); -#endif - - bool hasBinding() const { return d.hasBinding(); } - - QPropertyBinding<T> binding() const - { - return QPropertyBinding<T>(*this); - } - - QPropertyBinding<T> takeBinding() - { - return QPropertyBinding<T>(d.setBinding(QUntypedPropertyBinding(), &d)); - } - - template<typename Functor> - QPropertyChangeHandler<Functor> onValueChanged(Functor f); - template<typename Functor> - QPropertyChangeHandler<Functor> subscribe(Functor f); - - const QtPrivate::QPropertyBindingData &bindingData() const { return d; } -private: - void notify(Class *owner, T *oldValue=nullptr) - { - d.notifyObservers(&d); - if constexpr (std::is_invocable_v<decltype(Callback), Class>) { - Q_UNUSED(oldValue); - (owner->*Callback)(); - } else { - (owner->*Callback)(*oldValue); - } - } - - Q_DISABLE_COPY_MOVE(QNotifiedProperty) -}; - struct QPropertyObserverPrivate; struct QPropertyObserverPointer; @@ -649,27 +467,6 @@ QPropertyChangeHandler<Functor> QProperty<T>::subscribe(Functor f) return onValueChanged(f); } -template <typename T, auto Callback, auto ValueGuard> -template<typename Functor> -QPropertyChangeHandler<Functor> QNotifiedProperty<T, Callback, ValueGuard>::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, auto Callback, auto ValueGuard> -template<typename Functor> -QPropertyChangeHandler<Functor> QNotifiedProperty<T, Callback, ValueGuard>::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 { diff --git a/src/corelib/kernel/qtmetamacros.h b/src/corelib/kernel/qtmetamacros.h index 8612cc4fc5..96b1ada57e 100644 --- a/src/corelib/kernel/qtmetamacros.h +++ b/src/corelib/kernel/qtmetamacros.h @@ -91,41 +91,6 @@ QT_BEGIN_NAMESPACE #define Q_INTERFACES(x) QT_ANNOTATE_CLASS(qt_interfaces, x) #define Q_PROPERTY(...) QT_ANNOTATE_CLASS(qt_property, __VA_ARGS__) #define Q_PRIVATE_PROPERTY(d, text) QT_ANNOTATE_CLASS2(qt_private_property, d, text) -#define Q_PRIVATE_QPROPERTY(accessor, type, name, setter, ...) \ - struct _qt_property_api_##name { \ - type value() const; \ - type operator()() const { return value(); } \ - void setValue(type &&); \ - void setValue(type const &); \ - void operator=(type const &v) { setValue(v); } \ - void operator=(type &&v) { setValue(std::move(v)); } \ - QPropertyBinding<type> setBinding(const QPropertyBinding<type> &); \ - QPropertyBinding<type> setBinding(QPropertyBinding<type> &&); \ - QPropertyBinding<type> operator=(const QPropertyBinding<type> &b) { return setBinding(b); } \ - QPropertyBinding<type> operator=(QPropertyBinding<type> &&b) { return setBinding(std::move(b)); } \ - bool setBinding(const QUntypedPropertyBinding &); \ - template <typename Functor> \ - QPropertyBinding<type> setBinding(Functor f, \ - const QPropertyBindingSourceLocation &location = QT_PROPERTY_DEFAULT_BINDING_LOCATION) \ - { \ - return setBinding(Qt::makePropertyBinding(f, location)); \ - } \ - bool hasBinding() const; \ - QPropertyBinding<type> binding() const; \ - QPropertyBinding<type> takeBinding(); \ - }; \ - void setter(type const& value); -#if __has_cpp_attribute(no_unique_address) -#define Q_PRIVATE_QPROPERTIES_BEGIN -#define QT_PRIVATE_QPROPERTY_PREFIX [[no_unique_address]] -#define Q_PRIVATE_QPROPERTIES_END -#else -#define Q_PRIVATE_QPROPERTIES_BEGIN union { -#define QT_PRIVATE_QPROPERTY_PREFIX -#define Q_PRIVATE_QPROPERTIES_END }; -#endif -#define Q_PRIVATE_QPROPERTY_IMPL(name) \ - QT_PRIVATE_QPROPERTY_PREFIX _qt_property_api_##name name; #ifndef Q_REVISION # define Q_REVISION(...) #endif |