summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorFabian Kosmale <fabian.kosmale@qt.io>2021-04-22 11:21:17 +0200
committerFabian Kosmale <fabian.kosmale@qt.io>2021-05-03 20:32:42 +0200
commit98b4f4bc4d87aa2f2c30adbcb8fd42abcc88d6fb (patch)
treec543eaf56c9a7cb8507c904c70f3a74753323e2c /src
parentd225c6afe765777bcd4f854e755f2e9c18febd7e (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.cpp33
-rw-r--r--src/corelib/kernel/qproperty.h48
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>