diff options
author | Fabian Kosmale <fabian.kosmale@qt.io> | 2021-04-22 11:21:17 +0200 |
---|---|---|
committer | Fabian Kosmale <fabian.kosmale@qt.io> | 2021-05-03 20:32:42 +0200 |
commit | 98b4f4bc4d87aa2f2c30adbcb8fd42abcc88d6fb (patch) | |
tree | c543eaf56c9a7cb8507c904c70f3a74753323e2c /src | |
parent | d225c6afe765777bcd4f854e755f2e9c18febd7e (diff) |
Q(Untyped)Bindable: Print warnings when operations fail
Instead of silently failing, we now print an explanatory warning to aid
with debugging.
Task-number: QTBUG-89512
Change-Id: I36dd2ce452af12d0523c19286919095e366bd390
Reviewed-by: Edward Welbourne <edward.welbourne@qt.io>
Diffstat (limited to 'src')
-rw-r--r-- | src/corelib/kernel/qproperty.cpp | 33 | ||||
-rw-r--r-- | src/corelib/kernel/qproperty.h | 48 |
2 files changed, 75 insertions, 6 deletions
diff --git a/src/corelib/kernel/qproperty.cpp b/src/corelib/kernel/qproperty.cpp index 8f95b5fd5e..607048d94b 100644 --- a/src/corelib/kernel/qproperty.cpp +++ b/src/corelib/kernel/qproperty.cpp @@ -42,9 +42,12 @@ #include <qscopedvaluerollback.h> #include <QScopeGuard> +#include <QtCore/qloggingcategory.h> QT_BEGIN_NAMESPACE +Q_LOGGING_CATEGORY(lcQPropertyBinding, "qt.qproperty.binding"); + using namespace QtPrivate; void QPropertyBindingPrivatePtr::destroyAndFreeMemory() @@ -2131,6 +2134,36 @@ bool isPropertyInBindingWrapper(const QUntypedPropertyData *property) bindingStatus.currentCompatProperty->property == property; } +namespace BindableWarnings { + +void printUnsuitableBindableWarning(QAnyStringView prefix, BindableWarnings::Reason reason) +{ + switch (reason) { + case QtPrivate::BindableWarnings::NonBindableInterface: + qCWarning(lcQPropertyBinding).noquote() << prefix.toString() + << "The QBindable does not allow interaction with the binding."; + break; + case QtPrivate::BindableWarnings::ReadOnlyInterface: + qCWarning(lcQPropertyBinding).noquote() << prefix.toString() + << "The QBindable is read-only."; + break; + default: + case QtPrivate::BindableWarnings::InvalidInterface: + qCWarning(lcQPropertyBinding).noquote() << prefix.toString() + << "The QBindable is invalid."; + break; + } +} + +void printMetaTypeMismatch(QMetaType actual, QMetaType expected) +{ + qCWarning(lcQPropertyBinding) << "setBinding: Could not set binding as the property expects it to be of type" + << actual.name() + << "but got" << expected.name() << "instead."; +} + +} // namespace BindableWarnings end + } // namespace QtPrivate end QT_END_NAMESPACE diff --git a/src/corelib/kernel/qproperty.h b/src/corelib/kernel/qproperty.h index 9f15a2de7d..9be10c0a31 100644 --- a/src/corelib/kernel/qproperty.h +++ b/src/corelib/kernel/qproperty.h @@ -43,9 +43,7 @@ #include <QtCore/qglobal.h> #include <QtCore/qshareddata.h> #include <QtCore/qstring.h> -#include <functional> #include <type_traits> -#include <variant> #include <QtCore/qpropertyprivate.h> @@ -555,6 +553,15 @@ public: } +namespace QtPrivate { +// used in Q(Untyped)Bindable to print warnings about various binding errors +namespace BindableWarnings { +enum Reason { InvalidInterface, NonBindableInterface, ReadOnlyInterface }; +Q_CORE_EXPORT void printUnsuitableBindableWarning(QAnyStringView prefix, Reason reason); +Q_CORE_EXPORT void printMetaTypeMismatch(QMetaType actual, QMetaType expected); +} +} + class QUntypedBindable { protected: @@ -600,6 +607,11 @@ public: { if (iface) iface->setObserver(data, observer); +#ifndef QT_NO_DEBUG + else + QtPrivate::BindableWarnings::printUnsuitableBindableWarning("observe:", + QtPrivate::BindableWarnings::InvalidInterface); +#endif } template<typename Functor> @@ -619,16 +631,31 @@ public: QUntypedPropertyBinding binding() const { - if (!iface->getBinding) + if (!isBindable()) { +#ifndef QT_NO_DEBUG + QtPrivate::BindableWarnings::printUnsuitableBindableWarning("binding: ", + QtPrivate::BindableWarnings::NonBindableInterface); +#endif return QUntypedPropertyBinding(); + } return iface->getBinding(data); } bool setBinding(const QUntypedPropertyBinding &binding) { - if (!iface->setBinding) + if (isReadOnly()) { +#ifndef QT_NO_DEBUG + const auto errorType = iface ? QtPrivate::BindableWarnings::ReadOnlyInterface : + QtPrivate::BindableWarnings::InvalidInterface; + QtPrivate::BindableWarnings::printUnsuitableBindableWarning("setBinding: Could not set binding via bindable interface.", errorType); +#endif return false; - if (!binding.isNull() && binding.valueMetaType() != iface->metaType()) + } + if (!binding.isNull() && binding.valueMetaType() != iface->metaType()) { +#ifndef QT_NO_DEBUG + QtPrivate::BindableWarnings::printMetaTypeMismatch(iface->metaType(), binding.valueMetaType()); +#endif return false; + } iface->setBinding(data, binding); return true; } @@ -675,7 +702,16 @@ public: QPropertyBinding<T> setBinding(const QPropertyBinding<T> &binding) { Q_ASSERT(!iface || binding.isNull() || binding.valueMetaType() == iface->metaType()); - return (iface && iface->setBinding) ? static_cast<QPropertyBinding<T> &&>(iface->setBinding(data, binding)) : QPropertyBinding<T>(); + + if (iface && iface->setBinding) + return static_cast<QPropertyBinding<T> &&>(iface->setBinding(data, binding)); +#ifndef QT_NO_DEBUG + if (!iface) + QtPrivate::BindableWarnings::printUnsuitableBindableWarning("setBinding", QtPrivate::BindableWarnings::InvalidInterface); + else + QtPrivate::BindableWarnings::printUnsuitableBindableWarning("setBinding: Could not set binding via bindable interface.", QtPrivate::BindableWarnings::ReadOnlyInterface); +#endif + return QPropertyBinding<T>(); } #ifndef Q_CLANG_QDOC template <typename Functor> |