diff options
author | Lars Knoll <lars.knoll@qt.io> | 2020-08-29 14:02:36 +0200 |
---|---|---|
committer | Lars Knoll <lars.knoll@qt.io> | 2020-09-02 22:44:29 +0200 |
commit | 927647cd032cd2e43bae3184b879586849ffee50 (patch) | |
tree | edbd80d955448306e273cb136f21e5f514c5d86a /src | |
parent | 91a24f6cd71f03b001dc6a0a8dba23efe744033d (diff) |
Fix QPropertyAlias to work with all kinds of properties
So far QPropertyAlias was limited to working with QProperty<T>.
Change the implementation, so it can be constructed from any
property or even a QBindable<T>.
Change-Id: I175cffe94a9ef332367d39faa976eb065b0e6ffe
Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org>
Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
Diffstat (limited to 'src')
-rw-r--r-- | src/corelib/kernel/qproperty.h | 258 |
1 files changed, 126 insertions, 132 deletions
diff --git a/src/corelib/kernel/qproperty.h b/src/corelib/kernel/qproperty.h index 7ba2d9514a..2941de2c54 100644 --- a/src/corelib/kernel/qproperty.h +++ b/src/corelib/kernel/qproperty.h @@ -473,138 +473,6 @@ namespace Qt { } } -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) - { - if (property) - setSource(*property); - } - - QPropertyAlias(QPropertyAlias<T> *alias) - : QPropertyAlias(alias->aliasedProperty()) - {} - - T value() const - { - if (auto *p = aliasedProperty()) - return p->value(); - return T(); - } - - operator T() const { return value(); } - - void setValue(T &&newValue) - { - if (auto *p = aliasedProperty()) - p->setValue(std::move(newValue)); - } - - void setValue(const T &newValue) - { - if (auto *p = aliasedProperty()) - p->setValue(newValue); - } - - QPropertyAlias<T> &operator=(T &&newValue) - { - if (auto *p = aliasedProperty()) - *p = std::move(newValue); - return *this; - } - - QPropertyAlias<T> &operator=(const T &newValue) - { - if (auto *p = aliasedProperty()) - *p = newValue; - return *this; - } - - QPropertyBinding<T> setBinding(const QPropertyBinding<T> &newBinding) - { - if (auto *p = aliasedProperty()) - return p->setBinding(newBinding); - return QPropertyBinding<T>(); - } - - QPropertyBinding<T> setBinding(QPropertyBinding<T> &&newBinding) - { - if (auto *p = aliasedProperty()) - return p->setBinding(std::move(newBinding)); - return QPropertyBinding<T>(); - } - - bool setBinding(const QUntypedPropertyBinding &newBinding) - { - if (auto *p = aliasedProperty()) - return p->setBinding(newBinding); - return false; - } - -#ifndef Q_CLANG_QDOC - template <typename Functor> - QPropertyBinding<T> setBinding(Functor &&f, - const QPropertyBindingSourceLocation &location = QT_PROPERTY_DEFAULT_BINDING_LOCATION, - std::enable_if_t<std::is_invocable_v<Functor>> * = nullptr) - { - return setBinding(Qt::makePropertyBinding(std::forward<Functor>(f), location)); - } -#else - template <typename Functor> - QPropertyBinding<T> setBinding(Functor f); -#endif - - bool hasBinding() const - { - if (auto *p = aliasedProperty()) - return p->hasBinding(); - return false; - } - - QPropertyBinding<T> binding() const - { - if (auto *p = aliasedProperty()) - return p->binding(); - return QPropertyBinding<T>(); - } - - QPropertyBinding<T> takeBinding() - { - if (auto *p = aliasedProperty()) - return p->takeBinding(); - return QPropertyBinding<T>(); - } - - template<typename Functor> - QPropertyChangeHandler<Functor> onValueChanged(Functor f) - { - if (auto *p = aliasedProperty()) - return p->onValueChanged(f); - return QPropertyChangeHandler<Functor>(f); - } - - template<typename Functor> - QPropertyChangeHandler<Functor> subscribe(Functor f) - { - if (auto *p = aliasedProperty()) - return p->subscribe(f); - return QPropertyChangeHandler<Functor>(f); - } - - bool isValid() const - { - return aliasedProperty() != nullptr; - } -}; namespace QtPrivate { @@ -677,6 +545,9 @@ class QUntypedBindable protected: QUntypedPropertyData *data = nullptr; const QtPrivate::QBindableInterface *iface = nullptr; + constexpr QUntypedBindable(QUntypedPropertyData *d, const QtPrivate::QBindableInterface *i) + : data(d), iface(i) + {} public: constexpr QUntypedBindable() = default; @@ -739,6 +610,11 @@ public: template<typename T> class QBindable : public QUntypedBindable { + template<typename U> + friend class QPropertyAlias; + constexpr QBindable(QUntypedPropertyData *d, const QtPrivate::QBindableInterface *i) + : QUntypedBindable(d, i) + {} public: using QUntypedBindable::QUntypedBindable; explicit QBindable(const QUntypedBindable &b) : QUntypedBindable(b) @@ -777,6 +653,124 @@ public: #endif }; +template<typename T> +class QPropertyAlias : public QPropertyObserver +{ + Q_DISABLE_COPY_MOVE(QPropertyAlias) + const QtPrivate::QBindableInterface *iface = nullptr; + +public: + QPropertyAlias(QProperty<T> *property) + : QPropertyObserver(property), + iface(&QtPrivate::QBindableInterfaceForProperty<QProperty<T>>::iface) + { + if (iface) + iface->setObserver(aliasedProperty(), this); + } + + template<typename Property, typename = typename Property::InheritsQUntypedPropertyData> + QPropertyAlias(Property *property) + : QPropertyObserver(property), + iface(&QtPrivate::QBindableInterfaceForProperty<Property>::iface) + { + if (iface) + iface->setObserver(aliasedProperty(), this); + } + + QPropertyAlias(QPropertyAlias<T> *alias) + : QPropertyObserver(alias->aliasedProperty()), + iface(alias->iface) + { + if (iface) + iface->setObserver(aliasedProperty(), this); + } + + QPropertyAlias(const QBindable<T> &property) + : QPropertyObserver(property.data), + iface(property.iface) + { + if (iface) + iface->setObserver(aliasedProperty(), this); + } + + T value() const + { + T t = T(); + if (auto *p = aliasedProperty()) + iface->getter(p, &t); + return t; + } + + operator T() const { return value(); } + + void setValue(const T &newValue) + { + if (auto *p = aliasedProperty()) + iface->setter(p, &newValue); + } + + QPropertyAlias<T> &operator=(const T &newValue) + { + setValue(newValue); + return *this; + } + + QPropertyBinding<T> setBinding(const QPropertyBinding<T> &newBinding) + { + return QBindable<T>(aliasedProperty(), iface).setBinding(newBinding); + } + + bool setBinding(const QUntypedPropertyBinding &newBinding) + { + return QBindable<T>(aliasedProperty(), iface).setBinding(newBinding); + } + +#ifndef Q_CLANG_QDOC + template <typename Functor> + QPropertyBinding<T> setBinding(Functor &&f, + const QPropertyBindingSourceLocation &location = QT_PROPERTY_DEFAULT_BINDING_LOCATION, + std::enable_if_t<std::is_invocable_v<Functor>> * = nullptr) + { + return setBinding(Qt::makePropertyBinding(std::forward<Functor>(f), location)); + } +#else + template <typename Functor> + QPropertyBinding<T> setBinding(Functor f); +#endif + + bool hasBinding() const + { + return QBindable<T>(aliasedProperty(), iface).hasBinding(); + } + + QPropertyBinding<T> binding() const + { + return QBindable<T>(aliasedProperty(), iface).binding(); + } + + QPropertyBinding<T> takeBinding() + { + return QBindable<T>(aliasedProperty(), iface).takeBinding(); + } + + template<typename Functor> + QPropertyChangeHandler<Functor> onValueChanged(Functor f) + { + return QBindable<T>(aliasedProperty(), iface).onValueChanged(f); + } + + template<typename Functor> + QPropertyChangeHandler<Functor> subscribe(Functor f) + { + return QBindable<T>(aliasedProperty(), iface).subscribe(f); + } + + bool isValid() const + { + return aliasedProperty() != nullptr; + } +}; + struct QBindingStatus; struct QBindingStorageData; |