summaryrefslogtreecommitdiffstats
path: root/src/corelib/kernel/qproperty.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/corelib/kernel/qproperty.h')
-rw-r--r--src/corelib/kernel/qproperty.h146
1 files changed, 144 insertions, 2 deletions
diff --git a/src/corelib/kernel/qproperty.h b/src/corelib/kernel/qproperty.h
index 76c41f356c..e2a6172d84 100644
--- a/src/corelib/kernel/qproperty.h
+++ b/src/corelib/kernel/qproperty.h
@@ -85,6 +85,7 @@ struct Q_CORE_EXPORT QPropertyBindingSourceLocation
template <typename Functor> class QPropertyChangeHandler;
template <typename T> class QProperty;
+template <typename T, auto callbackMember> class QNotifiedProperty;
class QPropertyBindingErrorPrivate;
@@ -178,12 +179,15 @@ public:
: QUntypedPropertyBinding(property.d.priv.binding())
{}
-private:
+ template<auto notifier>
+ QPropertyBinding(const QNotifiedProperty<PropertyType, notifier> &property)
+ : QUntypedPropertyBinding(property.d.priv.binding())
+ {}
+
// Internal
explicit QPropertyBinding(const QUntypedPropertyBinding &binding)
: QUntypedPropertyBinding(binding)
{}
- friend class QProperty<PropertyType>;
};
namespace QtPrivate {
@@ -370,6 +374,140 @@ namespace Qt {
}
}
+template <typename T, typename Class, void(Class::*Callback)()>
+class QNotifiedProperty<T, Callback>
+{
+public:
+ using value_type = T;
+
+ QNotifiedProperty() = default;
+
+ explicit QNotifiedProperty(const T &initialValue) : d(initialValue) {}
+ explicit QNotifiedProperty(T &&initialValue) : d(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 QProperty(Class *owner, Functor &&f);
+#endif
+
+ ~QNotifiedProperty() = default;
+
+ T value() const
+ {
+ if (d.priv.hasBinding())
+ d.priv.evaluateIfDirty();
+ d.priv.registerWithCurrentlyEvaluatingBinding();
+ return d.getValue();
+ }
+
+ operator T() const
+ {
+ return value();
+ }
+
+ void setValue(Class *owner, T &&newValue)
+ {
+ if (d.setValueAndReturnTrueIfChanged(std::move(newValue)))
+ notify(owner);
+ d.priv.removeBinding();
+ }
+
+ void setValue(Class *owner, const T &newValue)
+ {
+ if (d.setValueAndReturnTrueIfChanged(newValue))
+ notify(owner);
+ d.priv.removeBinding();
+ }
+
+ QPropertyBinding<T> setBinding(Class *owner, const QPropertyBinding<T> &newBinding)
+ {
+ QPropertyBinding<T> oldBinding(d.priv.setBinding(newBinding, &d, owner, [](void *o) {
+ (reinterpret_cast<Class *>(o)->*Callback)();
+ }));
+ notify(owner);
+ return oldBinding;
+ }
+
+ QPropertyBinding<T> setBinding(Class *owner, QPropertyBinding<T> &&newBinding)
+ {
+ QPropertyBinding<T> b(std::move(newBinding));
+ QPropertyBinding<T> oldBinding(d.priv.setBinding(b, &d, owner, [](void *o) {
+ (reinterpret_cast<Class *>(o)->*Callback)();
+ }));
+ notify(owner);
+ return oldBinding;
+ }
+
+ bool setBinding(Class *owner, const QUntypedPropertyBinding &newBinding)
+ {
+ if (newBinding.valueMetaType().id() != qMetaTypeId<T>())
+ return false;
+ d.priv.setBinding(newBinding, &d, owner, [](void *o) {
+ (reinterpret_cast<Class *>(o)->*Callback)();
+ });
+ notify(owner);
+ 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.priv.hasBinding(); }
+
+ QPropertyBinding<T> binding() const
+ {
+ return QPropertyBinding<T>(*this);
+ }
+
+ QPropertyBinding<T> takeBinding()
+ {
+ return QPropertyBinding<T>(d.priv.setBinding(QUntypedPropertyBinding(), &d));
+ }
+
+ template<typename Functor>
+ QPropertyChangeHandler<Functor> onValueChanged(Functor f);
+ template<typename Functor>
+ QPropertyChangeHandler<Functor> subscribe(Functor f);
+
+private:
+ void notify(Class *owner)
+ {
+ d.priv.notifyObservers(&d);
+ (owner->*Callback)();
+ }
+
+ Q_DISABLE_COPY_MOVE(QNotifiedProperty)
+
+ friend class QPropertyBinding<T>;
+ friend class QPropertyObserver;
+ // Mutable because querying for the value may require evalating the binding expression, calling
+ // non-const functions on QPropertyBase.
+ mutable QtPrivate::QPropertyValueStorage<T> d;
+};
+
struct QPropertyObserverPrivate;
struct QPropertyObserverPointer;
@@ -392,6 +530,10 @@ public:
void setSource(const QProperty<PropertyType> &property)
{ setSource(property.d.priv); }
+ template <typename PropertyType, auto notifier>
+ void setSource(const QNotifiedProperty<PropertyType, notifier> &property)
+ { setSource(property.d.priv); }
+
protected:
QPropertyObserver(void (*callback)(QPropertyObserver*, void *));
QPropertyObserver(void *aliasedPropertyPtr);