From 1a65a4faf52f83ba3fbbba88cea1c4bb800e8de7 Mon Sep 17 00:00:00 2001 From: Ivan Solovev Date: Mon, 14 Dec 2020 12:27:53 +0100 Subject: QObject: port to new property system Extended QObjectPrivate::ExtraData to store a pointer to its parent, and reimplemented qGetBindingStorage() function for QObjectPrivate::ExtraData. This allows to use Q_OBJECT_COMPAT_PROPERTY macro for a property, stored in QObjectPrivate::ExtraData and solves all the problems with calling a custom setter. Task-number: QTBUG-85520 Change-Id: I40e01c29430846359ef9160fa1ae97c702be9a18 Reviewed-by: Edward Welbourne Reviewed-by: Sona Kurazyan --- src/corelib/global/qhooks.cpp | 2 +- src/corelib/kernel/qobject.cpp | 30 ++++++++++++++++++++++++------ src/corelib/kernel/qobject.h | 4 +++- src/corelib/kernel/qobject_p.h | 31 +++++++++++++++++++++++++++---- 4 files changed, 55 insertions(+), 12 deletions(-) (limited to 'src') diff --git a/src/corelib/global/qhooks.cpp b/src/corelib/global/qhooks.cpp index c3a625bb5f..491e126b7a 100644 --- a/src/corelib/global/qhooks.cpp +++ b/src/corelib/global/qhooks.cpp @@ -67,7 +67,7 @@ quintptr Q_CORE_EXPORT qtHookData[] = { // The required sizes and offsets are tested in tests/auto/other/toolsupport. // When this fails and the change was intentional, adjust the test and // adjust this value here. - 20 + 21 }; static_assert(QHooks::LastHookIndex == sizeof(qtHookData) / sizeof(qtHookData[0])); diff --git a/src/corelib/kernel/qobject.cpp b/src/corelib/kernel/qobject.cpp index 343922581c..b115066dce 100644 --- a/src/corelib/kernel/qobject.cpp +++ b/src/corelib/kernel/qobject.cpp @@ -1214,6 +1214,11 @@ QObjectPrivate::Connection::~Connection() QString QObject::objectName() const { Q_D(const QObject); + if (!d->extraData && QtPrivate::isAnyBindingEvaluating()) { + QObjectPrivate *dd = const_cast(d); + // extraData is mutable, so this should be safe + dd->extraData = new QObjectPrivate::ExtraData(dd); + } return d->extraData ? d->extraData->objectName : QString(); } @@ -1223,15 +1228,28 @@ QString QObject::objectName() const void QObject::setObjectName(const QString &name) { Q_D(QObject); + if (!d->extraData) - d->extraData = new QObjectPrivate::ExtraData; + d->extraData = new QObjectPrivate::ExtraData(d); + + d->extraData->objectName.removeBindingUnlessInWrapper(); if (d->extraData->objectName != name) { - d->extraData->objectName = name; - emit objectNameChanged(d->extraData->objectName, QPrivateSignal()); + d->extraData->objectName.setValueBypassingBindings(name); + d->extraData->objectName.notify(); // also emits a signal } } +QBindable QObject::bindableObjectName() +{ + Q_D(QObject); + + if (!d->extraData) + d->extraData = new QObjectPrivate::ExtraData(d); + + return QBindable(&d->extraData->objectName); +} + /*! \fn void QObject::objectNameChanged(const QString &objectName) This signal is emitted after the object's name has been changed. The new object name is passed as \a objectName. @@ -1731,7 +1749,7 @@ int QObject::startTimer(int interval, Qt::TimerType timerType) } int timerId = thisThreadData->eventDispatcher.loadRelaxed()->registerTimer(interval, timerType, this); if (!d->extraData) - d->extraData = new QObjectPrivate::ExtraData; + d->extraData = new QObjectPrivate::ExtraData(d); d->extraData->runningTimers.append(timerId); return timerId; } @@ -2164,7 +2182,7 @@ void QObject::installEventFilter(QObject *obj) } if (!d->extraData) - d->extraData = new QObjectPrivate::ExtraData; + d->extraData = new QObjectPrivate::ExtraData(d); // clean up unused items in the list d->extraData->eventFilters.removeAll((QObject *)nullptr); @@ -3971,7 +3989,7 @@ bool QObject::setProperty(const char *name, const QVariant &value) int id = meta->indexOfProperty(name); if (id < 0) { if (!d->extraData) - d->extraData = new QObjectPrivate::ExtraData; + d->extraData = new QObjectPrivate::ExtraData(d); const int idx = d->extraData->propertyNames.indexOf(name); diff --git a/src/corelib/kernel/qobject.h b/src/corelib/kernel/qobject.h index 5742db1c22..c59518367d 100644 --- a/src/corelib/kernel/qobject.h +++ b/src/corelib/kernel/qobject.h @@ -120,7 +120,8 @@ class Q_CORE_EXPORT QObject { Q_OBJECT - Q_PROPERTY(QString objectName READ objectName WRITE setObjectName NOTIFY objectNameChanged) + Q_PROPERTY(QString objectName READ objectName WRITE setObjectName NOTIFY objectNameChanged + BINDABLE bindableObjectName) Q_DECLARE_PRIVATE(QObject) public: @@ -137,6 +138,7 @@ public: QString objectName() const; void setObjectName(const QString &name); + QBindable bindableObjectName(); inline bool isWidgetType() const { return d_ptr->isWidget; } inline bool isWindowType() const { return d_ptr->isWindow; } diff --git a/src/corelib/kernel/qobject_p.h b/src/corelib/kernel/qobject_p.h index 019473018f..673c75fff1 100644 --- a/src/corelib/kernel/qobject_p.h +++ b/src/corelib/kernel/qobject_p.h @@ -61,6 +61,7 @@ #include "QtCore/qsharedpointer.h" #include "QtCore/qvariant.h" #include "QtCore/qproperty.h" +#include "QtCore/private/qproperty_p.h" QT_BEGIN_NAMESPACE @@ -102,12 +103,26 @@ class Q_CORE_EXPORT QObjectPrivate : public QObjectData public: struct ExtraData { - ExtraData() {} + ExtraData(QObjectPrivate *ptr) : parent(ptr) { } + + inline void setObjectNameForwarder(const QString &name) + { + parent->q_func()->setObjectName(name); + } + + inline void nameChangedForwarder(const QString &name) + { + emit parent->q_func()->objectNameChanged(name, QObject::QPrivateSignal()); + } + QList propertyNames; QList propertyValues; QList runningTimers; QList> eventFilters; - QString objectName; + Q_OBJECT_COMPAT_PROPERTY(QObjectPrivate::ExtraData, QString, objectName, + &QObjectPrivate::ExtraData::setObjectNameForwarder, + &QObjectPrivate::ExtraData::nameChangedForwarder) + QObjectPrivate *parent; }; typedef void (*StaticMetaCallFunction)(QObject *, QMetaObject::Call, int, void **); @@ -369,8 +384,9 @@ public: cd->ref.ref(); connections.storeRelaxed(cd); } + public: - ExtraData *extraData; // extra data set by the user + mutable ExtraData *extraData; // extra data set by the user // This atomic requires acquire/release semantics in a few places, // e.g. QObject::moveToThread must synchronize with QCoreApplication::postEvent, // because postEvent is thread-safe. @@ -619,7 +635,14 @@ inline QBindingStorage *qGetBindingStorage(QObjectPrivate *o) { return &o->bindingStorage; } - +inline const QBindingStorage *qGetBindingStorage(const QObjectPrivate::ExtraData *ed) +{ + return &ed->parent->bindingStorage; +} +inline QBindingStorage *qGetBindingStorage(QObjectPrivate::ExtraData *ed) +{ + return &ed->parent->bindingStorage; +} QT_END_NAMESPACE -- cgit v1.2.3