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 <ulf.hermann@qt.io>
This commit is contained in:
Fabian Kosmale 2021-02-03 15:25:37 +01:00
parent 2ffb91ac59
commit 4ceaf22bed
3 changed files with 55 additions and 18 deletions

View File

@ -844,7 +844,7 @@ class Q_CORE_EXPORT QBindingStorage
mutable QBindingStorageData *d = nullptr; mutable QBindingStorageData *d = nullptr;
QBindingStatus *bindingStatus = nullptr; QBindingStatus *bindingStatus = nullptr;
template<typename Class, typename T, auto Offset, auto Setter> template<typename Class, typename T, auto Offset, auto Setter, auto Signal>
friend class QObjectCompatProperty; friend class QObjectCompatProperty;
public: public:
QBindingStorage(); QBindingStorage();

View File

@ -385,10 +385,11 @@ inline QPropertyObserverPointer QPropertyBindingDataPointer::firstObserver() con
return { reinterpret_cast<QPropertyObserver *>(ptr->d_ptr) }; return { reinterpret_cast<QPropertyObserver *>(ptr->d_ptr) };
} }
template<typename Class, typename T, auto Offset, auto Setter> template<typename Class, typename T, auto Offset, auto Setter, auto Signal=nullptr>
class QObjectCompatProperty : public QPropertyData<T> class QObjectCompatProperty : public QPropertyData<T>
{ {
using ThisType = QObjectCompatProperty<Class, T, Offset, Setter>; using ThisType = QObjectCompatProperty<Class, T, Offset, Setter, Signal>;
using SignalTakesValue = std::is_invocable<decltype(Signal), Class, T>;
Class *owner() Class *owner()
{ {
char *that = reinterpret_cast<char *>(this); char *that = reinterpret_cast<char *>(this);
@ -523,6 +524,21 @@ public:
bd->removeBinding(); 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<T> binding() const QPropertyBinding<T> binding() const
{ {
auto *bd = qGetBindingStorage(owner())->bindingData(this); 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() { \ static constexpr size_t _qt_property_##name##_offset() { \
QT_WARNING_PUSH QT_WARNING_DISABLE_INVALID_OFFSETOF \
return offsetof(Class, name); \ return offsetof(Class, name); \
QT_WARNING_POP \
} \ } \
QObjectCompatProperty<Class, Type, Class::_qt_property_##name##_offset, setter> name; QObjectCompatProperty<Class, Type, Class::_qt_property_##name##_offset, setter> name;
#define Q_OBJECT_COMPAT_PROPERTY_WITH_ARGS(Class, Type, name, setter, value) \ #define Q_OBJECT_COMPAT_PROPERTY5(Class, Type, name, setter, signal) \
static constexpr size_t _qt_property_##name##_offset() \ static constexpr size_t _qt_property_##name##_offset() { \
{ \ return offsetof(Class, name); \
QT_WARNING_PUSH QT_WARNING_DISABLE_INVALID_OFFSETOF return offsetof(Class, name); \ } \
QT_WARNING_POP \ QObjectCompatProperty<Class, Type, Class::_qt_property_##name##_offset, setter, signal> 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<Class, Type, Class::_qt_property_##name##_offset, setter> name = \ QObjectCompatProperty<Class, Type, Class::_qt_property_##name##_offset, setter> name = \
QObjectCompatProperty<Class, Type, Class::_qt_property_##name##_offset, setter>( \ QObjectCompatProperty<Class, Type, Class::_qt_property_##name##_offset, setter>( \
value); 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<Class, Type, Class::_qt_property_##name##_offset, setter> name = \
QObjectCompatProperty<Class, Type, Class::_qt_property_##name##_offset, setter>( \
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 { namespace QtPrivate {
Q_CORE_EXPORT BindingEvaluationState *suspendCurrentBindingStatus(); Q_CORE_EXPORT BindingEvaluationState *suspendCurrentBindingStatus();
Q_CORE_EXPORT void restoreBindingStatus(BindingEvaluationState *status); Q_CORE_EXPORT void restoreBindingStatus(BindingEvaluationState *status);

View File

@ -1422,9 +1422,9 @@ signals:
void prop3Changed(); void prop3Changed();
public: public:
void setProp1(int val) { prop1Data.setValue(val); prop1Data.notify(); emit prop1Changed();} void setProp1(int val) { prop1Data.setValue(val); prop1Data.notify();}
void setProp2(int val) { prop2Data.setValue(val); prop2Data.notify(); emit prop2Changed();} void setProp2(int val) { prop2Data.setValue(val); prop2Data.notify();}
void setProp3(int val) { prop3Data.setValue(val); prop3Data.notify(); emit prop3Changed();} void setProp3(int val) { prop3Data.setValue(val); prop3Data.notify();}
int prop1() { return prop1Data; } int prop1() { return prop1Data; }
int prop2() { return prop2Data; } int prop2() { return prop2Data; }
@ -1435,9 +1435,9 @@ public:
QBindable<int> bindableProp3() { return QBindable<int>(&prop3Data); } QBindable<int> bindableProp3() { return QBindable<int>(&prop3Data); }
private: private:
Q_OBJECT_COMPAT_PROPERTY(FakeDependencyCreator, int, prop1Data, &FakeDependencyCreator::setProp1); Q_OBJECT_COMPAT_PROPERTY(FakeDependencyCreator, int, prop1Data, &FakeDependencyCreator::setProp1, &FakeDependencyCreator::prop1Changed);
Q_OBJECT_COMPAT_PROPERTY(FakeDependencyCreator, int, prop2Data, &FakeDependencyCreator::setProp2); Q_OBJECT_COMPAT_PROPERTY(FakeDependencyCreator, int, prop2Data, &FakeDependencyCreator::setProp2, &FakeDependencyCreator::prop2Changed);
Q_OBJECT_COMPAT_PROPERTY(FakeDependencyCreator, int, prop3Data, &FakeDependencyCreator::setProp3); Q_OBJECT_COMPAT_PROPERTY(FakeDependencyCreator, int, prop3Data, &FakeDependencyCreator::setProp3, &FakeDependencyCreator::prop3Changed);
}; };
void tst_QProperty::noFakeDependencies() void tst_QProperty::noFakeDependencies()