From 4ceaf22bed1bc0ed2dec4628fd9d9814c0e0fd86 Mon Sep 17 00:00:00 2001 From: Fabian Kosmale Date: Wed, 3 Feb 2021 15:25:37 +0100 Subject: [PATCH] QObjectCompatProperty: Emit signal in notfiy There is no need to write emit and notify at the same time, as not emitting after notify does not make sense. This naturally only applies to properties with a changed signal. Change-Id: I99ff7863a509262ad9d4f7c9c5afbc66fd37001c Reviewed-by: Ulf Hermann --- src/corelib/kernel/qproperty.h | 2 +- src/corelib/kernel/qproperty_p.h | 59 +++++++++++++++---- .../kernel/qproperty/tst_qproperty.cpp | 12 ++-- 3 files changed, 55 insertions(+), 18 deletions(-) diff --git a/src/corelib/kernel/qproperty.h b/src/corelib/kernel/qproperty.h index 6672f270f4..a085aac3d1 100644 --- a/src/corelib/kernel/qproperty.h +++ b/src/corelib/kernel/qproperty.h @@ -844,7 +844,7 @@ class Q_CORE_EXPORT QBindingStorage mutable QBindingStorageData *d = nullptr; QBindingStatus *bindingStatus = nullptr; - template + template friend class QObjectCompatProperty; public: QBindingStorage(); diff --git a/src/corelib/kernel/qproperty_p.h b/src/corelib/kernel/qproperty_p.h index a355a7faea..b4d41a362b 100644 --- a/src/corelib/kernel/qproperty_p.h +++ b/src/corelib/kernel/qproperty_p.h @@ -385,10 +385,11 @@ inline QPropertyObserverPointer QPropertyBindingDataPointer::firstObserver() con return { reinterpret_cast(ptr->d_ptr) }; } -template +template class QObjectCompatProperty : public QPropertyData { - using ThisType = QObjectCompatProperty; + using ThisType = QObjectCompatProperty; + using SignalTakesValue = std::is_invocable; Class *owner() { char *that = reinterpret_cast(this); @@ -523,6 +524,21 @@ public: bd->removeBinding(); } + void notify() + { + QBindingStorage *storage = qGetBindingStorage(owner()); + auto bd = storage->bindingData(this, false); + const bool inWrapper = inBindingWrapper(storage); + if (bd && !inWrapper) + notify(bd); + if constexpr (Signal != nullptr) { + if constexpr (SignalTakesValue::value) + (owner()->*Signal)(value()); + else + (owner()->*Signal)(); + } + } + QPropertyBinding binding() const { auto *bd = qGetBindingStorage(owner())->bindingData(this); @@ -562,24 +578,45 @@ private: } }; -#define Q_OBJECT_COMPAT_PROPERTY(Class, Type, name, setter) \ +#define Q_OBJECT_COMPAT_PROPERTY4(Class, Type, name, setter) \ static constexpr size_t _qt_property_##name##_offset() { \ - QT_WARNING_PUSH QT_WARNING_DISABLE_INVALID_OFFSETOF \ return offsetof(Class, name); \ - QT_WARNING_POP \ } \ QObjectCompatProperty name; -#define Q_OBJECT_COMPAT_PROPERTY_WITH_ARGS(Class, Type, name, setter, value) \ - static constexpr size_t _qt_property_##name##_offset() \ - { \ - QT_WARNING_PUSH QT_WARNING_DISABLE_INVALID_OFFSETOF return offsetof(Class, name); \ - QT_WARNING_POP \ - } \ +#define Q_OBJECT_COMPAT_PROPERTY5(Class, Type, name, setter, signal) \ + static constexpr size_t _qt_property_##name##_offset() { \ + return offsetof(Class, name); \ + } \ + QObjectCompatProperty name; + +#define Q_OBJECT_COMPAT_PROPERTY(...) \ + QT_WARNING_PUSH QT_WARNING_DISABLE_INVALID_OFFSETOF \ + QT_OVERLOADED_MACRO(Q_OBJECT_COMPAT_PROPERTY, __VA_ARGS__) \ + QT_WARNING_POP + +#define Q_OBJECT_COMPAT_PROPERTY_WITH_ARGS5(Class, Type, name, setter, value) \ + static constexpr size_t _qt_property_##name##_offset() { \ + return offsetof(Class, name); \ + } \ QObjectCompatProperty name = \ QObjectCompatProperty( \ value); +#define Q_OBJECT_COMPAT_PROPERTY_WITH_ARGS6(Class, Type, name, setter, signal, value) \ + static constexpr size_t _qt_property_##name##_offset() { \ + return offsetof(Class, name); \ + } \ + QObjectCompatProperty name = \ + QObjectCompatProperty( \ + value); + +#define Q_OBJECT_COMPAT_PROPERTY_WITH_ARGS(...) \ + QT_WARNING_PUSH QT_WARNING_DISABLE_INVALID_OFFSETOF \ + QT_OVERLOADED_MACRO(Q_OBJECT_COMPAT_PROPERTY_WITH_ARGS, __VA_ARGS__) \ + QT_WARNING_POP + + namespace QtPrivate { Q_CORE_EXPORT BindingEvaluationState *suspendCurrentBindingStatus(); Q_CORE_EXPORT void restoreBindingStatus(BindingEvaluationState *status); diff --git a/tests/auto/corelib/kernel/qproperty/tst_qproperty.cpp b/tests/auto/corelib/kernel/qproperty/tst_qproperty.cpp index 4186607d90..5ca5fcf935 100644 --- a/tests/auto/corelib/kernel/qproperty/tst_qproperty.cpp +++ b/tests/auto/corelib/kernel/qproperty/tst_qproperty.cpp @@ -1422,9 +1422,9 @@ signals: void prop3Changed(); public: - void setProp1(int val) { prop1Data.setValue(val); prop1Data.notify(); emit prop1Changed();} - void setProp2(int val) { prop2Data.setValue(val); prop2Data.notify(); emit prop2Changed();} - void setProp3(int val) { prop3Data.setValue(val); prop3Data.notify(); emit prop3Changed();} + void setProp1(int val) { prop1Data.setValue(val); prop1Data.notify();} + void setProp2(int val) { prop2Data.setValue(val); prop2Data.notify();} + void setProp3(int val) { prop3Data.setValue(val); prop3Data.notify();} int prop1() { return prop1Data; } int prop2() { return prop2Data; } @@ -1435,9 +1435,9 @@ public: QBindable bindableProp3() { return QBindable(&prop3Data); } private: - Q_OBJECT_COMPAT_PROPERTY(FakeDependencyCreator, int, prop1Data, &FakeDependencyCreator::setProp1); - Q_OBJECT_COMPAT_PROPERTY(FakeDependencyCreator, int, prop2Data, &FakeDependencyCreator::setProp2); - Q_OBJECT_COMPAT_PROPERTY(FakeDependencyCreator, int, prop3Data, &FakeDependencyCreator::setProp3); + Q_OBJECT_COMPAT_PROPERTY(FakeDependencyCreator, int, prop1Data, &FakeDependencyCreator::setProp1, &FakeDependencyCreator::prop1Changed); + Q_OBJECT_COMPAT_PROPERTY(FakeDependencyCreator, int, prop2Data, &FakeDependencyCreator::setProp2, &FakeDependencyCreator::prop2Changed); + Q_OBJECT_COMPAT_PROPERTY(FakeDependencyCreator, int, prop3Data, &FakeDependencyCreator::setProp3, &FakeDependencyCreator::prop3Changed); }; void tst_QProperty::noFakeDependencies()