QTimer: do not set active state when setting a negative interval
QObject::startTimer() returns 0 in case of failure, for example when someone tries to register a timer with a negative interval. However, QTimer internally uses -1 as an invalid timer id. This could lead to a situation when the timer was not really started, but QTimer::isActive() returned true. This patch fixes it in two ways: - check the return value of QObject::startTimer() and treat 0 as an error. - do not treat 0 as a valid timer id when calculating the active state. As a drive-by: move the `using namespace std::chrono_literals;` declaration to the top of tst_qtimer.cpp, so that we do not need to repeat it in each test case. Fixes: QTBUG-122087 Pick-to: 6.6 6.5 Change-Id: I0e21152b2173ebb5fb0dada1b99a903a321ca9c4 Reviewed-by: Ahmad Samir <a.samirh78@gmail.com> (cherry picked from commit 612b67cf13cedb832e082308b620f948377ddf21) Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org>
This commit is contained in:
parent
86cdd53a6d
commit
40e56294f1
@ -192,8 +192,11 @@ void QTimer::start()
|
|||||||
Q_D(QTimer);
|
Q_D(QTimer);
|
||||||
if (d->id != QTimerPrivate::INV_TIMER) // stop running timer
|
if (d->id != QTimerPrivate::INV_TIMER) // stop running timer
|
||||||
stop();
|
stop();
|
||||||
d->id = QObject::startTimer(std::chrono::milliseconds{d->inter}, d->type);
|
const int id = QObject::startTimer(std::chrono::milliseconds{d->inter}, d->type);
|
||||||
d->isActiveData.notify();
|
if (id > 0) {
|
||||||
|
d->id = id;
|
||||||
|
d->isActiveData.notify();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
@ -554,9 +557,16 @@ void QTimer::setInterval(int msec)
|
|||||||
d->inter.setValueBypassingBindings(msec);
|
d->inter.setValueBypassingBindings(msec);
|
||||||
if (d->id != QTimerPrivate::INV_TIMER) { // create new timer
|
if (d->id != QTimerPrivate::INV_TIMER) { // create new timer
|
||||||
QObject::killTimer(d->id); // restart timer
|
QObject::killTimer(d->id); // restart timer
|
||||||
d->id = QObject::startTimer(std::chrono::milliseconds{msec}, d->type);
|
const int id = QObject::startTimer(std::chrono::milliseconds{msec}, d->type);
|
||||||
// No need to call markDirty() for d->isActiveData here,
|
if (id > 0) {
|
||||||
// as timer state actually does not change
|
// Restarted successfully. No need to update the active state.
|
||||||
|
d->id = id;
|
||||||
|
} else {
|
||||||
|
// Failed to start the timer.
|
||||||
|
// Need to notify about active state change.
|
||||||
|
d->id = QTimerPrivate::INV_TIMER;
|
||||||
|
d->isActiveData.notify();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (intervalChanged)
|
if (intervalChanged)
|
||||||
d->inter.notify();
|
d->inter.notify();
|
||||||
|
@ -25,7 +25,7 @@ public:
|
|||||||
static constexpr int INV_TIMER = -1; // invalid timer id
|
static constexpr int INV_TIMER = -1; // invalid timer id
|
||||||
|
|
||||||
void setInterval(int msec) { q_func()->setInterval(msec); }
|
void setInterval(int msec) { q_func()->setInterval(msec); }
|
||||||
bool isActiveActualCalculation() const { return id >= 0; }
|
bool isActiveActualCalculation() const { return id > 0; }
|
||||||
|
|
||||||
int id = INV_TIMER;
|
int id = INV_TIMER;
|
||||||
Q_OBJECT_COMPAT_PROPERTY_WITH_ARGS(QTimerPrivate, int, inter, &QTimerPrivate::setInterval, 0)
|
Q_OBJECT_COMPAT_PROPERTY_WITH_ARGS(QTimerPrivate, int, inter, &QTimerPrivate::setInterval, 0)
|
||||||
|
@ -39,6 +39,8 @@ static bool glibDisabled = []() {
|
|||||||
}();
|
}();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
using namespace std::chrono_literals;
|
||||||
|
|
||||||
class tst_QTimer : public QObject
|
class tst_QTimer : public QObject
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
@ -94,6 +96,8 @@ private slots:
|
|||||||
void bindToTimer();
|
void bindToTimer();
|
||||||
void bindTimer();
|
void bindTimer();
|
||||||
void automatedBindingTests();
|
void automatedBindingTests();
|
||||||
|
|
||||||
|
void negativeInterval();
|
||||||
};
|
};
|
||||||
|
|
||||||
void tst_QTimer::zeroTimer()
|
void tst_QTimer::zeroTimer()
|
||||||
@ -166,7 +170,6 @@ void tst_QTimer::singleShotNormalizes_data()
|
|||||||
|
|
||||||
void tst_QTimer::singleShotNormalizes()
|
void tst_QTimer::singleShotNormalizes()
|
||||||
{
|
{
|
||||||
using namespace std::chrono_literals;
|
|
||||||
static constexpr auto TestTimeout = 250ms;
|
static constexpr auto TestTimeout = 250ms;
|
||||||
QFETCH(QByteArray, slotName);
|
QFETCH(QByteArray, slotName);
|
||||||
QEventLoop loop;
|
QEventLoop loop;
|
||||||
@ -1287,6 +1290,16 @@ void tst_QTimer::bindToTimer()
|
|||||||
|
|
||||||
timer.stop();
|
timer.stop();
|
||||||
QVERIFY(!active);
|
QVERIFY(!active);
|
||||||
|
|
||||||
|
// also test that using negative interval updates the binding correctly
|
||||||
|
timer.start(100);
|
||||||
|
QVERIFY(active);
|
||||||
|
timer.setInterval(-100);
|
||||||
|
QVERIFY(!active);
|
||||||
|
timer.start(100);
|
||||||
|
QVERIFY(active);
|
||||||
|
timer.start(-100);
|
||||||
|
QVERIFY(!active);
|
||||||
}
|
}
|
||||||
|
|
||||||
void tst_QTimer::bindTimer()
|
void tst_QTimer::bindTimer()
|
||||||
@ -1367,6 +1380,29 @@ void tst_QTimer::automatedBindingTests()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void tst_QTimer::negativeInterval()
|
||||||
|
{
|
||||||
|
QTimer timer;
|
||||||
|
|
||||||
|
// Starting with a negative interval does not change active state.
|
||||||
|
timer.start(-100ms);
|
||||||
|
QVERIFY(!timer.isActive());
|
||||||
|
|
||||||
|
// Updating the interval to a negative value stops the timer and changes
|
||||||
|
// the active state.
|
||||||
|
timer.start(100ms);
|
||||||
|
QVERIFY(timer.isActive());
|
||||||
|
timer.setInterval(-100);
|
||||||
|
QVERIFY(!timer.isActive());
|
||||||
|
|
||||||
|
// Starting with a negative interval when already started leads to stop
|
||||||
|
// and inactive state.
|
||||||
|
timer.start(100);
|
||||||
|
QVERIFY(timer.isActive());
|
||||||
|
timer.start(-100ms);
|
||||||
|
QVERIFY(!timer.isActive());
|
||||||
|
}
|
||||||
|
|
||||||
class OrderHelper : public QObject
|
class OrderHelper : public QObject
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
Loading…
x
Reference in New Issue
Block a user