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