diff options
Diffstat (limited to 'src/corelib/kernel/qproperty.h')
-rw-r--r-- | src/corelib/kernel/qproperty.h | 142 |
1 files changed, 124 insertions, 18 deletions
diff --git a/src/corelib/kernel/qproperty.h b/src/corelib/kernel/qproperty.h index fbd838654f..8c4b13cf5e 100644 --- a/src/corelib/kernel/qproperty.h +++ b/src/corelib/kernel/qproperty.h @@ -7,22 +7,32 @@ #include <QtCore/qglobal.h> #include <QtCore/qshareddata.h> #include <QtCore/qstring.h> +#include <QtCore/qttypetraits.h> #include <QtCore/qbindingstorage.h> #include <type_traits> #include <QtCore/qpropertyprivate.h> -#if __has_include(<source_location>) && __cplusplus >= 202002L && !defined(Q_CLANG_QDOC) +#if __has_include(<source_location>) && __cplusplus >= 202002L && !defined(Q_QDOC) #include <source_location> #if defined(__cpp_lib_source_location) #define QT_SOURCE_LOCATION_NAMESPACE std #define QT_PROPERTY_COLLECT_BINDING_LOCATION -#define QT_PROPERTY_DEFAULT_BINDING_LOCATION QPropertyBindingSourceLocation(std::source_location::current()) +#if defined(Q_CC_MSVC) +/* MSVC runs into an issue with constexpr with source location (error C7595) + so use the factory function as a workaround */ +# define QT_PROPERTY_DEFAULT_BINDING_LOCATION QPropertyBindingSourceLocation::fromStdSourceLocation(std::source_location::current()) +#else +/* some versions of gcc in turn run into + expression ‘std::source_location::current()’ is not a constant expression + so don't use the workaround there */ +# define QT_PROPERTY_DEFAULT_BINDING_LOCATION QPropertyBindingSourceLocation(std::source_location::current()) +#endif #endif #endif -#if __has_include(<experimental/source_location>) && !defined(Q_CLANG_QDOC) +#if __has_include(<experimental/source_location>) && !defined(Q_QDOC) #include <experimental/source_location> #if !defined(QT_PROPERTY_COLLECT_BINDING_LOCATION) #if defined(__cpp_lib_experimental_source_location) @@ -44,6 +54,17 @@ Q_CORE_EXPORT void beginPropertyUpdateGroup(); Q_CORE_EXPORT void endPropertyUpdateGroup(); } +class QScopedPropertyUpdateGroup +{ + Q_DISABLE_COPY_MOVE(QScopedPropertyUpdateGroup) +public: + Q_NODISCARD_CTOR + QScopedPropertyUpdateGroup() + { Qt::beginPropertyUpdateGroup(); } + ~QScopedPropertyUpdateGroup() noexcept(false) + { Qt::endPropertyUpdateGroup(); } +}; + template <typename T> class QPropertyData : public QUntypedPropertyData { @@ -86,6 +107,12 @@ struct Q_CORE_EXPORT QPropertyBindingSourceLocation line = cppLocation.line(); column = cppLocation.column(); } + QT_POST_CXX17_API_IN_EXPORTED_CLASS + static consteval QPropertyBindingSourceLocation + fromStdSourceLocation(const std::source_location &cppLocation) + { + return cppLocation; + } #endif #ifdef __cpp_lib_experimental_source_location constexpr QPropertyBindingSourceLocation(const std::experimental::source_location &cppLocation) @@ -202,7 +229,9 @@ public: ObserverNotifiesBinding, // observer was installed to notify bindings that obsverved property changed ObserverNotifiesChangeHandler, // observer is a change handler, which runs on every change ObserverIsPlaceholder, // the observer before this one is currently evaluated in QPropertyObserver::notifyObservers. - ObserverIsAlias +#if QT_DEPRECATED_SINCE(6, 6) + ObserverIsAlias QT_DEPRECATED_VERSION_X_6_6("Use QProperty and add a binding to the target.") +#endif }; protected: using ChangeHandler = void (*)(QPropertyObserver*, QUntypedPropertyData *); @@ -235,14 +264,17 @@ public: QPropertyObserver &operator=(QPropertyObserver &&other) noexcept; ~QPropertyObserver(); - template<typename Property, typename = typename Property::InheritsQUntypedPropertyData> + template <typename Property, QtPrivate::IsUntypedPropertyData<Property> = true> void setSource(const Property &property) { setSource(property.bindingData()); } void setSource(const QtPrivate::QPropertyBindingData &property); protected: QPropertyObserver(ChangeHandler changeHandler); +#if QT_DEPRECATED_SINCE(6, 6) + QT_DEPRECATED_VERSION_X_6_6("This constructor was only meant for internal use. Use QProperty and add a binding to the target.") QPropertyObserver(QUntypedPropertyData *aliasedPropertyPtr); +#endif QUntypedPropertyData *aliasedProperty() const { @@ -257,10 +289,11 @@ private: }; template <typename Functor> -class [[nodiscard]] QPropertyChangeHandler : public QPropertyObserver +class QPropertyChangeHandler : public QPropertyObserver { Functor m_handler; public: + Q_NODISCARD_CTOR QPropertyChangeHandler(Functor handler) : QPropertyObserver([](QPropertyObserver *self, QUntypedPropertyData *) { auto This = static_cast<QPropertyChangeHandler<Functor>*>(self); @@ -270,7 +303,8 @@ public: { } - template<typename Property, typename = typename Property::InheritsQUntypedPropertyData> + template <typename Property, QtPrivate::IsUntypedPropertyData<Property> = true> + Q_NODISCARD_CTOR QPropertyChangeHandler(const Property &property, Functor handler) : QPropertyObserver([](QPropertyObserver *self, QUntypedPropertyData *) { auto This = static_cast<QPropertyChangeHandler<Functor>*>(self); @@ -282,12 +316,14 @@ public: } }; -class [[nodiscard]] QPropertyNotifier : public QPropertyObserver +class QPropertyNotifier : public QPropertyObserver { std::function<void()> m_handler; public: + Q_NODISCARD_CTOR QPropertyNotifier() = default; template<typename Functor> + Q_NODISCARD_CTOR QPropertyNotifier(Functor handler) : QPropertyObserver([](QPropertyObserver *self, QUntypedPropertyData *) { auto This = static_cast<QPropertyNotifier *>(self); @@ -297,7 +333,9 @@ public: { } - template<typename Functor, typename Property, typename = typename Property::InheritsQUntypedPropertyData> + template <typename Functor, typename Property, + QtPrivate::IsUntypedPropertyData<Property> = true> + Q_NODISCARD_CTOR QPropertyNotifier(const Property &property, Functor handler) : QPropertyObserver([](QPropertyObserver *self, QUntypedPropertyData *) { auto This = static_cast<QPropertyNotifier *>(self); @@ -334,7 +372,7 @@ public: explicit QProperty(const QPropertyBinding<T> &binding) : QProperty() { setBinding(binding); } -#ifndef Q_CLANG_QDOC +#ifndef Q_QDOC template <typename Functor> explicit QProperty(Functor &&f, const QPropertyBindingSourceLocation &location = QT_PROPERTY_DEFAULT_BINDING_LOCATION, typename std::enable_if_t<std::is_invocable_r_v<T, Functor&>> * = nullptr) @@ -417,7 +455,7 @@ public: return true; } -#ifndef Q_CLANG_QDOC +#ifndef Q_QDOC template <typename Functor> QPropertyBinding<T> setBinding(Functor &&f, const QPropertyBindingSourceLocation &location = QT_PROPERTY_DEFAULT_BINDING_LOCATION, @@ -582,6 +620,60 @@ enum Reason { InvalidInterface, NonBindableInterface, ReadOnlyInterface }; Q_CORE_EXPORT void printUnsuitableBindableWarning(QAnyStringView prefix, Reason reason); Q_CORE_EXPORT void printMetaTypeMismatch(QMetaType actual, QMetaType expected); } + +namespace PropertyAdaptorSlotObjectHelpers { +Q_CORE_EXPORT void getter(const QUntypedPropertyData *d, void *value); +Q_CORE_EXPORT void setter(QUntypedPropertyData *d, const void *value); +Q_CORE_EXPORT QUntypedPropertyBinding getBinding(const QUntypedPropertyData *d); +Q_CORE_EXPORT bool bindingWrapper(QMetaType type, QUntypedPropertyData *d, + QtPrivate::QPropertyBindingFunction binding, + QUntypedPropertyData *temp, void *value); +Q_CORE_EXPORT QUntypedPropertyBinding setBinding(QUntypedPropertyData *d, + const QUntypedPropertyBinding &binding, + QPropertyBindingWrapper wrapper); +Q_CORE_EXPORT void setObserver(const QUntypedPropertyData *d, QPropertyObserver *observer); + +template<typename T> +bool bindingWrapper(QMetaType type, QUntypedPropertyData *d, + QtPrivate::QPropertyBindingFunction binding) +{ + struct Data : QPropertyData<T> + { + void *data() { return &this->val; } + } temp; + return bindingWrapper(type, d, binding, &temp, temp.data()); +} + +template<typename T> +QUntypedPropertyBinding setBinding(QUntypedPropertyData *d, const QUntypedPropertyBinding &binding) +{ + return setBinding(d, binding, &bindingWrapper<T>); +} + +template<typename T> +QUntypedPropertyBinding makeBinding(const QUntypedPropertyData *d, + const QPropertyBindingSourceLocation &location) +{ + return Qt::makePropertyBinding( + [d]() -> T { + T r; + getter(d, &r); + return r; + }, + location); +} + +template<class T> +inline constexpr QBindableInterface iface = { + &getter, + &setter, + &getBinding, + &setBinding<T>, + &makeBinding<T>, + &setObserver, + &QMetaType::fromType<T>, +}; +} } class QUntypedBindable @@ -594,6 +686,9 @@ protected: : data(d), iface(i) {} + Q_CORE_EXPORT explicit QUntypedBindable(QObject* obj, const QMetaProperty &property, const QtPrivate::QBindableInterface *i); + Q_CORE_EXPORT explicit QUntypedBindable(QObject* obj, const char* property, const QtPrivate::QBindableInterface *i); + public: constexpr QUntypedBindable() = default; template<typename Property> @@ -730,6 +825,12 @@ public: } } + explicit QBindable(QObject *obj, const QMetaProperty &property) + : QUntypedBindable(obj, property, &QtPrivate::PropertyAdaptorSlotObjectHelpers::iface<T>) {} + + explicit QBindable(QObject *obj, const char *property) + : QUntypedBindable(obj, property, &QtPrivate::PropertyAdaptorSlotObjectHelpers::iface<T>) {} + QPropertyBinding<T> makeBinding(const QPropertyBindingSourceLocation &location = QT_PROPERTY_DEFAULT_BINDING_LOCATION) const { return static_cast<QPropertyBinding<T> &&>(QUntypedBindable::makeBinding(location)); @@ -759,7 +860,7 @@ public: #endif return QPropertyBinding<T>(); } -#ifndef Q_CLANG_QDOC +#ifndef Q_QDOC template <typename Functor> QPropertyBinding<T> setBinding(Functor &&f, const QPropertyBindingSourceLocation &location = QT_PROPERTY_DEFAULT_BINDING_LOCATION, @@ -789,13 +890,16 @@ public: } }; +#if QT_DEPRECATED_SINCE(6, 6) template<typename T> -class QPropertyAlias : public QPropertyObserver +class QT_DEPRECATED_VERSION_X_6_6("Class was only meant for internal use, use a QProperty and add a binding to the target") +QPropertyAlias : public QPropertyObserver { Q_DISABLE_COPY_MOVE(QPropertyAlias) const QtPrivate::QBindableInterface *iface = nullptr; public: + QT_WARNING_PUSH QT_WARNING_DISABLE_DEPRECATED QPropertyAlias(QProperty<T> *property) : QPropertyObserver(property), iface(&QtPrivate::QBindableInterfaceForProperty<QProperty<T>>::iface) @@ -804,7 +908,7 @@ public: iface->setObserver(aliasedProperty(), this); } - template<typename Property, typename = typename Property::InheritsQUntypedPropertyData> + template <typename Property, QtPrivate::IsUntypedPropertyData<Property> = true> QPropertyAlias(Property *property) : QPropertyObserver(property), iface(&QtPrivate::QBindableInterfaceForProperty<Property>::iface) @@ -861,7 +965,7 @@ public: return QBindable<T>(aliasedProperty(), iface).setBinding(newBinding); } -#ifndef Q_CLANG_QDOC +#ifndef Q_QDOC template <typename Functor> QPropertyBinding<T> setBinding(Functor &&f, const QPropertyBindingSourceLocation &location = QT_PROPERTY_DEFAULT_BINDING_LOCATION, @@ -904,14 +1008,16 @@ public: template<typename Functor> QPropertyNotifier addNotifier(Functor f) { - return QBindable<T>(aliasedProperty(), iface).notify(f); + return QBindable<T>(aliasedProperty(), iface).addNotifier(f); } bool isValid() const { return aliasedProperty() != nullptr; } + QT_WARNING_POP }; +#endif // QT_DEPRECATED_SINCE(6, 6) template<typename Class, typename T, auto Offset, auto Signal = nullptr> class QObjectBindableProperty : public QPropertyData<T> @@ -951,7 +1057,7 @@ public: explicit QObjectBindableProperty(const QPropertyBinding<T> &binding) : QObjectBindableProperty() { setBinding(binding); } -#ifndef Q_CLANG_QDOC +#ifndef Q_QDOC template <typename Functor> explicit QObjectBindableProperty(Functor &&f, const QPropertyBindingSourceLocation &location = QT_PROPERTY_DEFAULT_BINDING_LOCATION, typename std::enable_if_t<std::is_invocable_r_v<T, Functor&>> * = nullptr) @@ -1044,7 +1150,7 @@ public: return true; } -#ifndef Q_CLANG_QDOC +#ifndef Q_QDOC template <typename Functor> QPropertyBinding<T> setBinding(Functor &&f, const QPropertyBindingSourceLocation &location = QT_PROPERTY_DEFAULT_BINDING_LOCATION, |