summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/corelib/kernel/qproperty.h258
-rw-r--r--tests/auto/corelib/kernel/qproperty/tst_qproperty.cpp37
2 files changed, 163 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;
diff --git a/tests/auto/corelib/kernel/qproperty/tst_qproperty.cpp b/tests/auto/corelib/kernel/qproperty/tst_qproperty.cpp
index f5652eb599..9bc2ce26b6 100644
--- a/tests/auto/corelib/kernel/qproperty/tst_qproperty.cpp
+++ b/tests/auto/corelib/kernel/qproperty/tst_qproperty.cpp
@@ -78,6 +78,7 @@ private slots:
void qobjectObservers();
void compatBindings();
void metaProperty();
+ void aliasOnMetaProperty();
};
void tst_QProperty::functorBinding()
@@ -1210,6 +1211,42 @@ void tst_QProperty::metaProperty()
QCOMPARE(object.fooData.value(), 1);
}
+void tst_QProperty::aliasOnMetaProperty()
+{
+ MyQObject object;
+ QPropertyAlias<int> alias(object.bindableFoo());
+
+ QVERIFY(alias.isValid());
+ QCOMPARE(alias.value(), object.foo());
+ QVERIFY(!alias.hasBinding());
+
+ object.setFoo(42);
+ QCOMPARE(alias.value(), 42);
+
+ auto f = [&object]() -> int {
+ return object.barData;
+ };
+ object.bindableFoo().setBinding(f);
+ QVERIFY(alias.hasBinding());
+ QCOMPARE(alias.value(), object.bar());
+
+ object.setBar(111);
+ QCOMPARE(alias.value(), 111);
+
+ int changedCount = 0;
+ auto observer = alias.onValueChanged([&changedCount]() { ++changedCount; });
+ QCOMPARE(changedCount, 0);
+ object.setBar(666);
+ QCOMPARE(changedCount, 1);
+
+ alias.setBinding([&object]() { return object.read(); });
+ QCOMPARE(changedCount, 2);
+ QCOMPARE(alias.value(), 0);
+ object.readData = 100;
+ QCOMPARE(changedCount, 3);
+ QCOMPARE(alias.value(), 100);
+}
+
QTEST_MAIN(tst_QProperty);
#include "tst_qproperty.moc"