diff --git a/QuickPromise/Q.qml b/QuickPromise/Q.qml index e5cb287..fa8004e 100644 --- a/QuickPromise/Q.qml +++ b/QuickPromise/Q.qml @@ -8,7 +8,11 @@ QtObject { id : component function setTimeout(callback,interval) { - QPTimer.setTimeout(callback,interval); + return QPTimer.setTimeout(callback,interval); + } + + function clearTimeout(id) { + QPTimer.clearTimeout(id); } function promise() { diff --git a/qptimer.cpp b/qptimer.cpp index 3b63af5..42c9ffa 100644 --- a/qptimer.cpp +++ b/qptimer.cpp @@ -13,22 +13,43 @@ QPTimer::~QPTimer() } -void QPTimer::setTimeout(QJSValue func, int interval) +int QPTimer::setTimeout(QJSValue func, int interval) { // It can't use the Timer from Quick Component to implement the function. // Because setTimeout(0) could not be executed in next tick with < Qt 5.4 - QTimer *timer = new QTimer(this); + int id = startTimer(interval); - connect(timer,SIGNAL(timeout()), - this,SLOT(onTriggered()),Qt::QueuedConnection); + callbacks[id] = func; - QVariant v = QVariant::fromValue(func); + return id; +} + +void QPTimer::clearTimeout(int id) +{ + if (callbacks.contains(id)) { + killTimer(id); + callbacks.remove(id); + } +} + +void QPTimer::timerEvent(QTimerEvent *event) +{ + int id = event->timerId(); + + QJSValue func = callbacks[id]; + + callbacks.remove(id); + + QJSValue res = func.call(); + + if (res.isError()) { + qDebug() << "Q.setTimeout() - Uncaught exception at line" + << res.property("lineNumber").toInt() + << ":" << res.toString(); + } - timer->setProperty("__quick_promise_func___",v); - timer->setInterval(interval); - timer->setSingleShot(true); - timer->start(); + killTimer(id); } void QPTimer::onTriggered() diff --git a/qptimer.h b/qptimer.h index aef734b..1290f0b 100644 --- a/qptimer.h +++ b/qptimer.h @@ -3,6 +3,7 @@ #include #include +#include /// QuickPromise's timer utility @@ -14,12 +15,18 @@ class QPTimer : public QObject ~QPTimer(); /// Implement the setTimeout function by C++. - Q_INVOKABLE void setTimeout(QJSValue func,int interval); + Q_INVOKABLE int setTimeout(QJSValue func,int interval); -private: + Q_INVOKABLE void clearTimeout(int id); + +protected: + void timerEvent(QTimerEvent *event); +private: Q_INVOKABLE void onTriggered(); + QMap callbacks; + }; #endif // QPTIMER_H diff --git a/tests/unittests/TestSuite.qml b/tests/unittests/TestSuite.qml index 5a0b4bf..5c97c7c 100644 --- a/tests/unittests/TestSuite.qml +++ b/tests/unittests/TestSuite.qml @@ -8,6 +8,7 @@ TestCase { wait(0); wait(0); wait(0); + wait(0); } diff --git a/tests/unittests/main.cpp b/tests/unittests/main.cpp index cff8a52..735d329 100644 --- a/tests/unittests/main.cpp +++ b/tests/unittests/main.cpp @@ -5,6 +5,10 @@ #include #include +namespace AutoTestRegister { + QUICK_TEST_MAIN(QuickTests) +} + int main(int argc, char *argv[]) { QApplication a(argc, argv); diff --git a/tests/unittests/tst_timer.qml b/tests/unittests/tst_timer.qml index e368a91..9fc1013 100644 --- a/tests/unittests/tst_timer.qml +++ b/tests/unittests/tst_timer.qml @@ -13,4 +13,37 @@ TestSuite { wait(10); } + function test_setTimeout() { + var count1 = 0, count2 = 0; + var id1 = Q.setTimeout(function(){ + count1++ + }, 0); + var id2 = Q.setTimeout(function(){ + count2++; + }, 0); + compare(count1, 0); + compare(count2, 0); + compare(parseInt(id1), id1); + compare(parseInt(id2), id2); + compare(id1 !== id2, true); + wait(0); + compare(count1, 1); + compare(count2, 1); + wait(100); + compare(count1, 1); + compare(count2, 1); + } + + function test_clearTimeout() { + var count = 0; + var id = Q.setTimeout(function(){ + count++ + }, 0); + compare(count, 0); + compare(id !== 0, true); + Q.clearTimeout(id); + wait(100); + compare(count, 0); + } + } diff --git a/tests/unittests/unittests.pro b/tests/unittests/unittests.pro index ab3eb6e..69a8ffd 100644 --- a/tests/unittests/unittests.pro +++ b/tests/unittests/unittests.pro @@ -12,6 +12,8 @@ SOURCES += main.cpp include(../../quickpromise.pri) DEFINES += SRCDIR=\\\"$$PWD/\\\" BASEDIR=\\\"$$PWD/..\\\" +DEFINES += QUICK_TEST_SOURCE_DIR=\\\"$$PWD\\\" + DISTFILES += \ tst_promise_resolve_signal.qml \