1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107
|
#ifndef JS_H
#define JS_H
#include <QtQml>
#include "jsnamfactory.h"
#include "jsresult.h"
class JSTimer : public QTimer {
Q_OBJECT
public:
static auto &getTimers() {
static QHash<uint, JSTimer *> timers;
return timers;
}
auto getId() const { return id; }
// This should be static but cannot bind static functions to QJSEngine
Q_INVOKABLE void clearTimeout(QJSValue id) {
// qDebug() << "Clearing timer" << id.toString();
auto timer = getTimers().take(id.toUInt());
if (timer) {
timer->stop();
timer->deleteLater();
} else
qDebug() << "Unknown id" << id.toUInt();
return;
}
// This should be static but cannot bind static functions to QJSEngine
Q_INVOKABLE QJSValue setTimeout(QJSValue callback, QJSValue delayTime, QJSValue args) {
qDebug() << callback.toString() << delayTime.toInt() << args.toString();
QJSValueList valueArgs;
if (args.isArray()) {
const int argsLength = args.property("length").toInt();
for (int i = 0; i < argsLength; ++i) {
auto arg = args.property(i);
qDebug() << "Adding arg" << arg.toString();
valueArgs << arg;
}
}
auto timer = new JSTimer();
timer->setInterval(delayTime.toInt());
connect(timer, &JSTimer::timeout, this, [callback, valueArgs]() mutable {
qDebug() << "Calling" << callback.toString();
if (!callback.isCallable()) qDebug() << callback.toString() << "is not callable";
auto value = callback.call(valueArgs);
if (value.isError()) {
qWarning() << "Error" << value.toString();
qDebug() << value.property("stack").toString().splitRef('\n');
}
});
timer->start();
return timer->getId();
}
Q_INVOKABLE JSTimer(QObject *parent = nullptr) : QTimer(parent) {
setTimerType(Qt::PreciseTimer);
setSingleShot(true);
// avoid 0
static uint counter = 1;
id = counter++;
connect(this, &JSTimer::destroyed, this, [id = id] { getTimers().remove(id); });
connect(this, &JSTimer::timeout, this, &QTimer::deleteLater);
getTimers().insert(id, this);
}
private:
uint id;
};
class JS : public QObject {
Q_OBJECT
public:
static JS &instance();
explicit JS(QObject *parent = nullptr);
JSNAMFactory &getNamFactory() { return namFactory; };
void initialize(const QUrl &url);
bool checkError(const QJSValue &value);
bool isInitialized();
QQmlEngine &getEngine() { return *engine; }
JSResult &callFunction(JSResult *result, const QString &name, const QJSValueList &args);
void resetNAM();
signals:
void initialized();
void initFailed(QString message);
private:
void initialize();
QQmlEngine *engine;
JSNAMFactory namFactory;
bool initializing = false;
bool ready = false;
QUrl url;
};
#endif // JS_H
|