]> git.sur5r.net Git - minitube/blobdiff - lib/js/js.h
New upstream version 3.8
[minitube] / lib / js / js.h
diff --git a/lib/js/js.h b/lib/js/js.h
new file mode 100644 (file)
index 0000000..8f0e33a
--- /dev/null
@@ -0,0 +1,105 @@
+#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 QJSValue clearTimeout(QJSValue id) {
+        auto timer = getTimers().take(id.toUInt());
+        if (timer) {
+            timer->stop();
+            timer->deleteLater();
+        } else
+            qDebug() << "Unknown id" << id.toUInt();
+        return QJSValue();
+    }
+    // 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::CoarseTimer);
+        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);
+
+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