Remove QNotifiedProperty and Q_PRIVATE_QPROPERTY
And all related functionality. This is being replaced by Q_BINDABLE_PROPERTY and Q_OBJECT_BINDABLE_PROPERTY in the next few commits. The new infrastructure coming will play nicer along with the existing property system. Commented out some autotests, that will get reimplemented with the updated infrastructure. Change-Id: I50c30bd4d5c6c6b6471f8eb93870e27d86f5a009 Reviewed-by: Ulf Hermann <ulf.hermann@qt.io>
This commit is contained in:
parent
e638e8a28d
commit
e6988d4d0b
@ -800,236 +800,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
|
\class QPropertyChangeHandler
|
||||||
\inmodule QtCore
|
\inmodule QtCore
|
||||||
|
@ -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 QPropertyObserverPrivate;
|
||||||
struct QPropertyObserverPointer;
|
struct QPropertyObserverPointer;
|
||||||
|
|
||||||
@ -649,27 +467,6 @@ QPropertyChangeHandler<Functor> QProperty<T>::subscribe(Functor f)
|
|||||||
return onValueChanged(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>
|
template<typename T>
|
||||||
class QPropertyAlias : public QPropertyObserver
|
class QPropertyAlias : public QPropertyObserver
|
||||||
{
|
{
|
||||||
|
@ -91,41 +91,6 @@ QT_BEGIN_NAMESPACE
|
|||||||
#define Q_INTERFACES(x) QT_ANNOTATE_CLASS(qt_interfaces, x)
|
#define Q_INTERFACES(x) QT_ANNOTATE_CLASS(qt_interfaces, x)
|
||||||
#define Q_PROPERTY(...) QT_ANNOTATE_CLASS(qt_property, __VA_ARGS__)
|
#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_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
|
#ifndef Q_REVISION
|
||||||
# define Q_REVISION(...)
|
# define Q_REVISION(...)
|
||||||
#endif
|
#endif
|
||||||
|
@ -670,11 +670,6 @@ void Generator::generateCode()
|
|||||||
for (int signalindex = 0; signalindex < cdef->signalList.size(); ++signalindex)
|
for (int signalindex = 0; signalindex < cdef->signalList.size(); ++signalindex)
|
||||||
generateSignal(&cdef->signalList[signalindex], signalindex);
|
generateSignal(&cdef->signalList[signalindex], signalindex);
|
||||||
|
|
||||||
//
|
|
||||||
// Generate QProperty forwarding API
|
|
||||||
//
|
|
||||||
generateQPropertyApi();
|
|
||||||
|
|
||||||
//
|
//
|
||||||
// Generate plugin meta data
|
// Generate plugin meta data
|
||||||
//
|
//
|
||||||
@ -1317,46 +1312,21 @@ void Generator::generateStaticMetacall()
|
|||||||
prefix += p.inPrivateClass + "->";
|
prefix += p.inPrivateClass + "->";
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!p.qpropertyname.isEmpty() && p.stored != "true") {
|
if (p.gspec == PropertyDef::PointerSpec)
|
||||||
// nullptr checks needed.
|
fprintf(out, " case %d: _a[0] = const_cast<void*>(reinterpret_cast<const void*>(%s%s())); break;\n",
|
||||||
fprintf(out, " case %d:\n", propindex);
|
propindex, prefix.constData(), p.read.constData());
|
||||||
if (p.gspec == PropertyDef::PointerSpec || p.gspec == PropertyDef::ReferenceSpec) {
|
else if (p.gspec == PropertyDef::ReferenceSpec)
|
||||||
fprintf(out, " if (auto *source = %s%s)\n", prefix.constData(), p.qpropertyname.constData());
|
fprintf(out, " case %d: _a[0] = const_cast<void*>(reinterpret_cast<const void*>(&%s%s())); break;\n",
|
||||||
fprintf(out, " _a[0] = const_cast<void*>(reinterpret_cast<const void*>(%ssource->value()));\n", p.gspec == PropertyDef::ReferenceSpec ? "&" : "");
|
propindex, prefix.constData(), p.read.constData());
|
||||||
fprintf(out, " else\n");
|
else if (cdef->enumDeclarations.value(p.type, false))
|
||||||
fprintf(out, " _a[0] = nullptr;\n");
|
fprintf(out, " case %d: *reinterpret_cast<int*>(_v) = QFlag(%s%s()); break;\n",
|
||||||
} else if (cdef->enumDeclarations.value(p.type, false)) {
|
propindex, prefix.constData(), p.read.constData());
|
||||||
fprintf(out, " if (auto *source = %s%s)\n", prefix.constData(), p.qpropertyname.constData());
|
else if (!p.read.isEmpty())
|
||||||
fprintf(out, " *reinterpret_cast<int*>(_v) = QFlag(source->value()));\n");
|
fprintf(out, " case %d: *reinterpret_cast< %s*>(_v) = %s%s(); break;\n",
|
||||||
fprintf(out, " else\n");
|
propindex, p.type.constData(), prefix.constData(), p.read.constData());
|
||||||
fprintf(out, " *reinterpret_cast<int*>(_v) = QFlag(%s())\n;", p.type.constData());
|
else
|
||||||
} else if (!p.read.isEmpty()) {
|
fprintf(out, " case %d: *reinterpret_cast< %s*>(_v) = %s%s; break;\n",
|
||||||
fprintf(out, " if (auto *source = %s%s)\n", prefix.constData(), p.qpropertyname.constData());
|
propindex, p.type.constData(), prefix.constData(), p.member.constData());
|
||||||
fprintf(out, " *reinterpret_cast<%s*>(_v) = source->value();\n", p.type.constData());
|
|
||||||
fprintf(out, " else\n");
|
|
||||||
fprintf(out, " *reinterpret_cast<%s*>(_v) = %s()\n;", p.type.constData(), p.type.constData());
|
|
||||||
} else {
|
|
||||||
fprintf(out, " *reinterpret_cast< %s*>(_v) = %s%s;\n",
|
|
||||||
p.type.constData(), prefix.constData(), p.member.constData());
|
|
||||||
}
|
|
||||||
fprintf(out, " break;\n");
|
|
||||||
} else {
|
|
||||||
if (p.gspec == PropertyDef::PointerSpec)
|
|
||||||
fprintf(out, " case %d: _a[0] = const_cast<void*>(reinterpret_cast<const void*>(%s%s())); break;\n",
|
|
||||||
propindex, prefix.constData(), p.read.constData());
|
|
||||||
else if (p.gspec == PropertyDef::ReferenceSpec)
|
|
||||||
fprintf(out, " case %d: _a[0] = const_cast<void*>(reinterpret_cast<const void*>(&%s%s())); break;\n",
|
|
||||||
propindex, prefix.constData(), p.read.constData());
|
|
||||||
else if (cdef->enumDeclarations.value(p.type, false))
|
|
||||||
fprintf(out, " case %d: *reinterpret_cast<int*>(_v) = QFlag(%s%s()); break;\n",
|
|
||||||
propindex, prefix.constData(), p.read.constData());
|
|
||||||
else if (!p.read.isEmpty())
|
|
||||||
fprintf(out, " case %d: *reinterpret_cast< %s*>(_v) = %s%s(); break;\n",
|
|
||||||
propindex, p.type.constData(), prefix.constData(), p.read.constData());
|
|
||||||
else
|
|
||||||
fprintf(out, " case %d: *reinterpret_cast< %s*>(_v) = %s%s; break;\n",
|
|
||||||
propindex, p.type.constData(), prefix.constData(), p.member.constData());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
fprintf(out, " default: break;\n");
|
fprintf(out, " default: break;\n");
|
||||||
fprintf(out, " }\n");
|
fprintf(out, " }\n");
|
||||||
@ -1382,35 +1352,11 @@ void Generator::generateStaticMetacall()
|
|||||||
prefix += p.inPrivateClass + "->";
|
prefix += p.inPrivateClass + "->";
|
||||||
}
|
}
|
||||||
if (cdef->enumDeclarations.value(p.type, false)) {
|
if (cdef->enumDeclarations.value(p.type, false)) {
|
||||||
if (!p.qpropertyname.isEmpty() && p.stored != "true") {
|
fprintf(out, " case %d: %s%s(QFlag(*reinterpret_cast<int*>(_v))); break;\n",
|
||||||
fprintf(out, " case %d:\n", propindex);
|
propindex, prefix.constData(), p.write.constData());
|
||||||
fprintf(out, " if (auto *destination = %s%s)\n", prefix.constData(), p.qpropertyname.constData());
|
|
||||||
fprintf(out, " destination->setValue(QFlag(*reinterpret_cast<int*>(_v)));");
|
|
||||||
fprintf(out, " break;");
|
|
||||||
} else {
|
|
||||||
fprintf(out, " case %d: %s%s(QFlag(*reinterpret_cast<int*>(_v))); break;\n",
|
|
||||||
propindex, prefix.constData(), p.write.constData());
|
|
||||||
}
|
|
||||||
} else if (!p.write.isEmpty()) {
|
} else if (!p.write.isEmpty()) {
|
||||||
QByteArray optionalQPropertyOwner;
|
fprintf(out, " case %d: %s%s(*reinterpret_cast< %s*>(_v)); break;\n",
|
||||||
if (p.isQPropertyWithNotifier) {
|
propindex, prefix.constData(), p.write.constData(), p.type.constData());
|
||||||
optionalQPropertyOwner = "_t";
|
|
||||||
if (p.inPrivateClass.size()) {
|
|
||||||
optionalQPropertyOwner += "->";
|
|
||||||
optionalQPropertyOwner += p.inPrivateClass;
|
|
||||||
}
|
|
||||||
optionalQPropertyOwner += ", ";
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!p.qpropertyname.isEmpty() && p.stored != "true") {
|
|
||||||
fprintf(out, " case %d:\n", propindex);
|
|
||||||
fprintf(out, " if (auto *destination = %s%s)\n", prefix.constData(), p.qpropertyname.constData());
|
|
||||||
fprintf(out, " destination->setValue(%s*reinterpret_cast<%s*>(_v));\n", optionalQPropertyOwner.constData(), p.type.constData());
|
|
||||||
fprintf(out, " break;\n");
|
|
||||||
} else {
|
|
||||||
fprintf(out, " case %d: %s%s(%s*reinterpret_cast< %s*>(_v)); break;\n",
|
|
||||||
propindex, prefix.constData(), p.write.constData(), optionalQPropertyOwner.constData(), p.type.constData());
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
fprintf(out, " case %d:\n", propindex);
|
fprintf(out, " case %d:\n", propindex);
|
||||||
fprintf(out, " if (%s%s != *reinterpret_cast< %s*>(_v)) {\n",
|
fprintf(out, " if (%s%s != *reinterpret_cast< %s*>(_v)) {\n",
|
||||||
@ -1458,6 +1404,7 @@ void Generator::generateStaticMetacall()
|
|||||||
}
|
}
|
||||||
fprintf(out, " }");
|
fprintf(out, " }");
|
||||||
|
|
||||||
|
#if 0
|
||||||
fprintf(out, " else ");
|
fprintf(out, " else ");
|
||||||
fprintf(out, "if (_c == QMetaObject::RegisterQPropertyObserver) {\n");
|
fprintf(out, "if (_c == QMetaObject::RegisterQPropertyObserver) {\n");
|
||||||
if (haveQProperties) {
|
if (haveQProperties) {
|
||||||
@ -1469,16 +1416,12 @@ void Generator::generateStaticMetacall()
|
|||||||
if (!p.isQProperty)
|
if (!p.isQProperty)
|
||||||
continue;
|
continue;
|
||||||
QByteArray prefix = "_t->";
|
QByteArray prefix = "_t->";
|
||||||
if (p.inPrivateClass.size()) {
|
|
||||||
prefix += p.inPrivateClass + "->";
|
|
||||||
}
|
|
||||||
if (p.qpropertyname.isEmpty() || p.stored == "true") {
|
if (p.qpropertyname.isEmpty() || p.stored == "true") {
|
||||||
fprintf(out, " case %d: observer->setSource(%s%s); break;\n",
|
fprintf(out, " case %d: observer->setSource(%s%s); break;\n",
|
||||||
propindex, prefix.constData(),
|
propindex, prefix.constData(), p.bindingAccessor.constData());
|
||||||
p.qpropertyname.isEmpty() ? p.name.constData() : p.qpropertyname.constData());
|
|
||||||
} else {
|
} else {
|
||||||
fprintf(out, " case %d: if (auto *source = %s%s) observer->setSource(*source); break; \n",
|
fprintf(out, " case %d: if (auto *source = %s%s) observer->setSource(*source); break; \n",
|
||||||
propindex, prefix.constData(), p.qpropertyname.constData());
|
propindex, prefix.constData(), p.bindingAccessor.constData());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fprintf(out, " default: break;\n");
|
fprintf(out, " default: break;\n");
|
||||||
@ -1496,26 +1439,16 @@ void Generator::generateStaticMetacall()
|
|||||||
if (!p.isQProperty)
|
if (!p.isQProperty)
|
||||||
continue;
|
continue;
|
||||||
QByteArray prefix = "_t->";
|
QByteArray prefix = "_t->";
|
||||||
QByteArray objectAccessor = "_t";
|
|
||||||
if (p.inPrivateClass.size()) {
|
|
||||||
prefix += p.inPrivateClass + "->";
|
|
||||||
objectAccessor += "->";
|
|
||||||
objectAccessor += p.inPrivateClass;
|
|
||||||
}
|
|
||||||
if (p.isQPropertyWithNotifier)
|
|
||||||
objectAccessor += ", ";
|
|
||||||
else
|
|
||||||
objectAccessor.clear();
|
|
||||||
|
|
||||||
if (p.qpropertyname.isEmpty() || p.stored == "true") {
|
if (p.qpropertyname.isEmpty() || p.stored == "true") {
|
||||||
fprintf(out, " case %d: %s%s.setBinding(%s*reinterpret_cast<QPropertyBinding<%s> *>(_a[0])); break;\n",
|
fprintf(out, " case %d: %s%s.setBinding(*reinterpret_cast<QPropertyBinding<%s> *>(_a[0])); break;\n",
|
||||||
propindex, prefix.constData(),
|
propindex, prefix.constData(),
|
||||||
p.qpropertyname.isEmpty() ? p.name.constData() : p.qpropertyname.constData(),
|
p.bindingAccessor.constData(),
|
||||||
objectAccessor.constData(), p.type.constData());
|
p.type.constData());
|
||||||
} else {
|
} else {
|
||||||
fprintf(out, " case %d: if (auto *source = %s%s) source->setBinding(%s*reinterpret_cast<QPropertyBinding<%s> *>(_a[0])); break;\n",
|
fprintf(out, " case %d: if (auto *source = %s%s) source->setBinding(*reinterpret_cast<QPropertyBinding<%s> *>(_a[0])); break;\n",
|
||||||
propindex, prefix.constData(), p.qpropertyname.constData(),
|
propindex, prefix.constData(), p.bindingAccessor.constData(),
|
||||||
objectAccessor.constData(), p.type.constData());
|
p.type.constData());
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -1523,7 +1456,7 @@ void Generator::generateStaticMetacall()
|
|||||||
fprintf(out, " }\n");
|
fprintf(out, " }\n");
|
||||||
}
|
}
|
||||||
fprintf(out, " }");
|
fprintf(out, " }");
|
||||||
|
#endif
|
||||||
fprintf(out, "\n#endif // QT_NO_PROPERTIES");
|
fprintf(out, "\n#endif // QT_NO_PROPERTIES");
|
||||||
needElse = true;
|
needElse = true;
|
||||||
}
|
}
|
||||||
@ -1608,199 +1541,6 @@ void Generator::generateSignal(FunctionDef *def,int index)
|
|||||||
fprintf(out, "}\n");
|
fprintf(out, "}\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
void Generator::generateQPropertyApi()
|
|
||||||
{
|
|
||||||
for (const PrivateQPropertyDef &property: cdef->privateQProperties) {
|
|
||||||
auto printAccessor = [this, property](bool constAccessor = false) {
|
|
||||||
const char *constOrNot = constAccessor ? "const " : " ";
|
|
||||||
fprintf(out, " const size_t propertyMemberOffset = Q_OFFSETOF(%s, %s);\n", cdef->qualified.constData(), property.name.constData());
|
|
||||||
fprintf(out, " %sauto *thisPtr = reinterpret_cast<%s%s *>(reinterpret_cast<%schar *>(this) - propertyMemberOffset);\n", constOrNot, constOrNot, cdef->qualified.constData(), constOrNot);
|
|
||||||
};
|
|
||||||
|
|
||||||
const bool stored = (property.name == property.storage);
|
|
||||||
const bool isNotifiedProperty = property.isNotifiedProperty;
|
|
||||||
|
|
||||||
// property accessor
|
|
||||||
fprintf(out, "\n%s %s::_qt_property_api_%s::value() const\n{\n",
|
|
||||||
property.type.name.constData(),
|
|
||||||
cdef->qualified.constData(),
|
|
||||||
property.name.constData());
|
|
||||||
printAccessor(/*const*/true);
|
|
||||||
if (stored) {
|
|
||||||
fprintf(out, " return thisPtr->%s->%s.value();\n", property.accessor.constData(), property.storage.constData());
|
|
||||||
} else {
|
|
||||||
fprintf(out, " if (auto *source = thisPtr->%s->%s)\n", property.accessor.constData(), property.storage.constData());
|
|
||||||
fprintf(out, " return source->value();\n");
|
|
||||||
fprintf(out, " else\n");
|
|
||||||
fprintf(out, " return %s();\n", property.type.name.constData());
|
|
||||||
}
|
|
||||||
fprintf(out, "}\n");
|
|
||||||
|
|
||||||
// property value setter
|
|
||||||
fprintf(out, "\nvoid %s::_qt_property_api_%s::setValue(%s const &value)\n{\n",
|
|
||||||
cdef->qualified.constData(),
|
|
||||||
property.name.constData(),
|
|
||||||
property.type.name.constData());
|
|
||||||
printAccessor();
|
|
||||||
if (stored) {
|
|
||||||
if (isNotifiedProperty)
|
|
||||||
fprintf(out, " thisPtr->%s->%s.setValue(thisPtr->%s, value);\n", property.accessor.constData(), property.storage.constData(), property.accessor.constData());
|
|
||||||
else
|
|
||||||
fprintf(out, " thisPtr->%s->%s.setValue(value);\n", property.accessor.constData(), property.storage.constData());
|
|
||||||
} else {
|
|
||||||
fprintf(out, " if (auto *target = thisPtr->%s->%s)\n", property.accessor.constData(), property.storage.constData());
|
|
||||||
if (isNotifiedProperty)
|
|
||||||
fprintf(out, " target->setValue(thisPtr->%s, value);\n", property.accessor.constData());
|
|
||||||
else
|
|
||||||
fprintf(out, " target->setValue(value);\n");
|
|
||||||
}
|
|
||||||
fprintf(out, "}\n");
|
|
||||||
|
|
||||||
// property value move setter
|
|
||||||
fprintf(out, "\nvoid %s::_qt_property_api_%s::setValue(%s &&value)\n{\n",
|
|
||||||
cdef->qualified.constData(),
|
|
||||||
property.name.constData(),
|
|
||||||
property.type.name.constData());
|
|
||||||
printAccessor();
|
|
||||||
if (stored) {
|
|
||||||
if (isNotifiedProperty)
|
|
||||||
fprintf(out, " thisPtr->%s->%s.setValue(thisPtr->%s, std::move(value));\n", property.accessor.constData(), property.storage.constData(), property.accessor.constData());
|
|
||||||
else
|
|
||||||
fprintf(out, " thisPtr->%s->%s.setValue(std::move(value));\n", property.accessor.constData(), property.storage.constData());
|
|
||||||
} else {
|
|
||||||
fprintf(out, " if (auto *target = thisPtr->%s->%s)\n", property.accessor.constData(), property.storage.constData());
|
|
||||||
if (isNotifiedProperty)
|
|
||||||
fprintf(out, " target->setValue(thisPtr->%s, std::move(value));\n", property.accessor.constData());
|
|
||||||
else
|
|
||||||
fprintf(out, " target->setValue(std::move(value));\n");
|
|
||||||
}
|
|
||||||
fprintf(out, "}\n");
|
|
||||||
|
|
||||||
// binding setter
|
|
||||||
fprintf(out, "\nQPropertyBinding<%s> %s::_qt_property_api_%s::setBinding(const QPropertyBinding<%s> &binding)\n{\n",
|
|
||||||
property.type.name.constData(),
|
|
||||||
cdef->qualified.constData(),
|
|
||||||
property.name.constData(),
|
|
||||||
property.type.name.constData());
|
|
||||||
printAccessor();
|
|
||||||
if (stored) {
|
|
||||||
if (isNotifiedProperty)
|
|
||||||
fprintf(out, " return thisPtr->%s->%s.setBinding(thisPtr->%s, binding);\n", property.accessor.constData(), property.storage.constData(), property.accessor.constData());
|
|
||||||
else
|
|
||||||
fprintf(out, " return thisPtr->%s->%s.setBinding(binding);\n", property.accessor.constData(), property.storage.constData());
|
|
||||||
} else {
|
|
||||||
fprintf(out, " if (auto *target = thisPtr->%s->%s)\n", property.accessor.constData(), property.storage.constData());
|
|
||||||
if (isNotifiedProperty)
|
|
||||||
fprintf(out, " return target->setBinding(thisPtr->%s, binding);\n", property.accessor.constData());
|
|
||||||
else
|
|
||||||
fprintf(out, " return target->setBinding(binding);\n");
|
|
||||||
fprintf(out, " else\n");
|
|
||||||
fprintf(out, " return QPropertyBinding<%s>();\n", property.type.name.constData());
|
|
||||||
}
|
|
||||||
fprintf(out, "}\n");
|
|
||||||
|
|
||||||
// binding move setter
|
|
||||||
fprintf(out, "\nQPropertyBinding<%s> %s::_qt_property_api_%s::setBinding(QPropertyBinding<%s> &&binding)\n{\n",
|
|
||||||
property.type.name.constData(),
|
|
||||||
cdef->qualified.constData(),
|
|
||||||
property.name.constData(),
|
|
||||||
property.type.name.constData());
|
|
||||||
printAccessor();
|
|
||||||
if (stored) {
|
|
||||||
if (isNotifiedProperty)
|
|
||||||
fprintf(out, " return thisPtr->%s->%s.setBinding(thisPtr->%s, std::move(binding));\n", property.accessor.constData(), property.storage.constData(), property.accessor.constData());
|
|
||||||
else
|
|
||||||
fprintf(out, " return thisPtr->%s->%s.setBinding(std::move(binding));\n", property.accessor.constData(), property.storage.constData());
|
|
||||||
} else {
|
|
||||||
fprintf(out, " if (auto *target = thisPtr->%s->%s)\n", property.accessor.constData(), property.storage.constData());
|
|
||||||
if (isNotifiedProperty)
|
|
||||||
fprintf(out, " return target->setBinding(thisPtr->%s, std::move(binding));\n", property.accessor.constData());
|
|
||||||
else
|
|
||||||
fprintf(out, " return target->setBinding(std::move(binding));\n");
|
|
||||||
fprintf(out, " else\n");
|
|
||||||
fprintf(out, " return QPropertyBinding<%s>();\n", property.type.name.constData());
|
|
||||||
}
|
|
||||||
fprintf(out, "}\n");
|
|
||||||
|
|
||||||
// untyped binding setter
|
|
||||||
fprintf(out, "\nbool %s::_qt_property_api_%s::setBinding(const QUntypedPropertyBinding &binding)\n{\n",
|
|
||||||
cdef->qualified.constData(),
|
|
||||||
property.name.constData());
|
|
||||||
printAccessor();
|
|
||||||
if (stored) {
|
|
||||||
if (isNotifiedProperty)
|
|
||||||
fprintf(out, " return thisPtr->%s->%s.setBinding(thisPtr->%s, binding);\n", property.accessor.constData(), property.storage.constData(), property.accessor.constData());
|
|
||||||
else
|
|
||||||
fprintf(out, " return thisPtr->%s->%s.setBinding(binding);\n", property.accessor.constData(), property.storage.constData());
|
|
||||||
} else {
|
|
||||||
fprintf(out, " if (auto *target = thisPtr->%s->%s)\n", property.accessor.constData(), property.storage.constData());
|
|
||||||
if (isNotifiedProperty)
|
|
||||||
fprintf(out, " return target->setBinding(thisPtr->%s, binding);\n", property.accessor.constData());
|
|
||||||
else
|
|
||||||
fprintf(out, " return target->setBinding(binding);\n");
|
|
||||||
fprintf(out, " else\n");
|
|
||||||
fprintf(out, " return false;\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
fprintf(out, "}\n");
|
|
||||||
|
|
||||||
// binding bool getter
|
|
||||||
fprintf(out, "\nbool %s::_qt_property_api_%s::hasBinding() const\n{\n",
|
|
||||||
cdef->qualified.constData(),
|
|
||||||
property.name.constData());
|
|
||||||
printAccessor(/*const*/true);
|
|
||||||
if (stored) {
|
|
||||||
fprintf(out, " return thisPtr->%s->%s.hasBinding();\n", property.accessor.constData(), property.storage.constData());
|
|
||||||
} else {
|
|
||||||
fprintf(out, " if (auto *source = thisPtr->%s->%s)\n", property.accessor.constData(), property.storage.constData());
|
|
||||||
fprintf(out, " return source->hasBinding();\n");
|
|
||||||
fprintf(out, " else\n");
|
|
||||||
fprintf(out, " return false;\n");
|
|
||||||
}
|
|
||||||
fprintf(out, "}\n");
|
|
||||||
|
|
||||||
// binding getter
|
|
||||||
fprintf(out, "\nQPropertyBinding<%s> %s::_qt_property_api_%s::binding() const\n{\n",
|
|
||||||
property.type.name.constData(),
|
|
||||||
cdef->qualified.constData(),
|
|
||||||
property.name.constData());
|
|
||||||
printAccessor(/*const*/true);
|
|
||||||
if (stored) {
|
|
||||||
fprintf(out, " return thisPtr->%s->%s.binding();\n", property.accessor.constData(), property.storage.constData());
|
|
||||||
} else {
|
|
||||||
fprintf(out, " if (auto *source = thisPtr->%s->%s)\n", property.accessor.constData(), property.storage.constData());
|
|
||||||
fprintf(out, " return source->binding();\n");
|
|
||||||
fprintf(out, " else\n");
|
|
||||||
fprintf(out, " return QPropertyBinding<%s>();\n", property.type.name.constData());
|
|
||||||
}
|
|
||||||
fprintf(out, "}\n");
|
|
||||||
|
|
||||||
// binding taker
|
|
||||||
fprintf(out, "\nQPropertyBinding<%s> %s::_qt_property_api_%s::takeBinding()\n{\n",
|
|
||||||
property.type.name.constData(),
|
|
||||||
cdef->qualified.constData(),
|
|
||||||
property.name.constData());
|
|
||||||
printAccessor();
|
|
||||||
if (stored) {
|
|
||||||
fprintf(out, " return thisPtr->%s->%s.takeBinding();\n", property.accessor.constData(), property.storage.constData());
|
|
||||||
} else {
|
|
||||||
fprintf(out, " if (auto *source = thisPtr->%s->%s)\n", property.accessor.constData(), property.storage.constData());
|
|
||||||
fprintf(out, " return source->takeBinding();\n");
|
|
||||||
fprintf(out, " else\n");
|
|
||||||
fprintf(out, " return QPropertyBinding<%s>();\n", property.type.name.constData());
|
|
||||||
}
|
|
||||||
fprintf(out, "}\n");
|
|
||||||
|
|
||||||
// property setter function
|
|
||||||
fprintf(out, "\nvoid %s::%s(%s const& value)\n{\n",
|
|
||||||
cdef->qualified.constData(),
|
|
||||||
property.setter.constData(),
|
|
||||||
property.type.name.constData());
|
|
||||||
fprintf(out, " this->%s.setValue(value);\n", property.name.constData());
|
|
||||||
fprintf(out, "}\n\n");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static CborError jsonValueToCbor(CborEncoder *parent, const QJsonValue &v);
|
static CborError jsonValueToCbor(CborEncoder *parent, const QJsonValue &v);
|
||||||
static CborError jsonObjectToCbor(CborEncoder *parent, const QJsonObject &o)
|
static CborError jsonObjectToCbor(CborEncoder *parent, const QJsonObject &o)
|
||||||
{
|
{
|
||||||
|
@ -63,7 +63,6 @@ private:
|
|||||||
void generateMetacall();
|
void generateMetacall();
|
||||||
void generateStaticMetacall();
|
void generateStaticMetacall();
|
||||||
void generateSignal(FunctionDef *def, int index);
|
void generateSignal(FunctionDef *def, int index);
|
||||||
void generateQPropertyApi();
|
|
||||||
void generatePluginMetaData();
|
void generatePluginMetaData();
|
||||||
QMultiMap<QByteArray, int> automaticPropertyMetaTypesHelper();
|
QMultiMap<QByteArray, int> automaticPropertyMetaTypesHelper();
|
||||||
QMap<int, QMultiMap<QByteArray, int>>
|
QMap<int, QMultiMap<QByteArray, int>>
|
||||||
|
@ -30,12 +30,12 @@
|
|||||||
// DO NOT EDIT.
|
// DO NOT EDIT.
|
||||||
|
|
||||||
static const short keyword_trans[][128] = {
|
static const short keyword_trans[][128] = {
|
||||||
{0,0,0,0,0,0,0,0,0,588,585,0,0,0,0,0,
|
{0,0,0,0,0,0,0,0,0,579,576,0,0,0,0,0,
|
||||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||||
588,252,586,589,8,38,239,587,25,26,236,234,30,235,27,237,
|
579,252,577,580,8,38,239,578,25,26,236,234,30,235,27,237,
|
||||||
22,22,22,22,22,22,22,22,22,22,34,41,23,39,24,43,
|
22,22,22,22,22,22,22,22,22,22,34,41,23,39,24,43,
|
||||||
0,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
|
0,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
|
||||||
8,21,8,8,8,8,8,8,8,8,8,31,591,32,238,8,
|
8,21,8,8,8,8,8,8,8,8,8,31,582,32,238,8,
|
||||||
0,1,2,3,4,5,6,7,8,9,8,8,10,11,12,13,
|
0,1,2,3,4,5,6,7,8,9,8,8,10,11,12,13,
|
||||||
14,8,15,16,17,18,19,20,8,8,8,36,245,37,248,0},
|
14,8,15,16,17,18,19,20,8,8,8,36,245,37,248,0},
|
||||||
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||||
@ -177,7 +177,7 @@ static const short keyword_trans[][128] = {
|
|||||||
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||||
0,0,0,0,0,0,0,0,0,0,42,0,0,0,28,0,
|
0,0,0,0,0,0,0,0,0,0,42,0,0,0,28,0,
|
||||||
594,594,594,594,594,594,594,594,594,594,0,0,0,0,0,0,
|
585,585,585,585,585,585,585,585,585,585,0,0,0,0,0,0,
|
||||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||||
@ -336,7 +336,7 @@ static const short keyword_trans[][128] = {
|
|||||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
|
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
|
||||||
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||||
0,0,0,0,0,0,0,0,0,0,593,0,0,0,0,592,
|
0,0,0,0,0,0,0,0,0,0,584,0,0,0,0,583,
|
||||||
0,0,0,0,0,0,0,0,0,0,0,0,0,258,0,0,
|
0,0,0,0,0,0,0,0,0,0,0,0,0,258,0,0,
|
||||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||||
@ -378,8 +378,8 @@ static const short keyword_trans[][128] = {
|
|||||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||||
0,0,0,475,424,408,416,380,0,484,0,0,0,574,364,358,
|
0,0,0,475,424,408,416,380,0,484,0,0,0,565,364,358,
|
||||||
386,0,566,472,0,0,0,0,0,0,0,0,0,0,0,0,
|
386,0,557,472,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
|
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
|
||||||
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||||
@ -443,7 +443,7 @@ static const short keyword_trans[][128] = {
|
|||||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||||
549,557,0,517,0,0,0,0,0,0,0,0,0,0,0,0,
|
549,0,0,517,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}
|
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}
|
||||||
};
|
};
|
||||||
@ -1013,39 +1013,30 @@ static const struct
|
|||||||
{CHARACTER, 0, 84, 555, CHARACTER},
|
{CHARACTER, 0, 84, 555, CHARACTER},
|
||||||
{CHARACTER, 0, 89, 556, CHARACTER},
|
{CHARACTER, 0, 89, 556, CHARACTER},
|
||||||
{Q_PRIVATE_PROPERTY_TOKEN, 0, 0, 0, CHARACTER},
|
{Q_PRIVATE_PROPERTY_TOKEN, 0, 0, 0, CHARACTER},
|
||||||
{CHARACTER, 0, 80, 558, CHARACTER},
|
{CHARACTER, 0, 69, 558, CHARACTER},
|
||||||
{CHARACTER, 0, 82, 559, CHARACTER},
|
{CHARACTER, 0, 86, 559, CHARACTER},
|
||||||
{CHARACTER, 0, 79, 560, CHARACTER},
|
{CHARACTER, 0, 73, 560, CHARACTER},
|
||||||
{CHARACTER, 0, 80, 561, CHARACTER},
|
{CHARACTER, 0, 83, 561, CHARACTER},
|
||||||
{CHARACTER, 0, 69, 562, CHARACTER},
|
{CHARACTER, 0, 73, 562, CHARACTER},
|
||||||
{CHARACTER, 0, 82, 563, CHARACTER},
|
{CHARACTER, 0, 79, 563, CHARACTER},
|
||||||
{CHARACTER, 0, 84, 564, CHARACTER},
|
{CHARACTER, 0, 78, 564, CHARACTER},
|
||||||
{CHARACTER, 0, 89, 565, CHARACTER},
|
|
||||||
{Q_PRIVATE_QPROPERTY_TOKEN, 0, 0, 0, CHARACTER},
|
|
||||||
{CHARACTER, 0, 69, 567, CHARACTER},
|
|
||||||
{CHARACTER, 0, 86, 568, CHARACTER},
|
|
||||||
{CHARACTER, 0, 73, 569, CHARACTER},
|
|
||||||
{CHARACTER, 0, 83, 570, CHARACTER},
|
|
||||||
{CHARACTER, 0, 73, 571, CHARACTER},
|
|
||||||
{CHARACTER, 0, 79, 572, CHARACTER},
|
|
||||||
{CHARACTER, 0, 78, 573, CHARACTER},
|
|
||||||
{Q_REVISION_TOKEN, 0, 0, 0, CHARACTER},
|
{Q_REVISION_TOKEN, 0, 0, 0, CHARACTER},
|
||||||
{CHARACTER, 0, 79, 575, CHARACTER},
|
{CHARACTER, 0, 79, 566, CHARACTER},
|
||||||
{CHARACTER, 0, 67, 576, CHARACTER},
|
{CHARACTER, 0, 67, 567, CHARACTER},
|
||||||
{CHARACTER, 0, 95, 577, CHARACTER},
|
{CHARACTER, 0, 95, 568, CHARACTER},
|
||||||
{CHARACTER, 0, 73, 578, CHARACTER},
|
{CHARACTER, 0, 73, 569, CHARACTER},
|
||||||
{CHARACTER, 0, 78, 579, CHARACTER},
|
{CHARACTER, 0, 78, 570, CHARACTER},
|
||||||
{CHARACTER, 0, 67, 580, CHARACTER},
|
{CHARACTER, 0, 67, 571, CHARACTER},
|
||||||
{CHARACTER, 0, 76, 581, CHARACTER},
|
{CHARACTER, 0, 76, 572, CHARACTER},
|
||||||
{CHARACTER, 0, 85, 582, CHARACTER},
|
{CHARACTER, 0, 85, 573, CHARACTER},
|
||||||
{CHARACTER, 0, 68, 583, CHARACTER},
|
{CHARACTER, 0, 68, 574, CHARACTER},
|
||||||
{CHARACTER, 0, 69, 584, CHARACTER},
|
{CHARACTER, 0, 69, 575, CHARACTER},
|
||||||
{Q_MOC_INCLUDE_TOKEN, 0, 0, 0, CHARACTER},
|
{Q_MOC_INCLUDE_TOKEN, 0, 0, 0, CHARACTER},
|
||||||
{NEWLINE, 0, 0, 0, NOTOKEN},
|
{NEWLINE, 0, 0, 0, NOTOKEN},
|
||||||
{QUOTE, 0, 0, 0, NOTOKEN},
|
{QUOTE, 0, 0, 0, NOTOKEN},
|
||||||
{SINGLEQUOTE, 0, 0, 0, NOTOKEN},
|
{SINGLEQUOTE, 0, 0, 0, NOTOKEN},
|
||||||
{WHITESPACE, 0, 0, 0, NOTOKEN},
|
{WHITESPACE, 0, 0, 0, NOTOKEN},
|
||||||
{HASH, 0, 35, 590, HASH},
|
{HASH, 0, 35, 581, HASH},
|
||||||
{PP_HASHHASH, 0, 0, 0, NOTOKEN},
|
{PP_HASHHASH, 0, 0, 0, NOTOKEN},
|
||||||
{BACKSLASH, 0, 0, 0, NOTOKEN},
|
{BACKSLASH, 0, 0, 0, NOTOKEN},
|
||||||
{CPP_COMMENT, 0, 0, 0, NOTOKEN},
|
{CPP_COMMENT, 0, 0, 0, NOTOKEN},
|
||||||
|
@ -576,35 +576,6 @@ bool Moc::parseMaybeFunction(const ClassDef *cdef, FunctionDef *def)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Try to parse QProperty<MyType> propertName; members
|
|
||||||
bool Moc::parseMaybeQProperty(ClassDef *def)
|
|
||||||
{
|
|
||||||
if (!test(IDENTIFIER))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
bool hasNotifier = false;
|
|
||||||
if (lexem() == "QNotifiedProperty") {
|
|
||||||
hasNotifier = true;
|
|
||||||
} else if (lexem() != "QProperty") {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!test(LANGLE))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
until(RANGLE);
|
|
||||||
|
|
||||||
next();
|
|
||||||
const auto propName = lexem();
|
|
||||||
|
|
||||||
if (!test(SEMIC))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
def->qPropertyMembersMaybeWithNotifier.insert(propName, hasNotifier);
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Moc::parse()
|
void Moc::parse()
|
||||||
{
|
{
|
||||||
QList<NamespaceDef> namespaceList;
|
QList<NamespaceDef> namespaceList;
|
||||||
@ -893,9 +864,6 @@ void Moc::parse()
|
|||||||
case Q_PRIVATE_PROPERTY_TOKEN:
|
case Q_PRIVATE_PROPERTY_TOKEN:
|
||||||
parsePrivateProperty(&def);
|
parsePrivateProperty(&def);
|
||||||
break;
|
break;
|
||||||
case Q_PRIVATE_QPROPERTY_TOKEN:
|
|
||||||
parsePrivateQProperty(&def);
|
|
||||||
break;
|
|
||||||
case ENUM: {
|
case ENUM: {
|
||||||
EnumDef enumDef;
|
EnumDef enumDef;
|
||||||
if (parseEnum(&enumDef))
|
if (parseEnum(&enumDef))
|
||||||
@ -953,9 +921,7 @@ void Moc::parse()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
index = rewind - 1;
|
index = rewind;
|
||||||
if (!parseMaybeQProperty(&def))
|
|
||||||
index = rewind;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1055,8 +1021,8 @@ static QByteArrayList requiredQtContainers(const QList<ClassDef> &classes)
|
|||||||
const QByteArray pattern = candidate + '<';
|
const QByteArray pattern = candidate + '<';
|
||||||
|
|
||||||
for (const auto &c : classes) {
|
for (const auto &c : classes) {
|
||||||
if (!c.privateQProperties.isEmpty())
|
for (const auto &p : c.propertyList)
|
||||||
needsQProperty = true;
|
needsQProperty |= p.isQProperty;
|
||||||
if (any_type_contains(c.propertyList, pattern) ||
|
if (any_type_contains(c.propertyList, pattern) ||
|
||||||
any_arg_contains(c.slotList, pattern) ||
|
any_arg_contains(c.slotList, pattern) ||
|
||||||
any_arg_contains(c.signalList, pattern) ||
|
any_arg_contains(c.signalList, pattern) ||
|
||||||
@ -1385,19 +1351,8 @@ void Moc::parsePropertyAttributes(PropertyDef &propDef)
|
|||||||
checkIsFunction(propDef.designable, "DESIGNABLE");
|
checkIsFunction(propDef.designable, "DESIGNABLE");
|
||||||
break;
|
break;
|
||||||
case 'N': if (l != "NOTIFY") error(2);
|
case 'N': if (l != "NOTIFY") error(2);
|
||||||
if (v == "false") {
|
propDef.notify = v;
|
||||||
if (!propDef.isQProperty)
|
break;
|
||||||
error(1);
|
|
||||||
propDef.isQPropertyWithNotifier = false;
|
|
||||||
break;
|
|
||||||
} else if (v == "true") {
|
|
||||||
if (!propDef.isQProperty)
|
|
||||||
error(1);
|
|
||||||
break;
|
|
||||||
} else {
|
|
||||||
propDef.notify = v;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case 'U': if (l != "USER") error(2);
|
case 'U': if (l != "USER") error(2);
|
||||||
propDef.user = v + v2;
|
propDef.user = v + v2;
|
||||||
checkIsFunction(propDef.user, "USER");
|
checkIsFunction(propDef.user, "USER");
|
||||||
@ -1494,19 +1449,19 @@ void Moc::parsePluginData(ClassDef *def)
|
|||||||
|
|
||||||
QByteArray Moc::parsePropertyAccessor()
|
QByteArray Moc::parsePropertyAccessor()
|
||||||
{
|
{
|
||||||
next(IDENTIFIER);
|
int nesting = 0;
|
||||||
QByteArray accessor = lexem();
|
QByteArray accessor;
|
||||||
while (test(SCOPE)) {
|
while (1) {
|
||||||
accessor += lexem();
|
Token t = peek();
|
||||||
next(IDENTIFIER);
|
if (!nesting && (t == RPAREN || t == COMMA))
|
||||||
|
break;
|
||||||
|
t = next();
|
||||||
|
if (t == LPAREN)
|
||||||
|
++nesting;
|
||||||
|
if (t == RPAREN)
|
||||||
|
--nesting;
|
||||||
accessor += lexem();
|
accessor += lexem();
|
||||||
}
|
}
|
||||||
// also allow void functions
|
|
||||||
if (test(LPAREN)) {
|
|
||||||
next(RPAREN);
|
|
||||||
accessor += "()";
|
|
||||||
}
|
|
||||||
|
|
||||||
return accessor;
|
return accessor;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1523,48 +1478,6 @@ void Moc::parsePrivateProperty(ClassDef *def)
|
|||||||
def->propertyList += propDef;
|
def->propertyList += propDef;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Moc::parsePrivateQProperty(ClassDef *def)
|
|
||||||
{
|
|
||||||
next(LPAREN);
|
|
||||||
const QByteArray accessor = parsePropertyAccessor();
|
|
||||||
next(COMMA);
|
|
||||||
const Type type = parseType();
|
|
||||||
next(COMMA);
|
|
||||||
next(IDENTIFIER);
|
|
||||||
const QByteArray name = lexem();
|
|
||||||
next(COMMA);
|
|
||||||
next(IDENTIFIER);
|
|
||||||
const QByteArray setter = lexem();
|
|
||||||
|
|
||||||
PropertyDef propDef;
|
|
||||||
propDef.name = name;
|
|
||||||
propDef.type = type.name;
|
|
||||||
propDef.isQProperty = true;
|
|
||||||
propDef.isQPropertyWithNotifier = true;
|
|
||||||
propDef.inPrivateClass = accessor;
|
|
||||||
propDef.designable = propDef.scriptable = propDef.stored = "true";
|
|
||||||
propDef.user = "false";
|
|
||||||
|
|
||||||
if (test(COMMA))
|
|
||||||
parsePropertyAttributes(propDef);
|
|
||||||
|
|
||||||
const bool stored = propDef.stored == "true";
|
|
||||||
propDef.qpropertyname = stored ? name : (name + "()");
|
|
||||||
|
|
||||||
def->privateQProperties += PrivateQPropertyDef {
|
|
||||||
type, name, setter, accessor, propDef.qpropertyname, propDef.isQPropertyWithNotifier
|
|
||||||
};
|
|
||||||
|
|
||||||
if (propDef.read.isEmpty())
|
|
||||||
propDef.read = propDef.qpropertyname + (stored ? ".value" : "->value");
|
|
||||||
if (propDef.write.isEmpty())
|
|
||||||
propDef.write = propDef.qpropertyname + (stored ? ".setValue" : "->setValue");
|
|
||||||
|
|
||||||
next(RPAREN);
|
|
||||||
|
|
||||||
def->propertyList += propDef;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Moc::parseEnumOrFlag(BaseDef *def, bool isFlag)
|
void Moc::parseEnumOrFlag(BaseDef *def, bool isFlag)
|
||||||
{
|
{
|
||||||
next(LPAREN);
|
next(LPAREN);
|
||||||
@ -1895,33 +1808,19 @@ void Moc::checkProperties(ClassDef *cdef)
|
|||||||
warning(msg.constData());
|
warning(msg.constData());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (p.read.isEmpty() && p.member.isEmpty()) {
|
if (p.read.isEmpty() && p.member.isEmpty() && !p.isQProperty) {
|
||||||
|
const int rewind = index;
|
||||||
auto qPropertyMemberIt = cdef->qPropertyMembersMaybeWithNotifier.constFind(p.name);
|
if (p.location >= 0)
|
||||||
const bool knownQPropertyMember = qPropertyMemberIt != cdef->qPropertyMembersMaybeWithNotifier.constEnd();
|
index = p.location;
|
||||||
if (!knownQPropertyMember && !p.isQProperty) {
|
QByteArray msg = "Property declaration " + p.name + " has neither an associated QProperty<> member"
|
||||||
const int rewind = index;
|
", nor a READ accessor function nor an associated MEMBER variable. The property will be invalid.";
|
||||||
if (p.location >= 0)
|
warning(msg.constData());
|
||||||
index = p.location;
|
index = rewind;
|
||||||
QByteArray msg = "Property declaration " + p.name + " has neither an associated QProperty<> member"
|
if (p.write.isEmpty()) {
|
||||||
", nor a READ accessor function nor an associated MEMBER variable. The property will be invalid.";
|
cdef->propertyList.removeAt(i);
|
||||||
warning(msg.constData());
|
--i;
|
||||||
index = rewind;
|
|
||||||
if (p.write.isEmpty()) {
|
|
||||||
cdef->propertyList.removeAt(i);
|
|
||||||
--i;
|
|
||||||
}
|
|
||||||
continue;
|
|
||||||
}
|
}
|
||||||
const bool stored = p.stored == "true";
|
continue;
|
||||||
p.qpropertyname = stored ? p.name : (p.name + "()");
|
|
||||||
p.read = p.qpropertyname + (stored ? ".value" : "->value");
|
|
||||||
p.write = p.qpropertyname + (stored ? ".setValue" : "->setValue");;
|
|
||||||
p.isQProperty = true;
|
|
||||||
const bool hasNotifier = knownQPropertyMember && qPropertyMemberIt.value();
|
|
||||||
p.isQPropertyWithNotifier = hasNotifier;
|
|
||||||
p.designable = p.scriptable = p.stored = "true";
|
|
||||||
p.user = "false";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int j = 0; j < cdef->publicList.count(); ++j) {
|
for (int j = 0; j < cdef->publicList.count(); ++j) {
|
||||||
|
@ -132,7 +132,7 @@ struct PropertyDef
|
|||||||
return (s == write);
|
return (s == write);
|
||||||
}
|
}
|
||||||
|
|
||||||
QByteArray name, type, member, read, write, reset, designable, scriptable, stored, user, notify, inPrivateClass, qpropertyname;
|
QByteArray name, type, member, read, write, reset, designable, scriptable, stored, user, notify, inPrivateClass;
|
||||||
int notifyId = -1; // -1 means no notifyId, >= 0 means signal defined in this class, < -1 means signal not defined in this class
|
int notifyId = -1; // -1 means no notifyId, >= 0 means signal defined in this class, < -1 means signal not defined in this class
|
||||||
enum Specification { ValueSpec, ReferenceSpec, PointerSpec };
|
enum Specification { ValueSpec, ReferenceSpec, PointerSpec };
|
||||||
Specification gspec = ValueSpec;
|
Specification gspec = ValueSpec;
|
||||||
@ -141,7 +141,6 @@ struct PropertyDef
|
|||||||
bool final = false;
|
bool final = false;
|
||||||
bool required = false;
|
bool required = false;
|
||||||
bool isQProperty = false;
|
bool isQProperty = false;
|
||||||
bool isQPropertyWithNotifier = false;
|
|
||||||
|
|
||||||
int location = -1; // token index, used for error reporting
|
int location = -1; // token index, used for error reporting
|
||||||
|
|
||||||
@ -156,7 +155,6 @@ struct PrivateQPropertyDef
|
|||||||
QByteArray setter;
|
QByteArray setter;
|
||||||
QByteArray accessor;
|
QByteArray accessor;
|
||||||
QByteArray storage;
|
QByteArray storage;
|
||||||
bool isNotifiedProperty;
|
|
||||||
};
|
};
|
||||||
Q_DECLARE_TYPEINFO(PrivateQPropertyDef, Q_MOVABLE_TYPE);
|
Q_DECLARE_TYPEINFO(PrivateQPropertyDef, Q_MOVABLE_TYPE);
|
||||||
|
|
||||||
@ -202,8 +200,6 @@ struct ClassDef : BaseDef {
|
|||||||
QList<FunctionDef> signalList, slotList, methodList, publicList;
|
QList<FunctionDef> signalList, slotList, methodList, publicList;
|
||||||
QList<QByteArray> nonClassSignalList;
|
QList<QByteArray> nonClassSignalList;
|
||||||
QList<PropertyDef> propertyList;
|
QList<PropertyDef> propertyList;
|
||||||
QList<PrivateQPropertyDef> privateQProperties;
|
|
||||||
QHash<QByteArray, bool> qPropertyMembersMaybeWithNotifier;
|
|
||||||
int revisionedMethods = 0;
|
int revisionedMethods = 0;
|
||||||
|
|
||||||
bool hasQObject = false;
|
bool hasQObject = false;
|
||||||
@ -262,7 +258,6 @@ public:
|
|||||||
|
|
||||||
bool parseFunction(FunctionDef *def, bool inMacro = false);
|
bool parseFunction(FunctionDef *def, bool inMacro = false);
|
||||||
bool parseMaybeFunction(const ClassDef *cdef, FunctionDef *def);
|
bool parseMaybeFunction(const ClassDef *cdef, FunctionDef *def);
|
||||||
bool parseMaybeQProperty(ClassDef *def);
|
|
||||||
|
|
||||||
void parseSlots(ClassDef *def, FunctionDef::Access access);
|
void parseSlots(ClassDef *def, FunctionDef::Access access);
|
||||||
void parseSignals(ClassDef *def);
|
void parseSignals(ClassDef *def);
|
||||||
@ -280,7 +275,6 @@ public:
|
|||||||
void parseSlotInPrivate(ClassDef *def, FunctionDef::Access access);
|
void parseSlotInPrivate(ClassDef *def, FunctionDef::Access access);
|
||||||
QByteArray parsePropertyAccessor();
|
QByteArray parsePropertyAccessor();
|
||||||
void parsePrivateProperty(ClassDef *def);
|
void parsePrivateProperty(ClassDef *def);
|
||||||
void parsePrivateQProperty(ClassDef *def);
|
|
||||||
|
|
||||||
void parseFunctionArguments(FunctionDef *def);
|
void parseFunctionArguments(FunctionDef *def);
|
||||||
|
|
||||||
|
@ -57,6 +57,7 @@ public:
|
|||||||
|
|
||||||
inline bool hasNext() const { return (index < symbols.size()); }
|
inline bool hasNext() const { return (index < symbols.size()); }
|
||||||
inline Token next() { if (index >= symbols.size()) return NOTOKEN; return symbols.at(index++).token; }
|
inline Token next() { if (index >= symbols.size()) return NOTOKEN; return symbols.at(index++).token; }
|
||||||
|
inline Token peek() { if (index >= symbols.size()) return NOTOKEN; return symbols.at(index).token; }
|
||||||
bool test(Token);
|
bool test(Token);
|
||||||
void next(Token);
|
void next(Token);
|
||||||
void next(Token, const char *msg);
|
void next(Token, const char *msg);
|
||||||
|
@ -178,7 +178,6 @@ QT_BEGIN_NAMESPACE
|
|||||||
F(Q_INVOKABLE_TOKEN) \
|
F(Q_INVOKABLE_TOKEN) \
|
||||||
F(Q_SCRIPTABLE_TOKEN) \
|
F(Q_SCRIPTABLE_TOKEN) \
|
||||||
F(Q_PRIVATE_PROPERTY_TOKEN) \
|
F(Q_PRIVATE_PROPERTY_TOKEN) \
|
||||||
F(Q_PRIVATE_QPROPERTY_TOKEN) \
|
|
||||||
F(Q_REVISION_TOKEN) \
|
F(Q_REVISION_TOKEN) \
|
||||||
F(Q_MOC_INCLUDE_TOKEN) \
|
F(Q_MOC_INCLUDE_TOKEN) \
|
||||||
F(SPECIAL_TREATMENT_MARK) \
|
F(SPECIAL_TREATMENT_MARK) \
|
||||||
|
@ -242,7 +242,6 @@ static const Keyword keywords[] = {
|
|||||||
{ "Q_SLOT", "Q_SLOT_TOKEN" },
|
{ "Q_SLOT", "Q_SLOT_TOKEN" },
|
||||||
{ "Q_SCRIPTABLE", "Q_SCRIPTABLE_TOKEN" },
|
{ "Q_SCRIPTABLE", "Q_SCRIPTABLE_TOKEN" },
|
||||||
{ "Q_PRIVATE_PROPERTY", "Q_PRIVATE_PROPERTY_TOKEN" },
|
{ "Q_PRIVATE_PROPERTY", "Q_PRIVATE_PROPERTY_TOKEN" },
|
||||||
{ "Q_PRIVATE_QPROPERTY", "Q_PRIVATE_QPROPERTY_TOKEN" },
|
|
||||||
{ "Q_REVISION", "Q_REVISION_TOKEN" },
|
{ "Q_REVISION", "Q_REVISION_TOKEN" },
|
||||||
{ "Q_MOC_INCLUDE", "Q_MOC_INCLUDE_TOKEN" },
|
{ "Q_MOC_INCLUDE", "Q_MOC_INCLUDE_TOKEN" },
|
||||||
{ "\n", "NEWLINE" },
|
{ "\n", "NEWLINE" },
|
||||||
|
@ -70,9 +70,6 @@ private slots:
|
|||||||
void multipleObservers();
|
void multipleObservers();
|
||||||
void propertyAlias();
|
void propertyAlias();
|
||||||
void arrowAndStarOperator();
|
void arrowAndStarOperator();
|
||||||
void notifiedProperty();
|
|
||||||
void notifiedPropertyWithOldValueCallback();
|
|
||||||
void notifiedPropertyWithGuard();
|
|
||||||
void typeNoOperatorEqual();
|
void typeNoOperatorEqual();
|
||||||
void bindingValueReplacement();
|
void bindingValueReplacement();
|
||||||
};
|
};
|
||||||
@ -780,240 +777,6 @@ void tst_QProperty::arrowAndStarOperator()
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
struct ClassWithNotifiedProperty
|
|
||||||
{
|
|
||||||
QList<int> recordedValues;
|
|
||||||
|
|
||||||
void callback() { recordedValues << property.value(); }
|
|
||||||
|
|
||||||
QNotifiedProperty<int, &ClassWithNotifiedProperty::callback> property;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct ClassWithNotifiedProperty2
|
|
||||||
{
|
|
||||||
QList<int> recordedValues;
|
|
||||||
|
|
||||||
void callback(int oldValue) { recordedValues << oldValue; }
|
|
||||||
|
|
||||||
QNotifiedProperty<int, &ClassWithNotifiedProperty2::callback> property;
|
|
||||||
};
|
|
||||||
|
|
||||||
void tst_QProperty::notifiedProperty()
|
|
||||||
{
|
|
||||||
ClassWithNotifiedProperty instance;
|
|
||||||
std::array<QProperty<int>, 5> otherProperties = {
|
|
||||||
QProperty<int>([&]() { return instance.property + 1; }),
|
|
||||||
QProperty<int>([&]() { return instance.property + 2; }),
|
|
||||||
QProperty<int>([&]() { return instance.property + 3; }),
|
|
||||||
QProperty<int>([&]() { return instance.property + 4; }),
|
|
||||||
QProperty<int>([&]() { return instance.property + 5; }),
|
|
||||||
};
|
|
||||||
|
|
||||||
auto check = [&] {
|
|
||||||
const int val = instance.property.value();
|
|
||||||
for (int i = 0; i < int(otherProperties.size()); ++i)
|
|
||||||
QCOMPARE(otherProperties[i].value(), val + i + 1);
|
|
||||||
};
|
|
||||||
|
|
||||||
QVERIFY(instance.recordedValues.isEmpty());
|
|
||||||
check();
|
|
||||||
|
|
||||||
instance.property.setValue(&instance, 42);
|
|
||||||
QCOMPARE(instance.recordedValues.count(), 1);
|
|
||||||
QCOMPARE(instance.recordedValues.at(0), 42);
|
|
||||||
instance.recordedValues.clear();
|
|
||||||
check();
|
|
||||||
|
|
||||||
instance.property.setValue(&instance, 42);
|
|
||||||
QVERIFY(instance.recordedValues.isEmpty());
|
|
||||||
check();
|
|
||||||
|
|
||||||
int subscribedCount = 0;
|
|
||||||
QProperty<int> injectedValue(100);
|
|
||||||
instance.property.setBinding(&instance, [&injectedValue]() { return injectedValue.value(); });
|
|
||||||
auto subscriber = [&] { ++subscribedCount; };
|
|
||||||
std::array<QPropertyChangeHandler<decltype (subscriber)>, 10> subscribers = {
|
|
||||||
instance.property.subscribe(subscriber),
|
|
||||||
instance.property.subscribe(subscriber),
|
|
||||||
instance.property.subscribe(subscriber),
|
|
||||||
instance.property.subscribe(subscriber),
|
|
||||||
instance.property.subscribe(subscriber),
|
|
||||||
instance.property.subscribe(subscriber),
|
|
||||||
instance.property.subscribe(subscriber),
|
|
||||||
instance.property.subscribe(subscriber),
|
|
||||||
instance.property.subscribe(subscriber),
|
|
||||||
instance.property.subscribe(subscriber)
|
|
||||||
};
|
|
||||||
|
|
||||||
QCOMPARE(subscribedCount, 10);
|
|
||||||
subscribedCount = 0;
|
|
||||||
|
|
||||||
QCOMPARE(instance.property.value(), 100);
|
|
||||||
QCOMPARE(instance.recordedValues.count(), 1);
|
|
||||||
QCOMPARE(instance.recordedValues.at(0), 100);
|
|
||||||
instance.recordedValues.clear();
|
|
||||||
check();
|
|
||||||
QCOMPARE(subscribedCount, 0);
|
|
||||||
|
|
||||||
injectedValue = 200;
|
|
||||||
QCOMPARE(instance.property.value(), 200);
|
|
||||||
QCOMPARE(instance.recordedValues.count(), 1);
|
|
||||||
QCOMPARE(instance.recordedValues.at(0), 200);
|
|
||||||
instance.recordedValues.clear();
|
|
||||||
check();
|
|
||||||
QCOMPARE(subscribedCount, 10);
|
|
||||||
subscribedCount = 0;
|
|
||||||
|
|
||||||
injectedValue = 400;
|
|
||||||
QCOMPARE(instance.property.value(), 400);
|
|
||||||
QCOMPARE(instance.recordedValues.count(), 1);
|
|
||||||
QCOMPARE(instance.recordedValues.at(0), 400);
|
|
||||||
instance.recordedValues.clear();
|
|
||||||
check();
|
|
||||||
QCOMPARE(subscribedCount, 10);
|
|
||||||
}
|
|
||||||
|
|
||||||
void tst_QProperty::notifiedPropertyWithOldValueCallback()
|
|
||||||
{
|
|
||||||
ClassWithNotifiedProperty2 instance;
|
|
||||||
instance.property.setValue(&instance, 1);
|
|
||||||
instance.property.setBinding(&instance, [](){return 2;});
|
|
||||||
instance.property.setBinding(&instance, [](){return 3;});
|
|
||||||
instance.property.setValue(&instance, 4);
|
|
||||||
QList<int> expected {0, 1, 2, 3};
|
|
||||||
QCOMPARE(instance.recordedValues, expected);
|
|
||||||
QCOMPARE(instance.property.value(), 4);
|
|
||||||
}
|
|
||||||
|
|
||||||
struct ClassWithNotifiedPropertyWithGuard
|
|
||||||
{
|
|
||||||
using This = ClassWithNotifiedPropertyWithGuard;
|
|
||||||
QList<int> recordedValues;
|
|
||||||
|
|
||||||
void callback() { recordedValues << property.value(); }
|
|
||||||
void callback2() { recordedValues << property2.value(); }
|
|
||||||
void callback3() {}
|
|
||||||
bool trivialGuard(int ) {return true;}
|
|
||||||
bool reject42(int newValue) {return newValue != 42;}
|
|
||||||
bool bound(int &newValue) { newValue = qBound<int>(0, newValue, 100); return true; }
|
|
||||||
|
|
||||||
QNotifiedProperty<int, &This::callback, &This::trivialGuard> property;
|
|
||||||
QNotifiedProperty<int, &This::callback2, &This::reject42> property2;
|
|
||||||
QNotifiedProperty<int, &This::callback3, &This::bound> property3;
|
|
||||||
};
|
|
||||||
|
|
||||||
void tst_QProperty::notifiedPropertyWithGuard()
|
|
||||||
{
|
|
||||||
{
|
|
||||||
// property with guard that returns always true is the same as using no guard
|
|
||||||
ClassWithNotifiedPropertyWithGuard instance;
|
|
||||||
|
|
||||||
std::array<QProperty<int>, 5> otherProperties = {
|
|
||||||
QProperty<int>([&]() { return instance.property + 1; }),
|
|
||||||
QProperty<int>([&]() { return instance.property + 2; }),
|
|
||||||
QProperty<int>([&]() { return instance.property + 3; }),
|
|
||||||
QProperty<int>([&]() { return instance.property + 4; }),
|
|
||||||
QProperty<int>([&]() { return instance.property + 5; }),
|
|
||||||
};
|
|
||||||
|
|
||||||
auto check = [&] {
|
|
||||||
const int val = instance.property.value();
|
|
||||||
for (int i = 0; i < int(otherProperties.size()); ++i)
|
|
||||||
QCOMPARE(otherProperties[i].value(), val + i + 1);
|
|
||||||
};
|
|
||||||
|
|
||||||
QVERIFY(instance.recordedValues.isEmpty());
|
|
||||||
check();
|
|
||||||
|
|
||||||
instance.property.setValue(&instance, 42);
|
|
||||||
QCOMPARE(instance.recordedValues.count(), 1);
|
|
||||||
QCOMPARE(instance.recordedValues.at(0), 42);
|
|
||||||
instance.recordedValues.clear();
|
|
||||||
check();
|
|
||||||
|
|
||||||
instance.property.setValue(&instance, 42);
|
|
||||||
QVERIFY(instance.recordedValues.isEmpty());
|
|
||||||
check();
|
|
||||||
|
|
||||||
int subscribedCount = 0;
|
|
||||||
QProperty<int> injectedValue(100);
|
|
||||||
instance.property.setBinding(&instance, [&injectedValue]() { return injectedValue.value(); });
|
|
||||||
auto subscriber = [&] { ++subscribedCount; };
|
|
||||||
std::array<QPropertyChangeHandler<decltype (subscriber)>, 10> subscribers = {
|
|
||||||
instance.property.subscribe(subscriber),
|
|
||||||
instance.property.subscribe(subscriber),
|
|
||||||
instance.property.subscribe(subscriber),
|
|
||||||
instance.property.subscribe(subscriber),
|
|
||||||
instance.property.subscribe(subscriber),
|
|
||||||
instance.property.subscribe(subscriber),
|
|
||||||
instance.property.subscribe(subscriber),
|
|
||||||
instance.property.subscribe(subscriber),
|
|
||||||
instance.property.subscribe(subscriber),
|
|
||||||
instance.property.subscribe(subscriber)
|
|
||||||
};
|
|
||||||
|
|
||||||
QCOMPARE(subscribedCount, 10);
|
|
||||||
subscribedCount = 0;
|
|
||||||
|
|
||||||
QCOMPARE(instance.property.value(), 100);
|
|
||||||
QCOMPARE(instance.recordedValues.count(), 1);
|
|
||||||
QCOMPARE(instance.recordedValues.at(0), 100);
|
|
||||||
instance.recordedValues.clear();
|
|
||||||
check();
|
|
||||||
QCOMPARE(subscribedCount, 0);
|
|
||||||
|
|
||||||
injectedValue = 200;
|
|
||||||
QCOMPARE(instance.property.value(), 200);
|
|
||||||
QCOMPARE(instance.recordedValues.count(), 1);
|
|
||||||
QCOMPARE(instance.recordedValues.at(0), 200);
|
|
||||||
instance.recordedValues.clear();
|
|
||||||
check();
|
|
||||||
QCOMPARE(subscribedCount, 10);
|
|
||||||
subscribedCount = 0;
|
|
||||||
|
|
||||||
injectedValue = 400;
|
|
||||||
QCOMPARE(instance.property.value(), 400);
|
|
||||||
QCOMPARE(instance.recordedValues.count(), 1);
|
|
||||||
QCOMPARE(instance.recordedValues.at(0), 400);
|
|
||||||
instance.recordedValues.clear();
|
|
||||||
check();
|
|
||||||
QCOMPARE(subscribedCount, 10);
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
|
||||||
// Values can be rejected
|
|
||||||
ClassWithNotifiedPropertyWithGuard instance2;
|
|
||||||
|
|
||||||
instance2.property2.setValue(&instance2, 1);
|
|
||||||
instance2.property2.setBinding(&instance2, [](){return 42;});
|
|
||||||
instance2.property2.setValue(&instance2, 2);
|
|
||||||
instance2.property2.setBinding(&instance2, [](){return 3;});
|
|
||||||
instance2.property2.setValue(&instance2, 42);
|
|
||||||
// Note that we get 1 twice
|
|
||||||
// This is an unfortunate result of the lazyness used for bindings
|
|
||||||
// When we call setBinding, the binding does not get evaluated, but we
|
|
||||||
// call the callback in notify; the callback will in our case query the
|
|
||||||
// properties' value. At that point we then evaluate the binding, and
|
|
||||||
// notice that the value is in fact disallowed. Thus we return the old
|
|
||||||
// value.
|
|
||||||
QList<int> expected {1, 1, 2, 3};
|
|
||||||
QCOMPARE(instance2.recordedValues, expected);
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
|
||||||
// guard can modify incoming values
|
|
||||||
ClassWithNotifiedPropertyWithGuard instance3;
|
|
||||||
instance3.property3.setValue(&instance3, 5);
|
|
||||||
int i1 = 5;
|
|
||||||
QCOMPARE(instance3.property3.value(), i1);
|
|
||||||
instance3.property3.setBinding(&instance3, [](){return 255;});
|
|
||||||
QCOMPARE(instance3.property3.value(), 100);
|
|
||||||
const int i2 = -1;
|
|
||||||
instance3.property3.setValue(&instance3, i2);
|
|
||||||
QCOMPARE(instance3.property3.value(), 0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void tst_QProperty::typeNoOperatorEqual()
|
void tst_QProperty::typeNoOperatorEqual()
|
||||||
{
|
{
|
||||||
struct Uncomparable
|
struct Uncomparable
|
||||||
@ -1076,42 +839,42 @@ void tst_QProperty::typeNoOperatorEqual()
|
|||||||
p1.setValue(u1);
|
p1.setValue(u1);
|
||||||
QCOMPARE(p1.value().data, p3.value().data);
|
QCOMPARE(p1.value().data, p3.value().data);
|
||||||
|
|
||||||
QNotifiedProperty<Uncomparable, &Uncomparable::changed> np;
|
// QNotifiedProperty<Uncomparable, &Uncomparable::changed> np;
|
||||||
QVERIFY(np.value().data != u1.data);
|
// QVERIFY(np.value().data != u1.data);
|
||||||
np.setValue(&u1, u1);
|
// np.setValue(&u1, u1);
|
||||||
QVERIFY(u1.changedCalled);
|
// QVERIFY(u1.changedCalled);
|
||||||
u1.changedCalled = false;
|
// u1.changedCalled = false;
|
||||||
QCOMPARE(np.value().data, u1.data);
|
// QCOMPARE(np.value().data, u1.data);
|
||||||
np.setValue(&u1, u1);
|
// np.setValue(&u1, u1);
|
||||||
QVERIFY(u1.changedCalled);
|
// QVERIFY(u1.changedCalled);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
struct Test {
|
//struct Test {
|
||||||
void notify() {};
|
// void notify() {};
|
||||||
bool bindText(int);
|
// bool bindText(int);
|
||||||
bool bindIconText(int);
|
// bool bindIconText(int);
|
||||||
QProperty<int> text;
|
// QProperty<int> text;
|
||||||
QNotifiedProperty<int, &Test::notify, &Test::bindIconText> iconText;
|
// QNotifiedProperty<int, &Test::notify, &Test::bindIconText> iconText;
|
||||||
};
|
//};
|
||||||
|
|
||||||
bool Test::bindIconText(int) {
|
//bool Test::bindIconText(int) {
|
||||||
Q_UNUSED(iconText.value()); // force read
|
// Q_UNUSED(iconText.value()); // force read
|
||||||
if (!iconText.hasBinding()) {
|
// if (!iconText.hasBinding()) {
|
||||||
iconText.setBinding(this, [=]() { return 0; });
|
// iconText.setBinding(this, [=]() { return 0; });
|
||||||
}
|
// }
|
||||||
return true;
|
// return true;
|
||||||
}
|
//}
|
||||||
|
|
||||||
void tst_QProperty::bindingValueReplacement()
|
void tst_QProperty::bindingValueReplacement()
|
||||||
{
|
{
|
||||||
Test test;
|
// Test test;
|
||||||
test.text = 0;
|
// test.text = 0;
|
||||||
test.bindIconText(0);
|
// test.bindIconText(0);
|
||||||
test.iconText.setValue(&test, 42); // should not crash
|
// test.iconText.setValue(&test, 42); // should not crash
|
||||||
QCOMPARE(test.iconText.value(), 42);
|
// QCOMPARE(test.iconText.value(), 42);
|
||||||
test.text = 1;
|
// test.text = 1;
|
||||||
QCOMPARE(test.iconText.value(), 42);
|
// QCOMPARE(test.iconText.value(), 42);
|
||||||
}
|
}
|
||||||
|
|
||||||
QTEST_MAIN(tst_QProperty);
|
QTEST_MAIN(tst_QProperty);
|
||||||
|
@ -1543,7 +1543,6 @@ class PrivatePropertyTest : public QObject
|
|||||||
Q_PRIVATE_PROPERTY(PrivatePropertyTest::d, QString blub4 MEMBER mBlub NOTIFY blub4Changed)
|
Q_PRIVATE_PROPERTY(PrivatePropertyTest::d, QString blub4 MEMBER mBlub NOTIFY blub4Changed)
|
||||||
Q_PRIVATE_PROPERTY(PrivatePropertyTest::d, QString blub5 MEMBER mBlub NOTIFY blub5Changed)
|
Q_PRIVATE_PROPERTY(PrivatePropertyTest::d, QString blub5 MEMBER mBlub NOTIFY blub5Changed)
|
||||||
Q_PRIVATE_PROPERTY(PrivatePropertyTest::d, QString blub6 MEMBER mConst CONSTANT)
|
Q_PRIVATE_PROPERTY(PrivatePropertyTest::d, QString blub6 MEMBER mConst CONSTANT)
|
||||||
Q_PRIVATE_PROPERTY(PrivatePropertyTest::d, QProperty<int> x)
|
|
||||||
class MyDPointer {
|
class MyDPointer {
|
||||||
public:
|
public:
|
||||||
MyDPointer() : mConst("const"), mBar(0), mPlop(0) {}
|
MyDPointer() : mConst("const"), mBar(0), mPlop(0) {}
|
||||||
@ -1557,7 +1556,6 @@ class PrivatePropertyTest : public QObject
|
|||||||
void setBlub(const QString &value) { mBlub = value; }
|
void setBlub(const QString &value) { mBlub = value; }
|
||||||
QString mBlub;
|
QString mBlub;
|
||||||
const QString mConst;
|
const QString mConst;
|
||||||
QProperty<int> x;
|
|
||||||
private:
|
private:
|
||||||
int mBar;
|
int mBar;
|
||||||
int mPlop;
|
int mPlop;
|
||||||
@ -1568,6 +1566,7 @@ public:
|
|||||||
int foo() { return mFoo ; }
|
int foo() { return mFoo ; }
|
||||||
void setFoo(int value) { mFoo = value; }
|
void setFoo(int value) { mFoo = value; }
|
||||||
MyDPointer *d_func() {return d.data();}
|
MyDPointer *d_func() {return d.data();}
|
||||||
|
const MyDPointer *d_func() const {return d.data();}
|
||||||
signals:
|
signals:
|
||||||
void blub4Changed();
|
void blub4Changed();
|
||||||
void blub5Changed(const QString &newBlub);
|
void blub5Changed(const QString &newBlub);
|
||||||
@ -1592,10 +1591,6 @@ void tst_Moc::qprivateproperties()
|
|||||||
|
|
||||||
test.setProperty("baz", 4);
|
test.setProperty("baz", 4);
|
||||||
QCOMPARE(test.property("baz"), QVariant::fromValue(4));
|
QCOMPARE(test.property("baz"), QVariant::fromValue(4));
|
||||||
|
|
||||||
test.setProperty("x", 100);
|
|
||||||
QCOMPARE(test.property("x"), QVariant::fromValue(100));
|
|
||||||
QVERIFY(test.metaObject()->property(test.metaObject()->indexOfProperty("x")).isQProperty());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void tst_Moc::warnOnPropertyWithoutREAD()
|
void tst_Moc::warnOnPropertyWithoutREAD()
|
||||||
@ -4084,7 +4079,7 @@ signals:
|
|||||||
void publicPropertyChanged();
|
void publicPropertyChanged();
|
||||||
|
|
||||||
public:
|
public:
|
||||||
QNotifiedProperty<int, &ClassWithQPropertyMembers::publicPropertyChanged> publicProperty;
|
// QNotifiedProperty<int, &ClassWithQPropertyMembers::publicPropertyChanged> publicProperty;
|
||||||
QProperty<int> notExposed;
|
QProperty<int> notExposed;
|
||||||
|
|
||||||
|
|
||||||
@ -4098,87 +4093,88 @@ private:
|
|||||||
|
|
||||||
void tst_Moc::qpropertyMembers()
|
void tst_Moc::qpropertyMembers()
|
||||||
{
|
{
|
||||||
const auto metaObject = &ClassWithQPropertyMembers::staticMetaObject;
|
// const auto metaObject = &ClassWithQPropertyMembers::staticMetaObject;
|
||||||
|
|
||||||
QCOMPARE(metaObject->propertyCount() - metaObject->superClass()->propertyCount(), 2);
|
// QCOMPARE(metaObject->propertyCount() - metaObject->superClass()->propertyCount(), 2);
|
||||||
|
|
||||||
QCOMPARE(metaObject->indexOfProperty("notExposed"), -1);
|
// QCOMPARE(metaObject->indexOfProperty("notExposed"), -1);
|
||||||
|
|
||||||
QMetaProperty prop = metaObject->property(metaObject->indexOfProperty("publicProperty"));
|
// QMetaProperty prop = metaObject->property(metaObject->indexOfProperty("publicProperty"));
|
||||||
QVERIFY(prop.isValid());
|
// QVERIFY(prop.isValid());
|
||||||
|
|
||||||
QVERIFY(metaObject->property(metaObject->indexOfProperty("privateExposedProperty")).isValid());
|
// QVERIFY(metaObject->property(metaObject->indexOfProperty("privateExposedProperty")).isValid());
|
||||||
|
|
||||||
ClassWithQPropertyMembers instance;
|
// ClassWithQPropertyMembers instance;
|
||||||
|
|
||||||
prop.write(&instance, 42);
|
// prop.write(&instance, 42);
|
||||||
QCOMPARE(instance.publicProperty.value(), 42);
|
// QCOMPARE(instance.publicProperty.value(), 42);
|
||||||
|
|
||||||
QSignalSpy publicPropertySpy(&instance, SIGNAL(publicPropertyChanged()));
|
// QSignalSpy publicPropertySpy(&instance, SIGNAL(publicPropertyChanged()));
|
||||||
|
|
||||||
instance.publicProperty.setValue(&instance, 100);
|
// instance.publicProperty.setValue(&instance, 100);
|
||||||
QCOMPARE(prop.read(&instance).toInt(), 100);
|
// QCOMPARE(prop.read(&instance).toInt(), 100);
|
||||||
QCOMPARE(publicPropertySpy.count(), 1);
|
// QCOMPARE(publicPropertySpy.count(), 1);
|
||||||
|
|
||||||
QCOMPARE(prop.metaType(), QMetaType(QMetaType::Int));
|
// QCOMPARE(prop.metaType(), QMetaType(QMetaType::Int));
|
||||||
|
|
||||||
QVERIFY(prop.notifySignal().isValid());
|
// QVERIFY(prop.notifySignal().isValid());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void tst_Moc::observerMetaCall()
|
void tst_Moc::observerMetaCall()
|
||||||
{
|
{
|
||||||
const auto metaObject = &ClassWithQPropertyMembers::staticMetaObject;
|
// const auto metaObject = &ClassWithQPropertyMembers::staticMetaObject;
|
||||||
QMetaProperty prop = metaObject->property(metaObject->indexOfProperty("publicProperty"));
|
// QMetaProperty prop = metaObject->property(metaObject->indexOfProperty("publicProperty"));
|
||||||
QVERIFY(prop.isValid());
|
// QVERIFY(prop.isValid());
|
||||||
|
|
||||||
ClassWithQPropertyMembers instance;
|
// ClassWithQPropertyMembers instance;
|
||||||
|
|
||||||
int observerCallCount = 0;
|
// int observerCallCount = 0;
|
||||||
|
|
||||||
QProperty<int> dummy;
|
|
||||||
auto handler = dummy.onValueChanged([&observerCallCount]() {
|
|
||||||
++observerCallCount;
|
|
||||||
});
|
|
||||||
|
|
||||||
{
|
// auto handler = QPropertyChangeHandler([&observerCallCount]() {
|
||||||
void *argv[] = { &handler };
|
// ++observerCallCount;
|
||||||
instance.qt_metacall(QMetaObject::RegisterQPropertyObserver, prop.propertyIndex(), argv);
|
// });
|
||||||
}
|
|
||||||
|
|
||||||
instance.publicProperty.setValue(&instance, 100);
|
// {
|
||||||
QCOMPARE(observerCallCount, 1);
|
// void *argv[] = { &handler };
|
||||||
instance.publicProperty.setValue(&instance, 101);
|
// instance.qt_metacall(QMetaObject::RegisterQPropertyObserver, prop.propertyIndex(), argv);
|
||||||
QCOMPARE(observerCallCount, 2);
|
// }
|
||||||
|
|
||||||
|
// QCOMPARE(observerCallCount, 0);
|
||||||
|
// instance.publicProperty.setValue(100);
|
||||||
|
// QCOMPARE(observerCallCount, 1);
|
||||||
|
// instance.publicProperty.setValue(&instance, 101);
|
||||||
|
// QCOMPARE(observerCallCount, 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void tst_Moc::setQPRopertyBinding()
|
void tst_Moc::setQPRopertyBinding()
|
||||||
{
|
{
|
||||||
const auto metaObject = &ClassWithQPropertyMembers::staticMetaObject;
|
// const auto metaObject = &ClassWithQPropertyMembers::staticMetaObject;
|
||||||
QMetaProperty prop = metaObject->property(metaObject->indexOfProperty("publicProperty"));
|
// QMetaProperty prop = metaObject->property(metaObject->indexOfProperty("publicProperty"));
|
||||||
QVERIFY(prop.isValid());
|
// QVERIFY(prop.isValid());
|
||||||
|
|
||||||
ClassWithQPropertyMembers instance;
|
// ClassWithQPropertyMembers instance;
|
||||||
|
|
||||||
bool bindingCalled = false;
|
// bool bindingCalled = false;
|
||||||
auto binding = Qt::makePropertyBinding([&bindingCalled]() {
|
// auto binding = Qt::makePropertyBinding([&bindingCalled]() {
|
||||||
bindingCalled = true;
|
// bindingCalled = true;
|
||||||
return 42;
|
// return 42;
|
||||||
});
|
// });
|
||||||
|
|
||||||
{
|
// {
|
||||||
void *argv[] = { &binding };
|
// void *argv[] = { &binding };
|
||||||
instance.qt_metacall(QMetaObject::SetQPropertyBinding, prop.propertyIndex(), argv);
|
// instance.qt_metacall(QMetaObject::SetQPropertyBinding, prop.propertyIndex(), argv);
|
||||||
}
|
// }
|
||||||
|
|
||||||
QCOMPARE(instance.publicProperty.value(), 42);
|
// QCOMPARE(instance.publicProperty.value(), 42);
|
||||||
QVERIFY(bindingCalled); // but now it should've been called :)
|
// QVERIFY(bindingCalled); // but now it should've been called :)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if 0
|
||||||
class ClassWithPrivateQPropertyShim :public QObject
|
class ClassWithPrivateQPropertyShim :public QObject
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
@ -4231,54 +4227,54 @@ public:
|
|||||||
Private *d_func() { return &priv; }
|
Private *d_func() { return &priv; }
|
||||||
const Private *d_func() const { return &priv; }
|
const Private *d_func() const { return &priv; }
|
||||||
};
|
};
|
||||||
|
#endif
|
||||||
|
|
||||||
void tst_Moc::privateQPropertyShim()
|
void tst_Moc::privateQPropertyShim()
|
||||||
{
|
{
|
||||||
ClassWithPrivateQPropertyShim testObject;
|
// ClassWithPrivateQPropertyShim testObject;
|
||||||
|
|
||||||
{
|
// {
|
||||||
auto metaObject = &ClassWithPrivateQPropertyShim::staticMetaObject;
|
// auto metaObject = &ClassWithPrivateQPropertyShim::staticMetaObject;
|
||||||
QMetaProperty prop = metaObject->property(metaObject->indexOfProperty("testProperty"));
|
// QMetaProperty prop = metaObject->property(metaObject->indexOfProperty("testProperty"));
|
||||||
QVERIFY(prop.isValid());
|
// QVERIFY(prop.isValid());
|
||||||
QVERIFY(prop.notifySignal().isValid());
|
// QVERIFY(prop.notifySignal().isValid());
|
||||||
}
|
// }
|
||||||
|
|
||||||
testObject.priv.testProperty.setValue(&testObject.priv, 42);
|
// testObject.priv.testProperty.setValue(&testObject.priv, 42);
|
||||||
QCOMPARE(testObject.property("testProperty").toInt(), 42);
|
// QCOMPARE(testObject.property("testProperty").toInt(), 42);
|
||||||
|
|
||||||
// Behave like a QProperty
|
// // Behave like a QProperty
|
||||||
QVERIFY(!testObject.testProperty.hasBinding());
|
// QVERIFY(!testObject.testProperty.hasBinding());
|
||||||
testObject.testProperty.setBinding([]() { return 100; });
|
// testObject.testProperty.setBinding([]() { return 100; });
|
||||||
QCOMPARE(testObject.testProperty.value(), 100);
|
// QCOMPARE(testObject.testProperty.value(), 100);
|
||||||
QVERIFY(testObject.testProperty.hasBinding());
|
// QVERIFY(testObject.testProperty.hasBinding());
|
||||||
|
|
||||||
// Old style setter getters
|
// // Old style setter getters
|
||||||
testObject.setTestProperty(400);
|
// testObject.setTestProperty(400);
|
||||||
QVERIFY(!testObject.testProperty.hasBinding());
|
// QVERIFY(!testObject.testProperty.hasBinding());
|
||||||
QCOMPARE(testObject.testProperty(), 400);
|
// QCOMPARE(testObject.testProperty(), 400);
|
||||||
|
|
||||||
// Created and default-initialized, without nullptr access
|
// // Created and default-initialized, without nullptr access
|
||||||
QCOMPARE(testObject.lazyTestProperty(), 0);
|
// QCOMPARE(testObject.lazyTestProperty(), 0);
|
||||||
|
|
||||||
// Explicitly set to something
|
// // Explicitly set to something
|
||||||
testObject.priv.lazyTestProperty()->setValue(&testObject.priv, 42);
|
// testObject.priv.lazyTestProperty()->setValue(&testObject.priv, 42);
|
||||||
QCOMPARE(testObject.property("lazyTestProperty").toInt(), 42);
|
// QCOMPARE(testObject.property("lazyTestProperty").toInt(), 42);
|
||||||
|
|
||||||
// Behave like a QProperty
|
// // Behave like a QProperty
|
||||||
QVERIFY(!testObject.lazyTestProperty.hasBinding());
|
// QVERIFY(!testObject.lazyTestProperty.hasBinding());
|
||||||
testObject.lazyTestProperty.setBinding([]() { return 100; });
|
// testObject.lazyTestProperty.setBinding([]() { return 100; });
|
||||||
QCOMPARE(testObject.lazyTestProperty.value(), 100);
|
// QCOMPARE(testObject.lazyTestProperty.value(), 100);
|
||||||
QVERIFY(testObject.lazyTestProperty.hasBinding());
|
// QVERIFY(testObject.lazyTestProperty.hasBinding());
|
||||||
|
|
||||||
// Old style setter getters
|
// // Old style setter getters
|
||||||
testObject.setLazyTestProperty(400);
|
// testObject.setLazyTestProperty(400);
|
||||||
QVERIFY(!testObject.lazyTestProperty.hasBinding());
|
// QVERIFY(!testObject.lazyTestProperty.hasBinding());
|
||||||
QCOMPARE(testObject.lazyTestProperty(), 400);
|
// QCOMPARE(testObject.lazyTestProperty(), 400);
|
||||||
|
|
||||||
// mo generates correct code for plain QProperty in PIMPL
|
// // mo generates correct code for plain QProperty in PIMPL
|
||||||
testObject.testProperty2.setValue(42);
|
// testObject.testProperty2.setValue(42);
|
||||||
QCOMPARE(testObject.testProperty2.value(), 42);
|
// QCOMPARE(testObject.testProperty2.value(), 42);
|
||||||
}
|
}
|
||||||
|
|
||||||
QTEST_MAIN(tst_Moc)
|
QTEST_MAIN(tst_Moc)
|
||||||
|
Loading…
Reference in New Issue
Block a user