#include "rktwebview_qt.h" #include "webviewqt.h" #include "rktwebview.h" #include "webviewwindow.h" #include #include #include #include #include #define COMMAND_QUIT 1 #define COMMAND_CLOSE 2 #define COMMAND_CREATE 3 #define COMMAND_SET_URL 4 class Command { public: int cmd; QVector args; QVariant result; bool done; public: Command(int _cmd) { cmd = _cmd; done = false; } }; static QString jsonString(QJsonObject obj) { QJsonDocument doc(obj); QString j = QString::fromUtf8(doc.toJson(QJsonDocument::JsonFormat::Compact)); return j; } void Rktwebview_qt::processCommands() { while(!_command_queue.empty()) { Command *cmd = _command_queue.dequeue(); switch(cmd->cmd) { case COMMAND_QUIT: { _app->quit(); cmd->done = true; } break; case COMMAND_CREATE: { int parent = cmd->args[0].toInt(); void *f = cmd->args[1].value(); void (*js_event_cb)(const char *msg) = reinterpret_cast (f); QWidget *p; if (_views.contains(parent)) { p = _views[parent]; } else { p = nullptr; } WebviewWindow *w = new WebviewWindow(p); WebViewQt *view = new WebViewQt(nextHandle(), w); w->addView(view, this); int id = view->id(); _views[id] = w; _view_js_callbacks[id] = js_event_cb; w->show(); cmd->result = id; cmd->done = true; } break; case COMMAND_CLOSE: { int wv = cmd->args[0].toInt(); if (_views.contains(wv)) { WebviewWindow *w= _views[wv]; _views.remove(wv); w->close(); w->deleteLater(); cmd->result = true; } else { cmd->result = false; } cmd->done = true; } break; case COMMAND_SET_URL: { int wv = cmd->args[0].toInt(); QString url = cmd->args[1].toString(); if (_views.contains(wv)) { WebviewWindow *w = _views[wv]; WebViewQt *v = w->view(); QUrl u(url); v->setUrl(u); cmd->result = true; } else { cmd->result = false; } cmd->done = true; } break; default: { cmd->result = false; cmd->done = true; } break; } } } void Rktwebview_qt::processJsEventQueue() { } void Rktwebview_qt::removeView(int id) { _views.remove(id); } int Rktwebview_qt::nextHandle() { int h = ++_current_handle; return h; } int Rktwebview_qt::rktWebViewCreate(int parent, void (*js_evt_cb)(const char *)) { Command c(COMMAND_CREATE); c.args.push_back(parent); void *function = reinterpret_cast(js_evt_cb); QVariant f(QVariant::fromValue(function)); c.args.push_back(f); _command_queue.enqueue(&c); while(!c.done) { doEvents(); } int id = c.result.toInt(); return id; } void Rktwebview_qt::rktWebViewClose(int wv) { Command c(COMMAND_CLOSE); c.args.push_back(wv); _command_queue.enqueue(&c); while(!c.done) { doEvents(); } } result_t Rktwebview_qt::rktSetUrl(rktwebview_t wv, const char *url) { Command c(COMMAND_SET_URL); QString _url(url); c.args.push_back(wv); c.args.push_back(_url); _command_queue.enqueue(&c); while(!c.done) { doEvents(); } bool r = c.result.toBool(); return r ? result_t::oke : result_t::set_navigate_failed; } void Rktwebview_qt::pageLoaded(rktwebview_t w, bool ok) { // Inject event handling code for the javascript side runJs(w, "window.rkt_event_queue = [];\n" "window.rkt_send_event = function(obj) { window.rkt_event_queue.push(obj); };\n" "window.rkt_get_events = function() { " " let q = window.rkt_event_queue; " " window.rkt_event_queue = [];" " let json_q = JSON.stringify(q);" " return json_q;" "};"); // trigger page loaded. QJsonObject obj; obj["event"] = "page-loaded"; obj["oke"] = ok; triggerEvent(w, jsonString(obj)); } void Rktwebview_qt::triggerEvent(rktwebview_t wv, const QString &msg) { } void Rktwebview_qt::rktQuit() { QList keys = _views.keys(); int i; for(i = 0; i < keys.size(); i++) { int view_handle = keys[i]; rktWebViewClose(view_handle); } Command c(COMMAND_QUIT); _command_queue.enqueue(&c); while(!c.done) { doEvents(); } } void Rktwebview_qt::runJs(rktwebview_t wv, const char *js) { if (_views.contains(wv)) { QString _js(js); WebViewQt *view = _views[wv]->view(); view->runJs(_js); } } void Rktwebview_qt::doEvents() { _app->processEvents(); } Rktwebview_qt::Rktwebview_qt(Rktwebview_qt **handler) : QObject() { _argc = 1; _argv[0] = const_cast("Rktwebview_qt"); _current_handle = 0; _handler = handler; _app = new QApplication(_argc, _argv); connect(&_process_commands, &QTimer::timeout, this, &Rktwebview_qt::processCommands); _process_commands.start(10); *_handler = nullptr; }