diff options
authorMitch Curtis <mitch.curtis@qt.io>2019-01-18 19:25:52 +0100
committerJani Heikkinen <jani.heikkinen@qt.io>2019-01-25 11:04:42 +0000
commitef34964c1fd6ae361da5a6b540f6448cf090e570 (patch)
parent1157ad6df74c746e96cadac1ee9a226811f4d084 (diff)
QQuickAbstractButton: fix clicked() not being emitted after long pressv5.
When a button is pressed long enough (QStyleHints::mousePressAndHoldInterval()) and there is a connection (e.g. signal handler) to the pressAndHold() signal, it is emitted. If nothing is connected to the signal, clicked() is emitted. Before this patch, QQuickAbstractButton used QObjectPrivate::isSignalConnected() to check whether or not anything was connected to pressAndHold(). The problem with this function is described by Olivier: "[...] there is an optimisation for the first 64 signals we store a bit in a 64bit integer to quickly see if a signal is connected. There is also the problem that it can return true even if the signal has been disconnected." This is also mentioned in a comment in the code: Returns \c true if the signal with index \a signal_index from object \a sender is connected. Signals with indices above a certain range are always considered connected (see connectedSignals in QObjectPrivate). When 5adce04 added inset signals to QQuickControl, it meant that signals in QQuickAbstractButton (which derives from QQuickControl) were pushed outside of that 64 signal range, resulting in the IS_SIGNAL_CONNECTED macro returning true. This patch fixes the issue by using QObject::isSignalConnected(), which does not use the 64 signal optimization. Fixes: QTBUG-72811 Change-Id: Ic6e54d6cab062e528522ef7e3cf27c1023d31347 Reviewed-by: Richard Moe Gustavsen <richard.gustavsen@qt.io> (cherry picked from commit bbc81363f082ab6a2736f8de83968a3941e367e2) Reviewed-by: Jani Heikkinen <jani.heikkinen@qt.io>
2 files changed, 19 insertions, 1 deletions
diff --git a/src/quicktemplates2/qquickabstractbutton.cpp b/src/quicktemplates2/qquickabstractbutton.cpp
index c0ce6978..9157b4f9 100644
--- a/src/quicktemplates2/qquickabstractbutton.cpp
+++ b/src/quicktemplates2/qquickabstractbutton.cpp
@@ -204,7 +204,9 @@ void QQuickAbstractButtonPrivate::handleUngrab()
bool QQuickAbstractButtonPrivate::isPressAndHoldConnected()
- IS_SIGNAL_CONNECTED(q, QQuickAbstractButton, pressAndHold, ());
+ const auto signal = &QQuickAbstractButton::pressAndHold;
+ const QMetaMethod method = QMetaMethod::fromSignal(signal);
+ return q->isSignalConnected(method);
void QQuickAbstractButtonPrivate::startPressAndHold()
diff --git a/tests/auto/controls/data/tst_abstractbutton.qml b/tests/auto/controls/data/tst_abstractbutton.qml
index 7bfa17c5..80155f69 100644
--- a/tests/auto/controls/data/tst_abstractbutton.qml
+++ b/tests/auto/controls/data/tst_abstractbutton.qml
@@ -865,4 +865,20 @@ TestCase {
compare(button3.checked, false)
compare(button3.action.checked, false)
+ function test_clickedAfterLongPress() {
+ var control = createTemporaryObject(button, testCase, { text: "Hello" })
+ verify(control)
+ var clickedSpy = signalSpy.createObject(control, { target: control, signalName: "clicked" })
+ verify(clickedSpy.valid)
+ mousePress(control)
+ // Ensure that clicked is emitted when no handler is defined for the pressAndHold() signal.
+ // Note that even though signal spies aren't considered in QObject::isSignalConnected(),
+ // we can't use one here to check for pressAndHold(), because otherwise clicked() won't be emitted.
+ wait(Qt.styleHints.mousePressAndHoldInterval + 100)
+ mouseRelease(control)
+ compare(clickedSpy.count, 1)
+ }