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