QScrollBar: emit valueChanged once even if a slot takes too much time
Put also processing of control activation into initial timer check for possibly pending mouse release event. [ChangeLog][QtWidgets][QScrollBar] Fixed a bug where the valueChanged() signal was emitted twice if a connected slot took too much time. Task-number: QTBUG-42871 Change-Id: I7bad5279ef84463a033b55256d241d4445374081 Reviewed-by: Giuseppe D'Angelo <giuseppe.dangelo@kdab.com>
This commit is contained in:
parent
b6514cf307
commit
1c1cce67fa
@ -593,13 +593,14 @@ void QScrollBar::mousePressEvent(QMouseEvent *e)
|
||||
d->clickOffset = sliderLength / 2;
|
||||
}
|
||||
const int initialDelay = 500; // default threshold
|
||||
d->activateControl(d->pressedControl, initialDelay);
|
||||
QElapsedTimer time;
|
||||
time.start();
|
||||
d->activateControl(d->pressedControl, initialDelay);
|
||||
repaint(style()->subControlRect(QStyle::CC_ScrollBar, &opt, d->pressedControl, this));
|
||||
if (time.elapsed() >= initialDelay && d->repeatActionTimer.isActive()) {
|
||||
// It took more than 500ms (the initial timer delay) to process the repaint(), we
|
||||
// therefore need to restart the timer in case we have a pending mouse release event;
|
||||
// It took more than 500ms (the initial timer delay) to process
|
||||
// the control activation and repaint(), we therefore need
|
||||
// to restart the timer in case we have a pending mouse release event;
|
||||
// otherwise we'll get a timer event right before the release event,
|
||||
// causing the repeat action to be invoked twice on a single mouse click.
|
||||
// 50ms is the default repeat time (see activateControl/setRepeatAction).
|
||||
|
@ -58,6 +58,7 @@ private slots:
|
||||
#ifndef QT_NO_WHEELEVENT
|
||||
void QTBUG_27308();
|
||||
#endif
|
||||
void QTBUG_42871();
|
||||
};
|
||||
|
||||
class SingleStepTestScrollBar : public QScrollBar {
|
||||
@ -169,5 +170,44 @@ void tst_QScrollBar::QTBUG_27308()
|
||||
}
|
||||
#endif
|
||||
|
||||
class QTBUG_42871_Handler : public QObject {
|
||||
Q_OBJECT
|
||||
public:
|
||||
int updatesCount;
|
||||
QTBUG_42871_Handler() : QObject(), updatesCount(0) {}
|
||||
public slots:
|
||||
void valueUpdated(int) { ++updatesCount; QTest::qSleep(600); }
|
||||
};
|
||||
|
||||
void tst_QScrollBar::QTBUG_42871()
|
||||
{
|
||||
QTBUG_42871_Handler myHandler;
|
||||
QScrollBar scrollBarWidget(Qt::Vertical);
|
||||
bool connection = connect(&scrollBarWidget, SIGNAL(valueChanged(int)), &myHandler, SLOT(valueUpdated(int)));
|
||||
QVERIFY(connection);
|
||||
scrollBarWidget.resize(100, scrollBarWidget.height());
|
||||
centerOnScreen(&scrollBarWidget);
|
||||
scrollBarWidget.show();
|
||||
QTest::qWaitForWindowExposed(&scrollBarWidget);
|
||||
QSignalSpy spy(&scrollBarWidget, SIGNAL(actionTriggered(int)));
|
||||
QVERIFY(spy.isValid());
|
||||
QCOMPARE(myHandler.updatesCount, 0);
|
||||
QCOMPARE(spy.count(), 0);
|
||||
|
||||
// Simulate a mouse click on the "scroll down button".
|
||||
const QPoint pressPoint(scrollBarWidget.width() / 2, scrollBarWidget.height() - 10);
|
||||
const QPoint globalPressPoint = scrollBarWidget.mapToGlobal(pressPoint);
|
||||
QMouseEvent mousePressEvent(QEvent::MouseButtonPress, pressPoint, globalPressPoint,
|
||||
Qt::LeftButton, Qt::LeftButton, 0);
|
||||
QApplication::sendEvent(&scrollBarWidget, &mousePressEvent);
|
||||
QTest::qWait(1);
|
||||
QMouseEvent mouseReleaseEvent(QEvent::MouseButtonRelease, pressPoint, globalPressPoint,
|
||||
Qt::LeftButton, Qt::LeftButton, 0);
|
||||
QApplication::sendEvent(&scrollBarWidget, &mouseReleaseEvent);
|
||||
// Check that the action was triggered once.
|
||||
QCOMPARE(myHandler.updatesCount, 1);
|
||||
QCOMPARE(spy.count(), 1);
|
||||
}
|
||||
|
||||
QTEST_MAIN(tst_QScrollBar)
|
||||
#include "tst_qscrollbar.moc"
|
||||
|
Loading…
x
Reference in New Issue
Block a user