diff options
20 files changed, 181 insertions, 0 deletions
diff --git a/src/corelib/kernel/qabstracteventdispatcher.cpp b/src/corelib/kernel/qabstracteventdispatcher.cpp index b98f3f4a30..9c025d6d6f 100644 --- a/src/corelib/kernel/qabstracteventdispatcher.cpp +++ b/src/corelib/kernel/qabstracteventdispatcher.cpp @@ -295,6 +295,16 @@ int QAbstractEventDispatcher::registerTimer(int interval, Qt::TimerType timerTyp \sa Qt::TimerType */ +/*! + \fn int QAbstractEventDispatcher::remainingTime(int timerId) + + Returns the remaining time in milliseconds with the given \a timerId. + If the timer is inactive, the returned value will be -1. If the timer is + overdue, the returned value will be 0. + + \sa Qt::TimerType +*/ + /*! \fn void QAbstractEventDispatcher::wakeUp() \threadsafe diff --git a/src/corelib/kernel/qabstracteventdispatcher.h b/src/corelib/kernel/qabstracteventdispatcher.h index 76f264c3c0..96498d207d 100644 --- a/src/corelib/kernel/qabstracteventdispatcher.h +++ b/src/corelib/kernel/qabstracteventdispatcher.h @@ -93,6 +93,8 @@ public: virtual bool unregisterTimers(QObject *object) = 0; virtual QList<TimerInfo> registeredTimers(QObject *object) const = 0; + virtual int remainingTime(int timerId) = 0; + virtual void wakeUp() = 0; virtual void interrupt() = 0; virtual void flush() = 0; diff --git a/src/corelib/kernel/qeventdispatcher_glib.cpp b/src/corelib/kernel/qeventdispatcher_glib.cpp index 3f272a2512..4429679e72 100644 --- a/src/corelib/kernel/qeventdispatcher_glib.cpp +++ b/src/corelib/kernel/qeventdispatcher_glib.cpp @@ -567,6 +567,19 @@ QList<QEventDispatcherGlib::TimerInfo> QEventDispatcherGlib::registeredTimers(QO return d->timerSource->timerList.registeredTimers(object); } +int QEventDispatcherGlib::remainingTime(int timerId) +{ +#ifndef QT_NO_DEBUG + if (timerId < 1) { + qWarning("QEventDispatcherGlib::remainingTimeTime: invalid argument"); + return -1; + } +#endif + + Q_D(QEventDispatcherGlib); + return d->timerSource->timerList.timerRemainingTime(timerId); +} + void QEventDispatcherGlib::interrupt() { wakeUp(); diff --git a/src/corelib/kernel/qeventdispatcher_glib_p.h b/src/corelib/kernel/qeventdispatcher_glib_p.h index 7bd40564b9..e230972092 100644 --- a/src/corelib/kernel/qeventdispatcher_glib_p.h +++ b/src/corelib/kernel/qeventdispatcher_glib_p.h @@ -85,6 +85,8 @@ public: bool unregisterTimers(QObject *object); QList<TimerInfo> registeredTimers(QObject *object) const; + int remainingTime(int timerId); + void wakeUp(); void interrupt(); void flush(); diff --git a/src/corelib/kernel/qeventdispatcher_unix.cpp b/src/corelib/kernel/qeventdispatcher_unix.cpp index d5805112e9..6eb96b832c 100644 --- a/src/corelib/kernel/qeventdispatcher_unix.cpp +++ b/src/corelib/kernel/qeventdispatcher_unix.cpp @@ -628,6 +628,19 @@ bool QEventDispatcherUNIX::hasPendingEvents() return qGlobalPostedEventsCount(); } +int QEventDispatcherUNIX::remainingTime(int timerId) +{ +#ifndef QT_NO_DEBUG + if (timerId < 1) { + qWarning("QEventDispatcherUNIX::remainingTime: invalid argument"); + return -1; + } +#endif + + Q_D(QEventDispatcherUNIX); + return d->timerList.timerRemainingTime(timerId); +} + void QEventDispatcherUNIX::wakeUp() { Q_D(QEventDispatcherUNIX); diff --git a/src/corelib/kernel/qeventdispatcher_unix_p.h b/src/corelib/kernel/qeventdispatcher_unix_p.h index e618853e09..05ecf52dbf 100644 --- a/src/corelib/kernel/qeventdispatcher_unix_p.h +++ b/src/corelib/kernel/qeventdispatcher_unix_p.h @@ -116,6 +116,8 @@ public: bool unregisterTimers(QObject *object); QList<TimerInfo> registeredTimers(QObject *object) const; + int remainingTime(int timerId); + void wakeUp(); void interrupt(); void flush(); diff --git a/src/corelib/kernel/qeventdispatcher_win.cpp b/src/corelib/kernel/qeventdispatcher_win.cpp index 768fde682b..26fd6316ae 100644 --- a/src/corelib/kernel/qeventdispatcher_win.cpp +++ b/src/corelib/kernel/qeventdispatcher_win.cpp @@ -50,6 +50,7 @@ #include "qvarlengtharray.h" #include "qwineventnotifier.h" +#include "qelapsedtimer.h" #include "qcoreapplication_p.h" #include <private/qthread_p.h> #include <private/qmutexpool_p.h> @@ -532,6 +533,8 @@ void QEventDispatcherWin32Private::registerTimer(WinTimerInfo *t) ok = SetTimer(internalHwnd, t->timerId, interval, 0); } + t->timeout = qt_msectime() + interval; + if (ok == 0) qErrnoWarning("QEventDispatcherWin32::registerTimer: Failed to create a timer"); } @@ -998,6 +1001,42 @@ void QEventDispatcherWin32::activateEventNotifiers() } } +int QEventDispatcherWin32::remainingTime(int timerId) +{ +#ifndef QT_NO_DEBUG + if (timerId < 1) { + qWarning("QEventDispatcherWin32::remainingTime: invalid argument"); + return -1; + } +#endif + + Q_D(QEventDispatcherWin32); + + if (d->timerVec.isEmpty()) + return -1; + + quint64 currentTime = qt_msectime(); + + register WinTimerInfo *t; + for (int i=0; i<d->timerVec.size(); i++) { + t = d->timerVec.at(i); + if (t && t->timerId == timerId) { // timer found + if (currentTime < t->timeout) { + // time to wait + return t->timeout - currentTime; + } else { + return 0; + } + } + } + +#ifndef QT_NO_DEBUG + qWarning("QEventDispatcherWin32::remainingTime: timer id %s not found", timerId); +#endif + + return -1; +} + void QEventDispatcherWin32::wakeUp() { Q_D(QEventDispatcherWin32); diff --git a/src/corelib/kernel/qeventdispatcher_win_p.h b/src/corelib/kernel/qeventdispatcher_win_p.h index 565f1ef4b3..e78236fd40 100644 --- a/src/corelib/kernel/qeventdispatcher_win_p.h +++ b/src/corelib/kernel/qeventdispatcher_win_p.h @@ -66,6 +66,7 @@ class QEventDispatcherWin32Private; // forward declaration LRESULT QT_WIN_CALLBACK qt_internal_proc(HWND hwnd, UINT message, WPARAM wp, LPARAM lp); +int qt_msectime(); class Q_CORE_EXPORT QEventDispatcherWin32 : public QAbstractEventDispatcher { @@ -94,6 +95,8 @@ public: void unregisterEventNotifier(QWinEventNotifier *notifier); void activateEventNotifiers(); + int remainingTime(int timerId); + void wakeUp(); void interrupt(); void flush(); @@ -123,6 +126,7 @@ struct WinTimerInfo { // internal timer info int timerId; int interval; Qt::TimerType timerType; + quint64 timeout; // - when to actually fire QObject *obj; // - object to receive events bool inTimerEvent; int fastTimerId; diff --git a/src/corelib/kernel/qtimer.cpp b/src/corelib/kernel/qtimer.cpp index f434df177c..2131188439 100644 --- a/src/corelib/kernel/qtimer.cpp +++ b/src/corelib/kernel/qtimer.cpp @@ -387,6 +387,25 @@ void QTimer::setInterval(int msec) } /*! + \property QTimer::remainingTime + \brief the remaining time in milliseconds + + Returns the timer's remaining value in milliseconds left until the timeout. + If the timer is inactive, the returned value will be -1. If the timer is + overdue, the returned value will be 0. + + \sa interval +*/ +int QTimer::remainingTime() const +{ + if (id != INV_TIMER) { + return QAbstractEventDispatcher::instance()->remainingTime(id); + } + + return -1; +} + +/*! \property QTimer::timerType \brief controls the accuracy of the timer diff --git a/src/corelib/kernel/qtimer.h b/src/corelib/kernel/qtimer.h index eff2a7bfe1..fa68676f27 100644 --- a/src/corelib/kernel/qtimer.h +++ b/src/corelib/kernel/qtimer.h @@ -57,6 +57,7 @@ class Q_CORE_EXPORT QTimer : public QObject Q_OBJECT Q_PROPERTY(bool singleShot READ isSingleShot WRITE setSingleShot) Q_PROPERTY(int interval READ interval WRITE setInterval) + Q_PROPERTY(int remainingTime READ remainingTime) Q_PROPERTY(Qt::TimerType timerType READ timerType WRITE setTimerType) Q_PROPERTY(bool active READ isActive) public: @@ -69,6 +70,8 @@ public: void setInterval(int msec); int interval() const { return inter; } + int remainingTime() const; + void setTimerType(Qt::TimerType atype) { this->type = atype; } Qt::TimerType timerType() const { return Qt::TimerType(type); } diff --git a/src/corelib/kernel/qtimerinfo_unix.cpp b/src/corelib/kernel/qtimerinfo_unix.cpp index 32e24edcf3..709338afda 100644 --- a/src/corelib/kernel/qtimerinfo_unix.cpp +++ b/src/corelib/kernel/qtimerinfo_unix.cpp @@ -412,6 +412,37 @@ bool QTimerInfoList::timerWait(timeval &tm) return true; } +/* + Returns the timer's remaining time in milliseconds with the given timerId, or + null if there is nothing left. If the timer id is not found in the list, the + returned value will be -1. If the timer is overdue, the returned value will be 0. +*/ +int QTimerInfoList::timerRemainingTime(int timerId) +{ + timeval currentTime = updateCurrentTime(); + repairTimersIfNeeded(); + timeval tm = {0, 0}; + + for (int i = 0; i < count(); ++i) { + register QTimerInfo *t = at(i); + if (t->id == timerId) { + if (currentTime < t->timeout) { + // time to wait + tm = roundToMillisecond(t->timeout - currentTime); + return tm.tv_sec*1000 + tm.tv_usec/1000; + } else { + return 0; + } + } + } + +#ifndef QT_NO_DEBUG + qWarning("QTimerInfoList::timerRemainingTime: timer id %i not found", timerId); +#endif + + return -1; +} + void QTimerInfoList::registerTimer(int timerId, int interval, Qt::TimerType timerType, QObject *object) { QTimerInfo *t = new QTimerInfo; diff --git a/src/corelib/kernel/qtimerinfo_unix_p.h b/src/corelib/kernel/qtimerinfo_unix_p.h index 4bf6b91ea6..cd431f9a4f 100644 --- a/src/corelib/kernel/qtimerinfo_unix_p.h +++ b/src/corelib/kernel/qtimerinfo_unix_p.h @@ -104,6 +104,8 @@ public: bool timerWait(timeval &); void timerInsert(QTimerInfo *); + int timerRemainingTime(int timerId); + void registerTimer(int timerId, int interval, Qt::TimerType timerType, QObject *object); bool unregisterTimer(int timerId); bool unregisterTimers(QObject *object); diff --git a/src/corelib/tools/qelapsedtimer_win.cpp b/src/corelib/tools/qelapsedtimer_win.cpp index 8171a27ea3..51e0690e72 100644 --- a/src/corelib/tools/qelapsedtimer_win.cpp +++ b/src/corelib/tools/qelapsedtimer_win.cpp @@ -120,6 +120,11 @@ static quint64 getTickCount() return val | (quint64(highdword) << 32); } +int qt_msectime() +{ + return ticksToNanoseconds(getTickCount()) / 1000000; +} + QElapsedTimer::ClockType QElapsedTimer::clockType() { resolveLibs(); diff --git a/src/plugins/platforms/cocoa/qcocoaeventdispatcher.h b/src/plugins/platforms/cocoa/qcocoaeventdispatcher.h index a4a1286fab..7fa1f0971f 100644 --- a/src/plugins/platforms/cocoa/qcocoaeventdispatcher.h +++ b/src/plugins/platforms/cocoa/qcocoaeventdispatcher.h @@ -128,6 +128,8 @@ public: bool unregisterTimers(QObject *object); QList<TimerInfo> registeredTimers(QObject *object) const; + int remainingTime(int timerId); + void wakeUp(); void interrupt(); void flush(); diff --git a/src/plugins/platforms/cocoa/qcocoaeventdispatcher.mm b/src/plugins/platforms/cocoa/qcocoaeventdispatcher.mm index 77cccac0b4..02722ce5bf 100644 --- a/src/plugins/platforms/cocoa/qcocoaeventdispatcher.mm +++ b/src/plugins/platforms/cocoa/qcocoaeventdispatcher.mm @@ -680,6 +680,19 @@ bool QCocoaEventDispatcher::processEvents(QEventLoop::ProcessEventsFlags flags) return retVal; } +int QCocoaEventDispatcher::remainingTime(int timerId) +{ +#ifndef QT_NO_DEBUG + if (timerId < 1) { + qWarning("QCocoaEventDispatcher::remainingTime: invalid argument"); + return -1; + } +#endif + + Q_D(QCocoaEventDispatcher); + return d->timerInfoList.timerRemainingTime(timerId); +} + void QCocoaEventDispatcher::wakeUp() { Q_D(QCocoaEventDispatcher); diff --git a/tests/auto/corelib/kernel/qcoreapplication/tst_qcoreapplication.cpp b/tests/auto/corelib/kernel/qcoreapplication/tst_qcoreapplication.cpp index 84d723ca61..29fa98b8bb 100644 --- a/tests/auto/corelib/kernel/qcoreapplication/tst_qcoreapplication.cpp +++ b/tests/auto/corelib/kernel/qcoreapplication/tst_qcoreapplication.cpp @@ -616,6 +616,7 @@ public: bool unregisterTimer(int ) { return false; } bool unregisterTimers(QObject *) { return false; } QList<TimerInfo> registeredTimers(QObject *) const { return QList<TimerInfo>(); } + int remainingTime(int) { return 0; } void wakeUp() {} void interrupt() {} void flush() {} diff --git a/tests/auto/corelib/kernel/qtimer/tst_qtimer.cpp b/tests/auto/corelib/kernel/qtimer/tst_qtimer.cpp index e8dade9387..e4ecfb6f2d 100644 --- a/tests/auto/corelib/kernel/qtimer/tst_qtimer.cpp +++ b/tests/auto/corelib/kernel/qtimer/tst_qtimer.cpp @@ -55,6 +55,7 @@ private slots: void zeroTimer(); void singleShotTimeout(); void timeout(); + void remainingTime(); void livelock_data(); void livelock(); void timerInfiniteRecursion_data(); @@ -143,6 +144,22 @@ void tst_QTimer::timeout() QVERIFY(helper.count > oldCount); } +void tst_QTimer::remainingTime() +{ + TimerHelper helper; + QTimer timer; + + connect(&timer, SIGNAL(timeout()), &helper, SLOT(timeout())); + timer.start(200); + + QCOMPARE(helper.count, 0); + + QTest::qWait(50); + QCOMPARE(helper.count, 0); + + int remainingTime = timer.remainingTime(); + QVERIFY2(qAbs(remainingTime - 150) < 50, qPrintable(QString::number(remainingTime))); +} void tst_QTimer::livelock_data() { diff --git a/tests/auto/corelib/thread/qthread/tst_qthread.cpp b/tests/auto/corelib/thread/qthread/tst_qthread.cpp index 8eccd17376..41cfc52354 100644 --- a/tests/auto/corelib/thread/qthread/tst_qthread.cpp +++ b/tests/auto/corelib/thread/qthread/tst_qthread.cpp @@ -1234,6 +1234,7 @@ public: bool unregisterTimer(int ) { return false; } bool unregisterTimers(QObject *) { return false; } QList<TimerInfo> registeredTimers(QObject *) const { return QList<TimerInfo>(); } + int remainingTime(int) { return 0; } void wakeUp() {} void interrupt() {} void flush() {} diff --git a/tests/auto/testlib/selftests/benchlibeventcounter/tst_benchlibeventcounter.cpp b/tests/auto/testlib/selftests/benchlibeventcounter/tst_benchlibeventcounter.cpp index bcd703b5d1..82de653586 100644 --- a/tests/auto/testlib/selftests/benchlibeventcounter/tst_benchlibeventcounter.cpp +++ b/tests/auto/testlib/selftests/benchlibeventcounter/tst_benchlibeventcounter.cpp @@ -62,6 +62,7 @@ public: void unregisterSocketNotifier(QSocketNotifier*) {} bool unregisterTimer(int) { return false; } bool unregisterTimers(QObject*) { return false; } + int remainingTime(int) { return 0; } void wakeUp() {} }; diff --git a/tests/auto/testlib/selftests/benchliboptions/tst_benchliboptions.cpp b/tests/auto/testlib/selftests/benchliboptions/tst_benchliboptions.cpp index cb1f7feead..d3be93b715 100644 --- a/tests/auto/testlib/selftests/benchliboptions/tst_benchliboptions.cpp +++ b/tests/auto/testlib/selftests/benchliboptions/tst_benchliboptions.cpp @@ -62,6 +62,7 @@ public: void unregisterSocketNotifier(QSocketNotifier*) {} bool unregisterTimer(int) { return false; } bool unregisterTimers(QObject*) { return false; } + int remainingTime(int) { return 0; } void wakeUp() {} }; |