diff --git a/src/resources/mathjax_preview.js b/src/resources/mathjax_preview.js index 22171c16..9404c1d0 100644 --- a/src/resources/mathjax_preview.js +++ b/src/resources/mathjax_preview.js @@ -13,17 +13,28 @@ if (typeof VPlantUMLServer == 'undefined') { VPlantUMLServer = 'http://www.plantuml.com/plantuml'; } -new QWebChannel(qt.webChannelTransport, - function(channel) { - content = channel.objects.content; +if (typeof VWebChannelPort == 'undefined') { + var VWebChannelPort = '20001'; +} - content.requestPreviewMathJax.connect(previewMathJax); - content.requestPreviewDiagram.connect(previewDiagram); +window.addEventListener('load', function() { + var baseUrl = 'ws://localhost:' + VWebChannelPort; + var socket = new WebSocket(baseUrl); + socket.onopen = function() { + console.log('WebSocket connected to ' + baseUrl); + new QWebChannel(socket, + function(channel) { + content = channel.objects.content; - channelInitialized = true; - }); + content.requestPreviewMathJax.connect(previewMathJax); + content.requestPreviewDiagram.connect(previewDiagram); -var timeStamps = new Map(); + channelInitialized = true; + }); + } +}); + +var timeStamps = new Object(); var htmlToElement = function(html) { var template = document.createElement('template'); @@ -37,7 +48,7 @@ var isEmptyMathJax = function(text) { }; var previewMathJax = function(identifier, id, timeStamp, text, isHtml) { - timeStamps.set(identifier, timeStamp); + timeStamps[identifier] = timeStamp; if (isEmptyMathJax(text)) { content.mathjaxResultReady(identifier, id, timeStamp, 'png', ''); @@ -87,7 +98,7 @@ var previewMathJax = function(identifier, id, timeStamp, text, isHtml) { }; var postProcessMathJax = function(identifier, id, timeStamp, container, isBlock) { - if (timeStamps.get(identifier) != timeStamp) { + if (timeStamps[identifier] != timeStamp) { contentDiv.removeChild(container); delete container; return; diff --git a/src/resources/mathjax_preview_template.html b/src/resources/mathjax_preview_template.html index 54024b78..3669193c 100644 --- a/src/resources/mathjax_preview_template.html +++ b/src/resources/mathjax_preview_template.html @@ -8,7 +8,7 @@ - + diff --git a/src/src.pro b/src/src.pro index 10430d53..ba2387b8 100644 --- a/src/src.pro +++ b/src/src.pro @@ -160,7 +160,8 @@ SOURCES += main.cpp\ vpreviewpage.cpp \ vwebview.cpp \ websocketclientwrapper.cpp \ - websockettransport.cpp + websockettransport.cpp \ + vmathjaxwebdocument.cpp HEADERS += vmainwindow.h \ vdirectorytree.h \ @@ -305,7 +306,8 @@ HEADERS += vmainwindow.h \ vpreviewpage.h \ vwebview.h \ websocketclientwrapper.h \ - websockettransport.h + websockettransport.h \ + vmathjaxwebdocument.h RESOURCES += \ vnote.qrc \ diff --git a/src/utils/vutils.cpp b/src/utils/vutils.cpp index 5af96956..9c11434a 100644 --- a/src/utils/vutils.cpp +++ b/src/utils/vutils.cpp @@ -978,7 +978,7 @@ with 2em, if there are Chinese characters in it, the font will be a mess. return templ; } -QString VUtils::generateMathJaxPreviewTemplate() +QString VUtils::generateMathJaxPreviewTemplate(quint16 p_port) { QString mj = g_config->getMathjaxJavascript(); QString templ = VNote::generateMathJaxPreviewTemplate(); @@ -1027,6 +1027,8 @@ QString VUtils::generateMathJaxPreviewTemplate() "\n" + "\n"; + extraFile += "\n"; + templ.replace(HtmlHolder::c_extraHolder, extraFile); return templ; diff --git a/src/utils/vutils.h b/src/utils/vutils.h index 62205f9a..fc163d05 100644 --- a/src/utils/vutils.h +++ b/src/utils/vutils.h @@ -206,7 +206,7 @@ public: static QString generateSimpleHtmlTemplate(const QString &p_body); // Generate template for MathJax preview. - static QString generateMathJaxPreviewTemplate(); + static QString generateMathJaxPreviewTemplate(quint16 p_port); // Get an available file name in @p_directory with base @p_baseFileName. // If there already exists a file named @p_baseFileName, try to add sequence diff --git a/src/vmathjaxpreviewhelper.cpp b/src/vmathjaxpreviewhelper.cpp index 06bf371f..ce3f3ea9 100644 --- a/src/vmathjaxpreviewhelper.cpp +++ b/src/vmathjaxpreviewhelper.cpp @@ -1,11 +1,14 @@ #include "vmathjaxpreviewhelper.h" -// #include -// #include +#include +#include +#include #include "utils/vutils.h" -// #include "vmathjaxwebdocument.h" +#include "vmathjaxwebdocument.h" #include "vconfigmanager.h" +#include "websocketclientwrapper.h" +#include "websockettransport.h" extern VConfigManager *g_config; @@ -14,7 +17,8 @@ VMathJaxPreviewHelper::VMathJaxPreviewHelper(QWidget *p_parentWidget, QObject *p m_parentWidget(p_parentWidget), m_initialized(false), m_nextID(0), - // m_webView(NULL), + m_webView(NULL), + m_channel(nullptr), m_webReady(false) { } @@ -30,9 +34,8 @@ void VMathJaxPreviewHelper::doInit() m_initialized = true; - /* - m_webView = new QWebEngineView(m_parentWidget); - connect(m_webView, &QWebEngineView::loadFinished, + m_webView = new QWebView(m_parentWidget); + connect(m_webView, &QWebView::loadFinished, this, [this]() { m_webReady = true; for (auto const & it : m_pendingFunc) { @@ -41,6 +44,7 @@ void VMathJaxPreviewHelper::doInit() m_pendingFunc.clear(); }); + m_webView->page()->settings()->setAttribute(QWebSettings::DeveloperExtrasEnabled, true); m_webView->hide(); m_webView->setFocusPolicy(Qt::NoFocus); @@ -71,16 +75,14 @@ void VMathJaxPreviewHelper::doInit() emit diagramPreviewResultReady(p_identifier, p_id, p_timeStamp, p_format, ba); }); - QWebChannel *channel = new QWebChannel(m_webView); - channel->registerObject(QStringLiteral("content"), m_webDoc); - m_webView->page()->setWebChannel(channel); + quint16 port = 20001; + bindToChannel(port, "content", m_webDoc); // setHtml() will change focus if it is not disabled. m_webView->setEnabled(false); QUrl baseUrl(QUrl::fromLocalFile(g_config->getDocumentPathOrHomePath() + QDir::separator())); - m_webView->setHtml(VUtils::generateMathJaxPreviewTemplate(), baseUrl); + m_webView->setHtml(VUtils::generateMathJaxPreviewTemplate(port), baseUrl); m_webView->setEnabled(true); - */ } void VMathJaxPreviewHelper::previewMathJax(int p_identifier, @@ -90,7 +92,18 @@ void VMathJaxPreviewHelper::previewMathJax(int p_identifier, { init(); - emit mathjaxPreviewResultReady(p_identifier, p_id, p_timeStamp, "png", ""); + if (!m_webReady) { + auto func = std::bind(&VMathJaxWebDocument::previewMathJax, + m_webDoc, + p_identifier, + p_id, + p_timeStamp, + p_text, + false); + m_pendingFunc.append(func); + } else { + m_webDoc->previewMathJax(p_identifier, p_id, p_timeStamp, p_text, false); + } } void VMathJaxPreviewHelper::previewMathJaxFromHtml(int p_identifier, @@ -100,7 +113,18 @@ void VMathJaxPreviewHelper::previewMathJaxFromHtml(int p_identifier, { init(); - emit mathjaxPreviewResultReady(p_identifier, p_id, p_timeStamp, "png", ""); + if (!m_webReady) { + auto func = std::bind(&VMathJaxWebDocument::previewMathJax, + m_webDoc, + p_identifier, + p_id, + p_timeStamp, + p_html, + true); + m_pendingFunc.append(func); + } else { + m_webDoc->previewMathJax(p_identifier, p_id, p_timeStamp, p_html, true); + } } void VMathJaxPreviewHelper::previewDiagram(int p_identifier, @@ -111,5 +135,36 @@ void VMathJaxPreviewHelper::previewDiagram(int p_identifier, { init(); - emit diagramPreviewResultReady(p_identifier, p_id, p_timeStamp, "png", ""); + if (!m_webReady) { + auto func = std::bind(&VMathJaxWebDocument::previewDiagram, + m_webDoc, + p_identifier, + p_id, + p_timeStamp, + p_lang, + p_text); + m_pendingFunc.append(func); + } else { + m_webDoc->previewDiagram(p_identifier, p_id, p_timeStamp, p_lang, p_text); + } +} + +void VMathJaxPreviewHelper::bindToChannel(quint16 p_port, const QString &p_name, QObject *p_object) +{ + Q_ASSERT(!m_channel); + auto server = new QWebSocketServer("Web View for Preview", + QWebSocketServer::NonSecureMode, + this); + quint16 port = p_port; + if (!server->listen(QHostAddress::LocalHost, port)) { + qWarning() << "fail to open web socket server on port" << port; + delete server; + return; + } + + auto clientWrapper = new WebSocketClientWrapper(server, this); + m_channel = new QWebChannel(this); + connect(clientWrapper, &WebSocketClientWrapper::clientConnected, + m_channel, &QWebChannel::connectTo); + m_channel->registerObject(p_name, p_object); } diff --git a/src/vmathjaxpreviewhelper.h b/src/vmathjaxpreviewhelper.h index 0a6d423e..9a61b728 100644 --- a/src/vmathjaxpreviewhelper.h +++ b/src/vmathjaxpreviewhelper.h @@ -7,8 +7,9 @@ #include "vconstants.h" -// class QWebEngineView; -// class VMathJaxWebDocument; +class QWebView; +class QWebChannel; +class VMathJaxWebDocument; class QWidget; typedef std::function PendingFunc; @@ -61,15 +62,19 @@ private: void doInit(); + void bindToChannel(quint16 p_port, const QString &p_name, QObject *p_object); + QWidget *m_parentWidget; int m_initialized; int m_nextID; - // QWebEngineView *m_webView; + QWebView *m_webView; - // VMathJaxWebDocument *m_webDoc; + QWebChannel *m_channel; + + VMathJaxWebDocument *m_webDoc; bool m_webReady; diff --git a/src/vmathjaxwebdocument.cpp b/src/vmathjaxwebdocument.cpp new file mode 100644 index 00000000..6f2d87ce --- /dev/null +++ b/src/vmathjaxwebdocument.cpp @@ -0,0 +1,54 @@ +#include "vmathjaxwebdocument.h" + +#include + +VMathJaxWebDocument::VMathJaxWebDocument(QObject *p_parent) + : QObject(p_parent) +{ +} + +void VMathJaxWebDocument::previewMathJax(int p_identifier, + int p_id, + TimeStamp p_timeStamp, + const QString &p_text, + bool p_isHtml) +{ + emit requestPreviewMathJax(p_identifier, p_id, p_timeStamp, p_text, p_isHtml); +} + +void VMathJaxWebDocument::mathjaxResultReady(int p_identifier, + int p_id, + unsigned long long p_timeStamp, + const QString &p_format, + const QString &p_data) +{ + emit mathjaxPreviewResultReady(p_identifier, p_id, p_timeStamp, p_format, p_data); +} + +void VMathJaxWebDocument::diagramResultReady(int p_identifier, + int p_id, + unsigned long long p_timeStamp, + const QString &p_format, + const QString &p_data) +{ + emit diagramPreviewResultReady(p_identifier, p_id, p_timeStamp, p_format, p_data); +} + +void VMathJaxWebDocument::previewDiagram(int p_identifier, + int p_id, + TimeStamp p_timeStamp, + const QString &p_lang, + const QString &p_text) +{ + emit requestPreviewDiagram(p_identifier, + p_id, + p_timeStamp, + p_lang, + p_text); +} + +void VMathJaxWebDocument::setLog(const QString &p_log) +{ + qDebug() << "JS:" << p_log; +} + diff --git a/src/vmathjaxwebdocument.h b/src/vmathjaxwebdocument.h new file mode 100644 index 00000000..7216dfdd --- /dev/null +++ b/src/vmathjaxwebdocument.h @@ -0,0 +1,69 @@ +#ifndef VMATHJAXWEBDOCUMENT_H +#define VMATHJAXWEBDOCUMENT_H + +#include + +#include "vconstants.h" + +class VMathJaxWebDocument : public QObject +{ + Q_OBJECT +public: + explicit VMathJaxWebDocument(QObject *p_parent = nullptr); + + void previewMathJax(int p_identifier, + int p_id, + TimeStamp p_timeStamp, + const QString &p_text, + bool p_isHtml); + + void previewDiagram(int p_identifier, + int p_id, + TimeStamp p_timeStamp, + const QString &p_lang, + const QString &p_text); + +public slots: + // Will be called in the HTML side + + void mathjaxResultReady(int p_identifier, + int p_id, + unsigned long long p_timeStamp, + const QString &p_format, + const QString &p_data); + + void diagramResultReady(int p_identifier, + int p_id, + unsigned long long p_timeStamp, + const QString &p_format, + const QString &p_data); + + void setLog(const QString &p_log); + +signals: + void requestPreviewMathJax(int p_identifier, + int p_id, + unsigned long long p_timeStamp, + const QString &p_text, + bool p_isHtml); + + void requestPreviewDiagram(int p_identifier, + int p_id, + unsigned long long p_timeStamp, + const QString &p_lang, + const QString &p_text); + + void mathjaxPreviewResultReady(int p_identifier, + int p_id, + TimeStamp p_timeStamp, + const QString &p_format, + const QString &p_data); + + void diagramPreviewResultReady(int p_identifier, + int p_id, + TimeStamp p_timeStamp, + const QString &p_format, + const QString &p_data); +}; + +#endif // VMATHJAXWEBDOCUMENT_H