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:
Lars Knoll 2020-08-21 13:00:02 +02:00
parent e638e8a28d
commit e6988d4d0b
13 changed files with 201 additions and 1288 deletions

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -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" },

View File

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

View File

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