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>
bb10
Lars Knoll 2020-08-22 10:39:42 +02:00
parent e3ea8768fc
commit ee96d705cc
2 changed files with 114 additions and 119 deletions

View File

@ -361,6 +361,8 @@ QPropertyObserver::QPropertyObserver(QUntypedPropertyData *aliasedPropertyPtr)
d.setAliasedProperty(aliasedPropertyPtr);
}
/*! \internal
*/
void QPropertyObserver::setSource(const QPropertyBindingData &property)
{
QPropertyObserverPointer d{this};

View File

@ -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