aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/qml/common/qqmlsignalnames.cpp19
-rw-r--r--src/qml/common/qqmlsignalnames_p.h3
-rw-r--r--src/qml/qml/qqmlproperty.cpp30
-rw-r--r--tests/auto/qml/qqmlconnections/data/badSignalHandlerName.qml15
-rw-r--r--tests/auto/qml/qqmlconnections/tst_qqmlconnections.cpp21
5 files changed, 81 insertions, 7 deletions
diff --git a/src/qml/common/qqmlsignalnames.cpp b/src/qml/common/qqmlsignalnames.cpp
index e66c26d4e2..d2a23205a6 100644
--- a/src/qml/common/qqmlsignalnames.cpp
+++ b/src/qml/common/qqmlsignalnames.cpp
@@ -191,6 +191,25 @@ std::optional<QString> QQmlSignalNames::handlerNameToSignalName(QStringView hand
/*!
\internal
+Returns a signal name from \a handlerName string. Do not use it on changed handlers, see
+changedHandlerNameToSignalName for that! Accepts improperly capitalized handler names and
+incorrectly resolves signal names that start with '_' or '$'.
+*/
+std::optional<QString> QQmlSignalNames::badHandlerNameToSignalName(QStringView handler)
+{
+ if (handler.size() <= StrlenOn || !handler.startsWith(On))
+ return {};
+
+ QString signalName = handler.sliced(StrlenOn).toString();
+
+ // This is quite wrong. But we need it for backwards compatibility.
+ signalName.front() = signalName.front().toLower();
+
+ return signalName;
+}
+
+/*!
+\internal
Returns a signal name from \a changedHandlerName string. Makes sure not to lowercase the 'C' from
Changed.
*/
diff --git a/src/qml/common/qqmlsignalnames_p.h b/src/qml/common/qqmlsignalnames_p.h
index 753f2ca97a..9c3d192666 100644
--- a/src/qml/common/qqmlsignalnames_p.h
+++ b/src/qml/common/qqmlsignalnames_p.h
@@ -49,6 +49,9 @@ public:
static bool isHandlerName(QStringView signalName);
static QString addPrefixToPropertyName(QStringView prefix, QStringView propertyName);
+
+ // ### Qt7: remove this
+ static std::optional<QString> badHandlerNameToSignalName(QStringView handler);
};
QT_END_NAMESPACE
diff --git a/src/qml/qml/qqmlproperty.cpp b/src/qml/qml/qqmlproperty.cpp
index 7437eefa85..099512192f 100644
--- a/src/qml/qml/qqmlproperty.cpp
+++ b/src/qml/qml/qqmlproperty.cpp
@@ -381,11 +381,11 @@ void QQmlPropertyPrivate::initProperty(QObject *obj, const QString &name,
};
const QString terminalString = terminal.toString();
- if (auto signalName = QQmlSignalNames::handlerNameToSignalName(terminalString)) {
+ const auto findSignal = [&](const QString &signalName) {
if (ddata && ddata->propertyCache) {
// Try method
- const QQmlPropertyData *d =
- ddata->propertyCache->property(*signalName, currentObject, context);
+ const QQmlPropertyData *d
+ = ddata->propertyCache->property(signalName, currentObject, context);
// ### Qt7: This code treats methods as signals. It should use d->isSignal().
// That would be a change in behavior, though. Right now you can construct a
@@ -396,13 +396,29 @@ void QQmlPropertyPrivate::initProperty(QObject *obj, const QString &name,
if (d) {
object = currentObject;
core = *d;
- return;
+ return true;
}
- if (findChangeSignal(terminalString))
- return;
- } else if (findSignalInMetaObject(signalName->toUtf8())) {
+ return findChangeSignal(terminalString);
+ }
+
+ return findSignalInMetaObject(signalName.toUtf8());
+ };
+
+ auto signalName = QQmlSignalNames::handlerNameToSignalName(terminalString);
+ if (signalName) {
+ if (findSignal(*signalName))
return;
+ } else {
+ signalName = QQmlSignalNames::badHandlerNameToSignalName(terminalString);
+ if (signalName) {
+ qWarning()
+ << terminalString
+ << "is not a properly capitalized signal handler name."
+ << QQmlSignalNames::signalNameToHandlerName(*signalName)
+ << "would be correct.";
+ if (findSignal(*signalName))
+ return;
}
}
diff --git a/tests/auto/qml/qqmlconnections/data/badSignalHandlerName.qml b/tests/auto/qml/qqmlconnections/data/badSignalHandlerName.qml
new file mode 100644
index 0000000000..921787aa36
--- /dev/null
+++ b/tests/auto/qml/qqmlconnections/data/badSignalHandlerName.qml
@@ -0,0 +1,15 @@
+import QtQml
+
+QtObject {
+ id: root
+ signal _foo
+
+ property int handled: 0
+
+ property Connections c: Connections {
+ target: root
+ function on_Foo() { root.handled += 1 }
+ function on_foo() { root.handled += 2 }
+ }
+}
+
diff --git a/tests/auto/qml/qqmlconnections/tst_qqmlconnections.cpp b/tests/auto/qml/qqmlconnections/tst_qqmlconnections.cpp
index 61102798e7..adbaffb1ce 100644
--- a/tests/auto/qml/qqmlconnections/tst_qqmlconnections.cpp
+++ b/tests/auto/qml/qqmlconnections/tst_qqmlconnections.cpp
@@ -55,6 +55,7 @@ private slots:
void bindToPropertyWithUnderscoreChangeHandler();
void invalidTarget();
+ void badSignalHandlerName();
private:
QQmlEngine engine;
void prefixes();
@@ -461,6 +462,26 @@ void tst_qqmlconnections::invalidTarget()
QTRY_VERIFY(root->objectName().isEmpty());
}
+void tst_qqmlconnections::badSignalHandlerName()
+{
+ QQmlEngine engine;
+ QQmlComponent component(&engine, testFileUrl("badSignalHandlerName.qml"));
+ QVERIFY2(component.isReady(), qPrintable(component.errorString()));
+
+ QTest::ignoreMessage(
+ QtWarningMsg,
+ "\"on_foo\" is not a properly capitalized signal handler name. "
+ "\"on_Foo\" would be correct.");
+
+ QScopedPointer<QObject> root(component.create());
+ QVERIFY(!root.isNull());
+
+ QCOMPARE(root->property("handled").toInt(), 0);
+ QMetaObject::invokeMethod(root.data(), "_foo");
+ QCOMPARE(root->property("handled").toInt(), 3);
+}
+
+
QTEST_MAIN(tst_qqmlconnections)
#include "tst_qqmlconnections.moc"