mirror of
https://gitee.com/vnotex/vnote.git
synced 2025-07-05 22:09:52 +08:00
support Mermaid and Flowchart.js preview
Mermaid preview is disabled for some issues.
This commit is contained in:
parent
8239abec2a
commit
10e2bba7f6
@ -3,7 +3,7 @@
|
|||||||
<meta charset="utf-8">
|
<meta charset="utf-8">
|
||||||
<head>
|
<head>
|
||||||
<style type="text/css">
|
<style type="text/css">
|
||||||
/* BACKGROUND_PLACE_HOLDER */
|
/* STYLE_GLOBAL_PLACE_HOLDER */
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
<style type="text/css">
|
<style type="text/css">
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
<meta charset="utf-8">
|
<meta charset="utf-8">
|
||||||
<head>
|
<head>
|
||||||
<style type="text/css">
|
<style type="text/css">
|
||||||
/* BACKGROUND_PLACE_HOLDER */
|
/* STYLE_GLOBAL_PLACE_HOLDER */
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
<style type="text/css">
|
<style type="text/css">
|
||||||
|
@ -1328,7 +1328,7 @@ var specialCodeBlock = function(lang) {
|
|||||||
|| (VEnableGraphviz && lang == 'dot');
|
|| (VEnableGraphviz && lang == 'dot');
|
||||||
};
|
};
|
||||||
|
|
||||||
var handlePlantUMLResult = function(id, format, result) {
|
var handlePlantUMLResult = function(id, timeStamp, format, result) {
|
||||||
var code = document.getElementsByClassName(plantUMLCodeClass + id)[0];
|
var code = document.getElementsByClassName(plantUMLCodeClass + id)[0];
|
||||||
if (code && result.length > 0) {
|
if (code && result.length > 0) {
|
||||||
var obj = null;
|
var obj = null;
|
||||||
@ -1348,7 +1348,7 @@ var handlePlantUMLResult = function(id, format, result) {
|
|||||||
finishOneAsyncJob();
|
finishOneAsyncJob();
|
||||||
};
|
};
|
||||||
|
|
||||||
var handleGraphvizResult = function(id, format, result) {
|
var handleGraphvizResult = function(id, timeStamp, format, result) {
|
||||||
var code = document.getElementsByClassName(graphvizCodeClass + id)[0];
|
var code = document.getElementsByClassName(graphvizCodeClass + id)[0];
|
||||||
if (code && result.length > 0) {
|
if (code && result.length > 0) {
|
||||||
var obj = null;
|
var obj = null;
|
||||||
|
@ -4,22 +4,25 @@ var contentDiv = document.getElementById('content-div');
|
|||||||
|
|
||||||
var content;
|
var content;
|
||||||
|
|
||||||
|
var VMermaidDivClass = 'mermaid-diagram';
|
||||||
|
var VFlowchartDivClass = 'flowchart-diagram';
|
||||||
|
|
||||||
new QWebChannel(qt.webChannelTransport,
|
new QWebChannel(qt.webChannelTransport,
|
||||||
function(channel) {
|
function(channel) {
|
||||||
content = channel.objects.content;
|
content = channel.objects.content;
|
||||||
|
|
||||||
content.requestPreviewMathJax.connect(previewMathJax);
|
content.requestPreviewMathJax.connect(previewMathJax);
|
||||||
|
content.requestPreviewDiagram.connect(previewDiagram);
|
||||||
|
|
||||||
channelInitialized = true;
|
channelInitialized = true;
|
||||||
});
|
});
|
||||||
|
|
||||||
var previewMathJax = function(identifier, id, text) {
|
var previewMathJax = function(identifier, id, timeStamp, text) {
|
||||||
if (text.length == 0) {
|
if (text.length == 0) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
var p = document.createElement('p');
|
var p = document.createElement('p');
|
||||||
p.id = identifier + '_' + id;
|
|
||||||
p.textContent = text;
|
p.textContent = text;
|
||||||
contentDiv.appendChild(p);
|
contentDiv.appendChild(p);
|
||||||
|
|
||||||
@ -27,7 +30,7 @@ var previewMathJax = function(identifier, id, text) {
|
|||||||
MathJax.Hub.Queue(["Typeset",
|
MathJax.Hub.Queue(["Typeset",
|
||||||
MathJax.Hub,
|
MathJax.Hub,
|
||||||
p,
|
p,
|
||||||
postProcessMathJax.bind(undefined, identifier, id, p)]);
|
postProcessMathJax.bind(undefined, identifier, id, timeStamp, p)]);
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.log("err: " + err);
|
console.log("err: " + err);
|
||||||
contentDiv.removeChild(p);
|
contentDiv.removeChild(p);
|
||||||
@ -35,14 +38,119 @@ var previewMathJax = function(identifier, id, text) {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
var postProcessMathJax = function(identifier, id, container) {
|
var postProcessMathJax = function(identifier, id, timeStamp, container) {
|
||||||
domtoimage.toPng(container, { height: container.clientHeight * 1.5 }).then(function (dataUrl) {
|
domtoimage.toPng(container, { height: container.clientHeight * 1.5 }).then(function (dataUrl) {
|
||||||
var png = dataUrl.substring(dataUrl.indexOf(',') + 1);
|
var png = dataUrl.substring(dataUrl.indexOf(',') + 1);
|
||||||
content.mathjaxResultReady(identifier, id, 'png', png);
|
content.mathjaxResultReady(identifier, id, timeStamp, 'png', png);
|
||||||
|
|
||||||
contentDiv.removeChild(container);
|
contentDiv.removeChild(container);
|
||||||
delete container;
|
delete container;
|
||||||
}).catch(function (err) {
|
}).catch(function (err) {
|
||||||
console.log("err: " + err);
|
console.log("err: " + err);
|
||||||
|
contentDiv.removeChild(container);
|
||||||
|
delete container;
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
var mermaidParserErr = false;
|
||||||
|
var mermaidIdx = 0;
|
||||||
|
|
||||||
|
var flowchartIdx = 0;
|
||||||
|
|
||||||
|
if (typeof mermaidAPI != "undefined") {
|
||||||
|
mermaidAPI.parseError = function(err, hash) {
|
||||||
|
mermaidParserErr = true;
|
||||||
|
|
||||||
|
// Clean the container element, or mermaidAPI won't render the graph with
|
||||||
|
// the same id.
|
||||||
|
var errGraph = document.getElementById('mermaid-diagram-' + mermaidIdx);
|
||||||
|
if (errGraph) {
|
||||||
|
var parentNode = errGraph.parentElement;
|
||||||
|
parentNode.outerHTML = '';
|
||||||
|
delete parentNode;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
var previewDiagram = function(identifier, id, timeStamp, lang, text) {
|
||||||
|
if (text.length == 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var div = null;
|
||||||
|
if (lang == 'flow' || lang == 'flowchart') {
|
||||||
|
flowchartIdx++;
|
||||||
|
try {
|
||||||
|
var graph = flowchart.parse(text);
|
||||||
|
} catch (err) {
|
||||||
|
console.log("err: " + err);
|
||||||
|
content.diagramResultReady(identifier, id, timeStamp, 'png', '');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (typeof graph == "undefined") {
|
||||||
|
content.diagramResultReady(identifier, id, timeStamp, 'png', '');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
div = document.createElement('div');
|
||||||
|
div.id = 'flowchart-diagram-' + flowchartIdx;
|
||||||
|
div.classList.add(VFlowchartDivClass);
|
||||||
|
|
||||||
|
contentDiv.appendChild(div);
|
||||||
|
|
||||||
|
// Draw on it after adding it to page.
|
||||||
|
try {
|
||||||
|
graph.drawSVG(div.id);
|
||||||
|
} catch (err) {
|
||||||
|
console.log("err: " + err);
|
||||||
|
contentDiv.removeChild(div);
|
||||||
|
delete div;
|
||||||
|
content.diagramResultReady(identifier, id, timeStamp, 'png', '');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
} else if (lang == 'mermaid') {
|
||||||
|
mermaidParserErr = false;
|
||||||
|
mermaidIdx++;
|
||||||
|
try {
|
||||||
|
// Do not increment mermaidIdx here.
|
||||||
|
var graph = mermaidAPI.render('mermaid-diagram-' + mermaidIdx,
|
||||||
|
text,
|
||||||
|
function(){});
|
||||||
|
} catch (err) {
|
||||||
|
console.log("err: " + err);
|
||||||
|
content.diagramResultReady(identifier, id, timeStamp, 'png', '');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mermaidParserErr || typeof graph == "undefined") {
|
||||||
|
content.diagramResultReady(identifier, id, timeStamp, 'png', '');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
div = document.createElement('div');
|
||||||
|
div.classList.add(VMermaidDivClass);
|
||||||
|
div.innerHTML = graph;
|
||||||
|
contentDiv.appendChild(div);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!div) {
|
||||||
|
content.diagramResultReady(identifier, id, timeStamp, 'png', '');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// For Flowchart.js, we need to add addtitional height. Since Mermaid is not
|
||||||
|
// supported now, we just add it simply here.
|
||||||
|
domtoimage.toPng(div, { height: div.clientHeight + 30 }).then(function (dataUrl) {
|
||||||
|
var png = dataUrl.substring(dataUrl.indexOf(',') + 1);
|
||||||
|
content.diagramResultReady(identifier, id, timeStamp, 'png', png);
|
||||||
|
|
||||||
|
contentDiv.removeChild(div);
|
||||||
|
delete div;
|
||||||
|
}).catch(function (err) {
|
||||||
|
console.log("err: " + err);
|
||||||
|
contentDiv.removeChild(div);
|
||||||
|
content.diagramResultReady(identifier, id, timeStamp, 'png', '');
|
||||||
|
delete div;
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
@ -2,6 +2,10 @@
|
|||||||
<html>
|
<html>
|
||||||
<meta charset="utf-8">
|
<meta charset="utf-8">
|
||||||
<head>
|
<head>
|
||||||
|
<style type="text/css">
|
||||||
|
/* STYLE_GLOBAL_PLACE_HOLDER */
|
||||||
|
</style>
|
||||||
|
|
||||||
<link rel="stylesheet" type="text/css" href="CSS_PLACE_HOLDER">
|
<link rel="stylesheet" type="text/css" href="CSS_PLACE_HOLDER">
|
||||||
<script src="qrc:/resources/qwebchannel.js"></script>
|
<script src="qrc:/resources/qwebchannel.js"></script>
|
||||||
<!-- EXTRA_PLACE_HOLDER -->
|
<!-- EXTRA_PLACE_HOLDER -->
|
||||||
|
@ -171,6 +171,7 @@ div.mermaid-diagram {
|
|||||||
}
|
}
|
||||||
|
|
||||||
div.flowchart-diagram {
|
div.flowchart-diagram {
|
||||||
|
padding: 0px 5px 0px 5px;
|
||||||
margin: 16px 0px 16px 0px;
|
margin: 16px 0px 16px 0px;
|
||||||
width: fit-content;
|
width: fit-content;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
@ -179,6 +180,7 @@ div.flowchart-diagram {
|
|||||||
}
|
}
|
||||||
|
|
||||||
div.plantuml-diagram {
|
div.plantuml-diagram {
|
||||||
|
padding: 5px 5px 0px 5px;
|
||||||
margin: 16px 0px 16px 0px;
|
margin: 16px 0px 16px 0px;
|
||||||
width: fit-content;
|
width: fit-content;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
|
@ -174,12 +174,14 @@ div.mermaid-diagram {
|
|||||||
}
|
}
|
||||||
|
|
||||||
div.flowchart-diagram {
|
div.flowchart-diagram {
|
||||||
|
padding: 0px 5px 0px 5px;
|
||||||
margin: 16px 0px 16px 0px;
|
margin: 16px 0px 16px 0px;
|
||||||
width: fit-content;
|
width: fit-content;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
}
|
}
|
||||||
|
|
||||||
div.plantuml-diagram {
|
div.plantuml-diagram {
|
||||||
|
padding: 5px 5px 0px 5px;
|
||||||
margin: 16px 0px 16px 0px;
|
margin: 16px 0px 16px 0px;
|
||||||
width: fit-content;
|
width: fit-content;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
|
@ -175,12 +175,14 @@ div.mermaid-diagram {
|
|||||||
}
|
}
|
||||||
|
|
||||||
div.flowchart-diagram {
|
div.flowchart-diagram {
|
||||||
|
padding: 0px 5px 0px 5px;
|
||||||
margin: 16px 0px 16px 0px;
|
margin: 16px 0px 16px 0px;
|
||||||
width: fit-content;
|
width: fit-content;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
}
|
}
|
||||||
|
|
||||||
div.plantuml-diagram {
|
div.plantuml-diagram {
|
||||||
|
padding: 5px 5px 0px 5px;
|
||||||
margin: 16px 0px 16px 0px;
|
margin: 16px 0px 16px 0px;
|
||||||
width: fit-content;
|
width: fit-content;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
|
@ -38,7 +38,7 @@ markdown_converter=2
|
|||||||
enable_mermaid=false
|
enable_mermaid=false
|
||||||
|
|
||||||
; Enable MathJax
|
; Enable MathJax
|
||||||
enable_mathjax=true
|
enable_mathjax=false
|
||||||
|
|
||||||
; Enable Flowchart.js
|
; Enable Flowchart.js
|
||||||
enable_flowchart=false
|
enable_flowchart=false
|
||||||
|
@ -818,19 +818,31 @@ QString VUtils::generateExportHtmlTemplate(const QString &p_renderBg, bool p_inc
|
|||||||
QString VUtils::generateMathJaxPreviewTemplate()
|
QString VUtils::generateMathJaxPreviewTemplate()
|
||||||
{
|
{
|
||||||
QString templ = VNote::generateMathJaxPreviewTemplate();
|
QString templ = VNote::generateMathJaxPreviewTemplate();
|
||||||
QString mj = g_config->getMathjaxJavascript();
|
templ.replace(HtmlHolder::c_JSHolder, g_config->getMathjaxJavascript());
|
||||||
// Chante MathJax to be rendered as SVG.
|
|
||||||
QRegExp reg("(Mathjax\\.js\\?config=)\\S+", Qt::CaseInsensitive);
|
|
||||||
// mj.replace(reg, QString("\\1%1").arg("TeX-MML-AM_SVG"));
|
|
||||||
|
|
||||||
templ.replace(HtmlHolder::c_JSHolder, mj);
|
|
||||||
|
|
||||||
QString extraFile;
|
QString extraFile;
|
||||||
|
|
||||||
|
QString mathjaxScale = QString::number((int)(100 * VUtils::calculateScaleFactor()));
|
||||||
|
|
||||||
|
/*
|
||||||
|
// Mermaid.
|
||||||
|
extraFile += "<link rel=\"stylesheet\" type=\"text/css\" href=\"" + g_config->getMermaidCssStyleUrl() + "\"/>\n" +
|
||||||
|
"<script src=\"qrc" + VNote::c_mermaidApiJsFile + "\"></script>\n";
|
||||||
|
*/
|
||||||
|
|
||||||
|
// Flowchart.
|
||||||
|
extraFile += "<script src=\"qrc" + VNote::c_raphaelJsFile + "\"></script>\n" +
|
||||||
|
"<script src=\"qrc" + VNote::c_flowchartJsFile + "\"></script>\n";
|
||||||
|
|
||||||
|
// MathJax.
|
||||||
extraFile += "<script type=\"text/x-mathjax-config\">"
|
extraFile += "<script type=\"text/x-mathjax-config\">"
|
||||||
"MathJax.Hub.Config({\n"
|
"MathJax.Hub.Config({\n"
|
||||||
" tex2jax: {inlineMath: [['$','$'], ['\\\\(','\\\\)']],\n"
|
" tex2jax: {inlineMath: [['$','$'], ['\\\\(','\\\\)']],\n"
|
||||||
"processEscapes: true,\n"
|
"processEscapes: true,\n"
|
||||||
"processClass: \"tex2jax_process|language-mathjax|lang-mathjax\"},\n"
|
"processClass: \"tex2jax_process|language-mathjax|lang-mathjax\"},\n"
|
||||||
|
" \"HTML-CSS\": {\n"
|
||||||
|
" scale: " + mathjaxScale + "\n"
|
||||||
|
" },\n"
|
||||||
" showProcessingMessages: false,\n"
|
" showProcessingMessages: false,\n"
|
||||||
" messageStyle: \"none\"});\n"
|
" messageStyle: \"none\"});\n"
|
||||||
"</script>\n";
|
"</script>\n";
|
||||||
|
@ -4,6 +4,8 @@
|
|||||||
#include <QString>
|
#include <QString>
|
||||||
#include <QStringList>
|
#include <QStringList>
|
||||||
|
|
||||||
|
typedef unsigned long long TimeStamp;
|
||||||
|
|
||||||
// Html: rich text file;
|
// Html: rich text file;
|
||||||
// Markdown: Markdown text file;
|
// Markdown: Markdown text file;
|
||||||
// List: Infinite list file like WorkFlowy;
|
// List: Infinite list file like WorkFlowy;
|
||||||
@ -38,7 +40,7 @@ namespace HtmlHolder
|
|||||||
static const QString c_JSHolder = "JS_PLACE_HOLDER";
|
static const QString c_JSHolder = "JS_PLACE_HOLDER";
|
||||||
static const QString c_cssHolder = "CSS_PLACE_HOLDER";
|
static const QString c_cssHolder = "CSS_PLACE_HOLDER";
|
||||||
static const QString c_codeBlockCssHolder = "HIGHLIGHTJS_CSS_PLACE_HOLDER";
|
static const QString c_codeBlockCssHolder = "HIGHLIGHTJS_CSS_PLACE_HOLDER";
|
||||||
static const QString c_globalStyleHolder = "/* BACKGROUND_PLACE_HOLDER */";
|
static const QString c_globalStyleHolder = "/* STYLE_GLOBAL_PLACE_HOLDER */";
|
||||||
static const QString c_extraHolder = "<!-- EXTRA_PLACE_HOLDER -->";
|
static const QString c_extraHolder = "<!-- EXTRA_PLACE_HOLDER -->";
|
||||||
static const QString c_bodyHolder = "<!-- BODY_PLACE_HOLDER -->";
|
static const QString c_bodyHolder = "<!-- BODY_PLACE_HOLDER -->";
|
||||||
static const QString c_headHolder = "<!-- HEAD_PLACE_HOLDER -->";
|
static const QString c_headHolder = "<!-- HEAD_PLACE_HOLDER -->";
|
||||||
|
@ -147,7 +147,7 @@ void VDocument::processPlantUML(int p_id, const QString &p_format, const QString
|
|||||||
this, &VDocument::plantUMLResultReady);
|
this, &VDocument::plantUMLResultReady);
|
||||||
}
|
}
|
||||||
|
|
||||||
m_plantUMLHelper->processAsync(p_id, p_format, p_text);
|
m_plantUMLHelper->processAsync(p_id, 0, p_format, p_text);
|
||||||
}
|
}
|
||||||
|
|
||||||
void VDocument::processGraphviz(int p_id, const QString &p_format, const QString &p_text)
|
void VDocument::processGraphviz(int p_id, const QString &p_format, const QString &p_text)
|
||||||
@ -158,7 +158,7 @@ void VDocument::processGraphviz(int p_id, const QString &p_format, const QString
|
|||||||
this, &VDocument::graphvizResultReady);
|
this, &VDocument::graphvizResultReady);
|
||||||
}
|
}
|
||||||
|
|
||||||
m_graphvizHelper->processAsync(p_id, p_format, p_text);
|
m_graphvizHelper->processAsync(p_id, 0, p_format, p_text);
|
||||||
}
|
}
|
||||||
|
|
||||||
void VDocument::setPreviewEnabled(bool p_enabled)
|
void VDocument::setPreviewEnabled(bool p_enabled)
|
||||||
|
@ -142,9 +142,15 @@ signals:
|
|||||||
|
|
||||||
void wordCountInfoUpdated();
|
void wordCountInfoUpdated();
|
||||||
|
|
||||||
void plantUMLResultReady(int p_id, const QString &p_format, const QString &p_result);
|
void plantUMLResultReady(int p_id,
|
||||||
|
unsigned long long p_timeStamp,
|
||||||
|
const QString &p_format,
|
||||||
|
const QString &p_result);
|
||||||
|
|
||||||
void graphvizResultReady(int p_id, const QString &p_format, const QString &p_result);
|
void graphvizResultReady(int p_id,
|
||||||
|
unsigned long long p_timeStamp,
|
||||||
|
const QString &p_format,
|
||||||
|
const QString &p_result);
|
||||||
|
|
||||||
void requestPreviewEnabled(bool p_enabled);
|
void requestPreviewEnabled(bool p_enabled);
|
||||||
|
|
||||||
|
@ -9,6 +9,7 @@ extern VConfigManager *g_config;
|
|||||||
|
|
||||||
#define TaskIdProperty "GraphvizTaskId"
|
#define TaskIdProperty "GraphvizTaskId"
|
||||||
#define TaskFormatProperty "GraphvizTaskFormat"
|
#define TaskFormatProperty "GraphvizTaskFormat"
|
||||||
|
#define TaskTimeStampProperty "GraphvizTaskTimeStamp"
|
||||||
|
|
||||||
VGraphvizHelper::VGraphvizHelper(QObject *p_parent)
|
VGraphvizHelper::VGraphvizHelper(QObject *p_parent)
|
||||||
: QObject(p_parent)
|
: QObject(p_parent)
|
||||||
@ -16,10 +17,11 @@ VGraphvizHelper::VGraphvizHelper(QObject *p_parent)
|
|||||||
prepareCommand(m_program, m_args);
|
prepareCommand(m_program, m_args);
|
||||||
}
|
}
|
||||||
|
|
||||||
void VGraphvizHelper::processAsync(int p_id, const QString &p_format, const QString &p_text)
|
void VGraphvizHelper::processAsync(int p_id, TimeStamp p_timeStamp, const QString &p_format, const QString &p_text)
|
||||||
{
|
{
|
||||||
QProcess *process = new QProcess(this);
|
QProcess *process = new QProcess(this);
|
||||||
process->setProperty(TaskIdProperty, p_id);
|
process->setProperty(TaskIdProperty, p_id);
|
||||||
|
process->setProperty(TaskTimeStampProperty, p_timeStamp);
|
||||||
process->setProperty(TaskFormatProperty, p_format);
|
process->setProperty(TaskFormatProperty, p_format);
|
||||||
connect(process, SIGNAL(finished(int, QProcess::ExitStatus)),
|
connect(process, SIGNAL(finished(int, QProcess::ExitStatus)),
|
||||||
this, SLOT(handleProcessFinished(int, QProcess::ExitStatus)));
|
this, SLOT(handleProcessFinished(int, QProcess::ExitStatus)));
|
||||||
@ -51,7 +53,8 @@ void VGraphvizHelper::handleProcessFinished(int p_exitCode, QProcess::ExitStatus
|
|||||||
QProcess *process = static_cast<QProcess *>(sender());
|
QProcess *process = static_cast<QProcess *>(sender());
|
||||||
int id = process->property(TaskIdProperty).toInt();
|
int id = process->property(TaskIdProperty).toInt();
|
||||||
QString format = process->property(TaskFormatProperty).toString();
|
QString format = process->property(TaskFormatProperty).toString();
|
||||||
qDebug() << "process finished" << id << format << p_exitCode << p_exitStatus;
|
TimeStamp timeStamp = process->property(TaskTimeStampProperty).toULongLong();
|
||||||
|
qDebug() << "process finished" << id << timeStamp << format << p_exitCode << p_exitStatus;
|
||||||
bool failed = true;
|
bool failed = true;
|
||||||
if (p_exitStatus == QProcess::NormalExit) {
|
if (p_exitStatus == QProcess::NormalExit) {
|
||||||
if (p_exitCode < 0) {
|
if (p_exitCode < 0) {
|
||||||
@ -60,9 +63,9 @@ void VGraphvizHelper::handleProcessFinished(int p_exitCode, QProcess::ExitStatus
|
|||||||
failed = false;
|
failed = false;
|
||||||
QByteArray outBa = process->readAllStandardOutput();
|
QByteArray outBa = process->readAllStandardOutput();
|
||||||
if (format == "svg") {
|
if (format == "svg") {
|
||||||
emit resultReady(id, format, QString::fromLocal8Bit(outBa));
|
emit resultReady(id, timeStamp, format, QString::fromLocal8Bit(outBa));
|
||||||
} else {
|
} else {
|
||||||
emit resultReady(id, format, QString::fromLocal8Bit(outBa.toBase64()));
|
emit resultReady(id, timeStamp, format, QString::fromLocal8Bit(outBa.toBase64()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@ -76,7 +79,7 @@ void VGraphvizHelper::handleProcessFinished(int p_exitCode, QProcess::ExitStatus
|
|||||||
qWarning() << "Graphviz stderr:" << errStr;
|
qWarning() << "Graphviz stderr:" << errStr;
|
||||||
}
|
}
|
||||||
|
|
||||||
emit resultReady(id, format, "");
|
emit resultReady(id, timeStamp, format, "");
|
||||||
}
|
}
|
||||||
|
|
||||||
process->deleteLater();
|
process->deleteLater();
|
||||||
|
@ -6,18 +6,20 @@
|
|||||||
#include <QStringList>
|
#include <QStringList>
|
||||||
#include <QProcess>
|
#include <QProcess>
|
||||||
|
|
||||||
|
#include "vconstants.h"
|
||||||
|
|
||||||
class VGraphvizHelper : public QObject
|
class VGraphvizHelper : public QObject
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
public:
|
public:
|
||||||
explicit VGraphvizHelper(QObject *p_parent = nullptr);
|
explicit VGraphvizHelper(QObject *p_parent = nullptr);
|
||||||
|
|
||||||
void processAsync(int p_id, const QString &p_format, const QString &p_text);
|
void processAsync(int p_id, TimeStamp p_timeStamp, const QString &p_format, const QString &p_text);
|
||||||
|
|
||||||
void prepareCommand(QString &p_cmd, QStringList &p_args) const;
|
void prepareCommand(QString &p_cmd, QStringList &p_args) const;
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void resultReady(int p_id, const QString &p_format, const QString &p_result);
|
void resultReady(int p_id, TimeStamp p_timeStamp, const QString &p_format, const QString &p_result);
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
void handleProcessFinished(int p_exitCode, QProcess::ExitStatus p_exitStatus);
|
void handleProcessFinished(int p_exitCode, QProcess::ExitStatus p_exitStatus);
|
||||||
|
@ -42,6 +42,7 @@ CodeBlockPreviewInfo::CodeBlockPreviewInfo(const VCodeBlock &p_cb)
|
|||||||
void CodeBlockPreviewInfo::clearImageData()
|
void CodeBlockPreviewInfo::clearImageData()
|
||||||
{
|
{
|
||||||
m_imgData.clear();
|
m_imgData.clear();
|
||||||
|
m_imgDataBa.clear();
|
||||||
m_inplacePreview.clear();
|
m_inplacePreview.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -64,7 +65,6 @@ void CodeBlockPreviewInfo::updateNonContent(const QTextDocument *p_doc,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update inplace preview according to m_imgData.
|
|
||||||
void CodeBlockPreviewInfo::updateInplacePreview(const VEditor *p_editor,
|
void CodeBlockPreviewInfo::updateInplacePreview(const VEditor *p_editor,
|
||||||
const QTextDocument *p_doc)
|
const QTextDocument *p_doc)
|
||||||
{
|
{
|
||||||
@ -100,12 +100,12 @@ VLivePreviewHelper::VLivePreviewHelper(VEditor *p_editor,
|
|||||||
m_livePreviewEnabled(false),
|
m_livePreviewEnabled(false),
|
||||||
m_inplacePreviewEnabled(false),
|
m_inplacePreviewEnabled(false),
|
||||||
m_graphvizHelper(NULL),
|
m_graphvizHelper(NULL),
|
||||||
m_plantUMLHelper(NULL)
|
m_plantUMLHelper(NULL),
|
||||||
|
m_lastInplacePreviewSize(0),
|
||||||
|
m_timeStamp(0)
|
||||||
{
|
{
|
||||||
connect(m_editor->object(), &VEditorObject::cursorPositionChanged,
|
connect(m_editor->object(), &VEditorObject::cursorPositionChanged,
|
||||||
this, &VLivePreviewHelper::handleCursorPositionChanged);
|
this, &VLivePreviewHelper::handleCursorPositionChanged);
|
||||||
connect(m_document, &VDocument::codeBlockPreviewReady,
|
|
||||||
this, &VLivePreviewHelper::webAsyncResultReady);
|
|
||||||
|
|
||||||
m_flowchartEnabled = g_config->getEnableFlowchart();
|
m_flowchartEnabled = g_config->getEnableFlowchart();
|
||||||
m_mermaidEnabled = g_config->getEnableMermaid();
|
m_mermaidEnabled = g_config->getEnableMermaid();
|
||||||
@ -117,6 +117,9 @@ VLivePreviewHelper::VLivePreviewHelper(VEditor *p_editor,
|
|||||||
m_mathJaxID = m_mathJaxHelper->registerIdentifier();
|
m_mathJaxID = m_mathJaxHelper->registerIdentifier();
|
||||||
connect(m_mathJaxHelper, &VMathJaxPreviewHelper::mathjaxPreviewResultReady,
|
connect(m_mathJaxHelper, &VMathJaxPreviewHelper::mathjaxPreviewResultReady,
|
||||||
this, &VLivePreviewHelper::mathjaxPreviewResultReady);
|
this, &VLivePreviewHelper::mathjaxPreviewResultReady);
|
||||||
|
connect(m_mathJaxHelper, &VMathJaxPreviewHelper::diagramPreviewResultReady,
|
||||||
|
// The same handle logics.
|
||||||
|
this, &VLivePreviewHelper::mathjaxPreviewResultReady);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool VLivePreviewHelper::isPreviewLang(const QString &p_lang) const
|
bool VLivePreviewHelper::isPreviewLang(const QString &p_lang) const
|
||||||
@ -134,6 +137,8 @@ void VLivePreviewHelper::updateCodeBlocks(const QVector<VCodeBlock> &p_codeBlock
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
++m_timeStamp;
|
||||||
|
|
||||||
int lastIndex = m_cbIndex;
|
int lastIndex = m_cbIndex;
|
||||||
m_cbIndex = -1;
|
m_cbIndex = -1;
|
||||||
int cursorBlock = m_editor->textCursorW().block().blockNumber();
|
int cursorBlock = m_editor->textCursorW().block().blockNumber();
|
||||||
@ -239,6 +244,7 @@ void VLivePreviewHelper::updateLivePreview()
|
|||||||
|
|
||||||
if (!cb.hasImageData()) {
|
if (!cb.hasImageData()) {
|
||||||
m_graphvizHelper->processAsync(m_cbIndex | LANG_PREFIX_GRAPHVIZ | TYPE_LIVE_PREVIEW,
|
m_graphvizHelper->processAsync(m_cbIndex | LANG_PREFIX_GRAPHVIZ | TYPE_LIVE_PREVIEW,
|
||||||
|
m_timeStamp,
|
||||||
"svg",
|
"svg",
|
||||||
removeFence(vcb.m_text));
|
removeFence(vcb.m_text));
|
||||||
} else {
|
} else {
|
||||||
@ -253,6 +259,7 @@ void VLivePreviewHelper::updateLivePreview()
|
|||||||
|
|
||||||
if (!cb.hasImageData()) {
|
if (!cb.hasImageData()) {
|
||||||
m_plantUMLHelper->processAsync(m_cbIndex | LANG_PREFIX_PLANTUML | TYPE_LIVE_PREVIEW,
|
m_plantUMLHelper->processAsync(m_cbIndex | LANG_PREFIX_PLANTUML | TYPE_LIVE_PREVIEW,
|
||||||
|
m_timeStamp,
|
||||||
"svg",
|
"svg",
|
||||||
removeFence(vcb.m_text));
|
removeFence(vcb.m_text));
|
||||||
} else {
|
} else {
|
||||||
@ -292,13 +299,20 @@ void VLivePreviewHelper::setInplacePreviewEnabled(bool p_enabled)
|
|||||||
for (auto & cb : m_codeBlocks) {
|
for (auto & cb : m_codeBlocks) {
|
||||||
cb.clearImageData();
|
cb.clearImageData();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
updateInplacePreview();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void VLivePreviewHelper::localAsyncResultReady(int p_id,
|
void VLivePreviewHelper::localAsyncResultReady(int p_id,
|
||||||
|
TimeStamp p_timeStamp,
|
||||||
const QString &p_format,
|
const QString &p_format,
|
||||||
const QString &p_result)
|
const QString &p_result)
|
||||||
{
|
{
|
||||||
|
if (p_timeStamp != m_timeStamp) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
Q_UNUSED(p_format);
|
Q_UNUSED(p_format);
|
||||||
Q_ASSERT(p_format == "svg");
|
Q_ASSERT(p_format == "svg");
|
||||||
int idx = p_id & INDEX_MASK;
|
int idx = p_id & INDEX_MASK;
|
||||||
@ -354,6 +368,7 @@ void VLivePreviewHelper::processForInplacePreview(int p_idx)
|
|||||||
updateInplacePreview();
|
updateInplacePreview();
|
||||||
} else {
|
} else {
|
||||||
m_graphvizHelper->processAsync(p_idx | LANG_PREFIX_GRAPHVIZ | TYPE_INPLACE_PREVIEW,
|
m_graphvizHelper->processAsync(p_idx | LANG_PREFIX_GRAPHVIZ | TYPE_INPLACE_PREVIEW,
|
||||||
|
m_timeStamp,
|
||||||
"svg",
|
"svg",
|
||||||
removeFence(vcb.m_text));
|
removeFence(vcb.m_text));
|
||||||
}
|
}
|
||||||
@ -369,43 +384,66 @@ void VLivePreviewHelper::processForInplacePreview(int p_idx)
|
|||||||
updateInplacePreview();
|
updateInplacePreview();
|
||||||
} else {
|
} else {
|
||||||
m_plantUMLHelper->processAsync(p_idx | LANG_PREFIX_PLANTUML | TYPE_INPLACE_PREVIEW,
|
m_plantUMLHelper->processAsync(p_idx | LANG_PREFIX_PLANTUML | TYPE_INPLACE_PREVIEW,
|
||||||
|
m_timeStamp,
|
||||||
"svg",
|
"svg",
|
||||||
removeFence(vcb.m_text));
|
removeFence(vcb.m_text));
|
||||||
}
|
}
|
||||||
} else if (vcb.m_lang == "flow"
|
} else if (vcb.m_lang == "flow"
|
||||||
|| vcb.m_lang == "flowchart") {
|
|| vcb.m_lang == "flowchart") {
|
||||||
m_document->previewCodeBlock(p_idx,
|
m_mathJaxHelper->previewDiagram(m_mathJaxID,
|
||||||
vcb.m_lang,
|
p_idx,
|
||||||
removeFence(vcb.m_text),
|
m_timeStamp,
|
||||||
false);
|
vcb.m_lang,
|
||||||
|
removeFence(vcb.m_text));
|
||||||
} else if (vcb.m_lang == "mathjax") {
|
} else if (vcb.m_lang == "mathjax") {
|
||||||
m_mathJaxHelper->previewMathJax(m_mathJaxID,
|
m_mathJaxHelper->previewMathJax(m_mathJaxID,
|
||||||
p_idx,
|
p_idx,
|
||||||
|
m_timeStamp,
|
||||||
removeFence(vcb.m_text));
|
removeFence(vcb.m_text));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void VLivePreviewHelper::updateInplacePreview()
|
void VLivePreviewHelper::updateInplacePreview()
|
||||||
{
|
{
|
||||||
|
QSet<int> blocks;
|
||||||
QVector<QSharedPointer<VImageToPreview> > images;
|
QVector<QSharedPointer<VImageToPreview> > images;
|
||||||
for (int i = 0; i < m_codeBlocks.size(); ++i) {
|
for (int i = 0; i < m_codeBlocks.size(); ++i) {
|
||||||
CodeBlockPreviewInfo &cb = m_codeBlocks[i];
|
CodeBlockPreviewInfo &cb = m_codeBlocks[i];
|
||||||
if (cb.inplacePreviewReady()) {
|
if (cb.inplacePreviewReady()) {
|
||||||
// Generate the image.
|
// Generate the image.
|
||||||
|
bool valid = false;
|
||||||
if (cb.hasImageData()) {
|
if (cb.hasImageData()) {
|
||||||
cb.inplacePreview()->m_image.loadFromData(cb.imageData().toUtf8(),
|
cb.inplacePreview()->m_image.loadFromData(cb.imageData().toUtf8(),
|
||||||
cb.imageFormat().toLocal8Bit().data());
|
cb.imageFormat().toLocal8Bit().data());
|
||||||
images.append(cb.inplacePreview());
|
images.append(cb.inplacePreview());
|
||||||
|
valid = true;
|
||||||
} else if (cb.hasImageDataBa()) {
|
} else if (cb.hasImageDataBa()) {
|
||||||
cb.inplacePreview()->m_image.loadFromData(cb.imageDataBa(),
|
cb.inplacePreview()->m_image.loadFromData(cb.imageDataBa(),
|
||||||
cb.imageFormat().toLocal8Bit().data());
|
cb.imageFormat().toLocal8Bit().data());
|
||||||
images.append(cb.inplacePreview());
|
images.append(cb.inplacePreview());
|
||||||
|
valid = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!valid) {
|
||||||
|
blocks.insert(cb.inplacePreview()->m_blockNumber);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
blocks.insert(cb.codeBlock().m_endBlock);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (images.isEmpty() && m_lastInplacePreviewSize == 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
emit inplacePreviewCodeBlockUpdated(images);
|
emit inplacePreviewCodeBlockUpdated(images);
|
||||||
|
|
||||||
|
m_lastInplacePreviewSize = images.size();
|
||||||
|
|
||||||
|
if (!blocks.isEmpty()) {
|
||||||
|
emit checkBlocksForObsoletePreview(blocks.toList());
|
||||||
|
}
|
||||||
|
|
||||||
// Clear image.
|
// Clear image.
|
||||||
for (int i = 0; i < m_codeBlocks.size(); ++i) {
|
for (int i = 0; i < m_codeBlocks.size(); ++i) {
|
||||||
CodeBlockPreviewInfo &cb = m_codeBlocks[i];
|
CodeBlockPreviewInfo &cb = m_codeBlocks[i];
|
||||||
@ -416,28 +454,18 @@ void VLivePreviewHelper::updateInplacePreview()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void VLivePreviewHelper::webAsyncResultReady(int p_id,
|
|
||||||
const QString &p_lang,
|
|
||||||
const QString &p_result)
|
|
||||||
{
|
|
||||||
Q_UNUSED(p_lang);
|
|
||||||
if (p_id >= m_codeBlocks.size() || p_result.isEmpty()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
CodeBlockPreviewInfo &cb = m_codeBlocks[p_id];
|
|
||||||
cb.setImageData(QStringLiteral("svg"), p_result);
|
|
||||||
cb.updateInplacePreview(m_editor, m_doc);
|
|
||||||
updateInplacePreview();
|
|
||||||
}
|
|
||||||
|
|
||||||
void VLivePreviewHelper::mathjaxPreviewResultReady(int p_identitifer,
|
void VLivePreviewHelper::mathjaxPreviewResultReady(int p_identitifer,
|
||||||
int p_id,
|
int p_id,
|
||||||
|
TimeStamp p_timeStamp,
|
||||||
const QString &p_format,
|
const QString &p_format,
|
||||||
const QByteArray &p_data)
|
const QByteArray &p_data)
|
||||||
{
|
{
|
||||||
if (p_identitifer != m_mathJaxID
|
if (p_identitifer != m_mathJaxID || p_timeStamp != m_timeStamp) {
|
||||||
|| (p_id >= m_codeBlocks.size() || p_data.isEmpty())) {
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (p_id >= m_codeBlocks.size() || p_data.isEmpty()) {
|
||||||
|
updateInplacePreview();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -6,6 +6,7 @@
|
|||||||
|
|
||||||
#include "hgmarkdownhighlighter.h"
|
#include "hgmarkdownhighlighter.h"
|
||||||
#include "vpreviewmanager.h"
|
#include "vpreviewmanager.h"
|
||||||
|
#include "vconstants.h"
|
||||||
|
|
||||||
class VEditor;
|
class VEditor;
|
||||||
class VDocument;
|
class VDocument;
|
||||||
@ -133,18 +134,19 @@ public:
|
|||||||
public slots:
|
public slots:
|
||||||
void updateCodeBlocks(const QVector<VCodeBlock> &p_codeBlocks);
|
void updateCodeBlocks(const QVector<VCodeBlock> &p_codeBlocks);
|
||||||
|
|
||||||
void webAsyncResultReady(int p_id, const QString &p_lang, const QString &p_result);
|
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void inplacePreviewCodeBlockUpdated(const QVector<QSharedPointer<VImageToPreview> > &p_images);
|
void inplacePreviewCodeBlockUpdated(const QVector<QSharedPointer<VImageToPreview> > &p_images);
|
||||||
|
|
||||||
|
void checkBlocksForObsoletePreview(const QList<int> &p_blocks);
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
void handleCursorPositionChanged();
|
void handleCursorPositionChanged();
|
||||||
|
|
||||||
void localAsyncResultReady(int p_id, const QString &p_format, const QString &p_result);
|
void localAsyncResultReady(int p_id, TimeStamp p_timeStamp, const QString &p_format, const QString &p_result);
|
||||||
|
|
||||||
void mathjaxPreviewResultReady(int p_identitifer,
|
void mathjaxPreviewResultReady(int p_identitifer,
|
||||||
int p_id,
|
int p_id,
|
||||||
|
TimeStamp p_timeStamp,
|
||||||
const QString &p_format,
|
const QString &p_format,
|
||||||
const QByteArray &p_data);
|
const QByteArray &p_data);
|
||||||
|
|
||||||
@ -187,6 +189,10 @@ private:
|
|||||||
|
|
||||||
// Identification for VMathJaxPreviewHelper.
|
// Identification for VMathJaxPreviewHelper.
|
||||||
int m_mathJaxID;
|
int m_mathJaxID;
|
||||||
|
|
||||||
|
int m_lastInplacePreviewSize;
|
||||||
|
|
||||||
|
TimeStamp m_timeStamp;
|
||||||
};
|
};
|
||||||
|
|
||||||
inline bool VLivePreviewHelper::isPreviewEnabled() const
|
inline bool VLivePreviewHelper::isPreviewEnabled() const
|
||||||
|
@ -24,6 +24,7 @@ VMathJaxPreviewHelper::~VMathJaxPreviewHelper()
|
|||||||
void VMathJaxPreviewHelper::doInit()
|
void VMathJaxPreviewHelper::doInit()
|
||||||
{
|
{
|
||||||
Q_ASSERT(!m_initialized);
|
Q_ASSERT(!m_initialized);
|
||||||
|
m_initialized = true;
|
||||||
|
|
||||||
m_webView = new QWebEngineView(m_parentWidget);
|
m_webView = new QWebEngineView(m_parentWidget);
|
||||||
connect(m_webView, &QWebEngineView::loadFinished,
|
connect(m_webView, &QWebEngineView::loadFinished,
|
||||||
@ -36,9 +37,23 @@ void VMathJaxPreviewHelper::doInit()
|
|||||||
|
|
||||||
m_webDoc = new VMathJaxWebDocument(m_webView);
|
m_webDoc = new VMathJaxWebDocument(m_webView);
|
||||||
connect(m_webDoc, &VMathJaxWebDocument::mathjaxPreviewResultReady,
|
connect(m_webDoc, &VMathJaxWebDocument::mathjaxPreviewResultReady,
|
||||||
this, [this](int p_identifier, int p_id, const QString &p_format, const QString &p_data) {
|
this, [this](int p_identifier,
|
||||||
|
int p_id,
|
||||||
|
TimeStamp p_timeStamp,
|
||||||
|
const QString &p_format,
|
||||||
|
const QString &p_data) {
|
||||||
QByteArray ba = QByteArray::fromBase64(p_data.toUtf8());
|
QByteArray ba = QByteArray::fromBase64(p_data.toUtf8());
|
||||||
emit mathjaxPreviewResultReady(p_identifier, p_id, p_format, ba);
|
emit mathjaxPreviewResultReady(p_identifier, p_id, p_timeStamp, p_format, ba);
|
||||||
|
});
|
||||||
|
|
||||||
|
connect(m_webDoc, &VMathJaxWebDocument::diagramPreviewResultReady,
|
||||||
|
this, [this](int p_identifier,
|
||||||
|
int p_id,
|
||||||
|
TimeStamp p_timeStamp,
|
||||||
|
const QString &p_format,
|
||||||
|
const QString &p_data) {
|
||||||
|
QByteArray ba = QByteArray::fromBase64(p_data.toUtf8());
|
||||||
|
emit diagramPreviewResultReady(p_identifier, p_id, p_timeStamp, p_format, ba);
|
||||||
});
|
});
|
||||||
|
|
||||||
QWebChannel *channel = new QWebChannel(m_webView);
|
QWebChannel *channel = new QWebChannel(m_webView);
|
||||||
@ -50,15 +65,25 @@ void VMathJaxPreviewHelper::doInit()
|
|||||||
while (!m_webReady) {
|
while (!m_webReady) {
|
||||||
VUtils::sleepWait(100);
|
VUtils::sleepWait(100);
|
||||||
}
|
}
|
||||||
|
|
||||||
m_initialized = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void VMathJaxPreviewHelper::previewMathJax(int p_identifier,
|
void VMathJaxPreviewHelper::previewMathJax(int p_identifier,
|
||||||
int p_id,
|
int p_id,
|
||||||
|
TimeStamp p_timeStamp,
|
||||||
const QString &p_text)
|
const QString &p_text)
|
||||||
{
|
{
|
||||||
init();
|
init();
|
||||||
|
|
||||||
m_webDoc->previewMathJax(p_identifier, p_id, p_text);
|
m_webDoc->previewMathJax(p_identifier, p_id, p_timeStamp, p_text);
|
||||||
|
}
|
||||||
|
|
||||||
|
void VMathJaxPreviewHelper::previewDiagram(int p_identifier,
|
||||||
|
int p_id,
|
||||||
|
TimeStamp p_timeStamp,
|
||||||
|
const QString &p_lang,
|
||||||
|
const QString &p_text)
|
||||||
|
{
|
||||||
|
init();
|
||||||
|
|
||||||
|
m_webDoc->previewDiagram(p_identifier, p_id, p_timeStamp, p_lang, p_text);
|
||||||
}
|
}
|
||||||
|
@ -3,6 +3,8 @@
|
|||||||
|
|
||||||
#include <QObject>
|
#include <QObject>
|
||||||
|
|
||||||
|
#include "vconstants.h"
|
||||||
|
|
||||||
class QWebEngineView;
|
class QWebEngineView;
|
||||||
class VMathJaxWebDocument;
|
class VMathJaxWebDocument;
|
||||||
class QWidget;
|
class QWidget;
|
||||||
@ -18,15 +20,33 @@ public:
|
|||||||
// Get an ID for identification.
|
// Get an ID for identification.
|
||||||
int registerIdentifier();
|
int registerIdentifier();
|
||||||
|
|
||||||
// Preview @p_text and return SVG data asynchronously.
|
// Preview @p_text and return PNG data asynchronously.
|
||||||
// @p_identifier: identifier the caller registered;
|
// @p_identifier: identifier the caller registered;
|
||||||
// @p_id: internal id for each caller;
|
// @p_id: internal id for each caller;
|
||||||
// @p_text: raw text of the MathJax script.
|
// @p_text: raw text of the MathJax script.
|
||||||
void previewMathJax(int p_identifier, int p_id, const QString &p_text);
|
void previewMathJax(int p_identifier, int p_id, TimeStamp p_timeStamp, const QString &p_text);
|
||||||
|
|
||||||
|
// Preview @p_text and return PNG data asynchronously.
|
||||||
|
// @p_identifier: identifier the caller registered;
|
||||||
|
// @p_id: internal id for each caller;
|
||||||
|
// @p_lang: language of the diagram;
|
||||||
|
// @p_text: raw text of the script.
|
||||||
|
void previewDiagram(int p_identifier,
|
||||||
|
int p_id,
|
||||||
|
TimeStamp p_timeStamp,
|
||||||
|
const QString &p_lang,
|
||||||
|
const QString &p_text);
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void mathjaxPreviewResultReady(int p_identifier,
|
void mathjaxPreviewResultReady(int p_identifier,
|
||||||
int p_id,
|
int p_id,
|
||||||
|
TimeStamp p_timeStamp,
|
||||||
|
const QString &p_format,
|
||||||
|
const QByteArray &p_data);
|
||||||
|
|
||||||
|
void diagramPreviewResultReady(int p_identifier,
|
||||||
|
int p_id,
|
||||||
|
TimeStamp p_timeStamp,
|
||||||
const QString &p_format,
|
const QString &p_format,
|
||||||
const QByteArray &p_data);
|
const QByteArray &p_data);
|
||||||
|
|
||||||
|
@ -9,15 +9,39 @@ VMathJaxWebDocument::VMathJaxWebDocument(QObject *p_parent)
|
|||||||
|
|
||||||
void VMathJaxWebDocument::previewMathJax(int p_identifier,
|
void VMathJaxWebDocument::previewMathJax(int p_identifier,
|
||||||
int p_id,
|
int p_id,
|
||||||
|
TimeStamp p_timeStamp,
|
||||||
const QString &p_text)
|
const QString &p_text)
|
||||||
{
|
{
|
||||||
emit requestPreviewMathJax(p_identifier, p_id, p_text);
|
emit requestPreviewMathJax(p_identifier, p_id, p_timeStamp, p_text);
|
||||||
}
|
}
|
||||||
|
|
||||||
void VMathJaxWebDocument::mathjaxResultReady(int p_identifier,
|
void VMathJaxWebDocument::mathjaxResultReady(int p_identifier,
|
||||||
int p_id,
|
int p_id,
|
||||||
|
unsigned long long p_timeStamp,
|
||||||
const QString &p_format,
|
const QString &p_format,
|
||||||
const QString &p_data)
|
const QString &p_data)
|
||||||
{
|
{
|
||||||
emit mathjaxPreviewResultReady(p_identifier, p_id, p_format, 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);
|
||||||
}
|
}
|
||||||
|
@ -3,27 +3,58 @@
|
|||||||
|
|
||||||
#include <QObject>
|
#include <QObject>
|
||||||
|
|
||||||
|
#include "vconstants.h"
|
||||||
|
|
||||||
class VMathJaxWebDocument : public QObject
|
class VMathJaxWebDocument : public QObject
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
public:
|
public:
|
||||||
explicit VMathJaxWebDocument(QObject *p_parent = nullptr);
|
explicit VMathJaxWebDocument(QObject *p_parent = nullptr);
|
||||||
|
|
||||||
void previewMathJax(int p_identifier, int p_id, const QString &p_text);
|
void previewMathJax(int p_identifier, int p_id, TimeStamp p_timeStamp, const QString &p_text);
|
||||||
|
|
||||||
|
void previewDiagram(int p_identifier,
|
||||||
|
int p_id,
|
||||||
|
TimeStamp p_timeStamp,
|
||||||
|
const QString &p_lang,
|
||||||
|
const QString &p_text);
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
// Will be called in the HTML side
|
// Will be called in the HTML side
|
||||||
|
|
||||||
void mathjaxResultReady(int p_identifier,
|
void mathjaxResultReady(int p_identifier,
|
||||||
int p_id,
|
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_format,
|
||||||
const QString &p_data);
|
const QString &p_data);
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void requestPreviewMathJax(int p_identifier, int p_id, const QString &p_text);
|
void requestPreviewMathJax(int p_identifier,
|
||||||
|
int p_id,
|
||||||
|
unsigned long long p_timeStamp,
|
||||||
|
const QString &p_text);
|
||||||
|
|
||||||
|
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,
|
void mathjaxPreviewResultReady(int p_identifier,
|
||||||
int p_id,
|
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_format,
|
||||||
const QString &p_data);
|
const QString &p_data);
|
||||||
};
|
};
|
||||||
|
@ -523,6 +523,8 @@ void VMdTab::setupMarkdownEditor()
|
|||||||
m_livePreviewHelper, &VLivePreviewHelper::setInplacePreviewEnabled);
|
m_livePreviewHelper, &VLivePreviewHelper::setInplacePreviewEnabled);
|
||||||
connect(m_livePreviewHelper, &VLivePreviewHelper::inplacePreviewCodeBlockUpdated,
|
connect(m_livePreviewHelper, &VLivePreviewHelper::inplacePreviewCodeBlockUpdated,
|
||||||
m_editor->getPreviewManager(), &VPreviewManager::updateCodeBlocks);
|
m_editor->getPreviewManager(), &VPreviewManager::updateCodeBlocks);
|
||||||
|
connect(m_livePreviewHelper, &VLivePreviewHelper::checkBlocksForObsoletePreview,
|
||||||
|
m_editor->getPreviewManager(), &VPreviewManager::checkBlocksForObsoletePreview);
|
||||||
m_livePreviewHelper->setInplacePreviewEnabled(m_editor->getPreviewManager()->isPreviewEnabled());
|
m_livePreviewHelper->setInplacePreviewEnabled(m_editor->getPreviewManager()->isPreviewEnabled());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -174,7 +174,17 @@ QString VNote::generateMathJaxPreviewTemplate()
|
|||||||
const QString c_templatePath(":/resources/mathjax_preview_template.html");
|
const QString c_templatePath(":/resources/mathjax_preview_template.html");
|
||||||
QString templ = VUtils::readFileFromDisk(c_templatePath);
|
QString templ = VUtils::readFileFromDisk(c_templatePath);
|
||||||
g_palette->fillStyle(templ);
|
g_palette->fillStyle(templ);
|
||||||
|
|
||||||
|
QString cssStyle;
|
||||||
|
cssStyle += "div.flowchart-diagram { margin: 0px !important; "
|
||||||
|
" padding: 0px 5px 0px 5px !important; }\n"
|
||||||
|
"div.mermaid-diagram { margin: 0px !important; "
|
||||||
|
" padding: 0px 5px 0px 5px !important; }\n";
|
||||||
|
|
||||||
|
templ.replace(HtmlHolder::c_globalStyleHolder, cssStyle);
|
||||||
|
|
||||||
templ.replace(HtmlHolder::c_cssHolder, g_config->getCssStyleUrl());
|
templ.replace(HtmlHolder::c_cssHolder, g_config->getCssStyleUrl());
|
||||||
|
|
||||||
return templ;
|
return templ;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -182,6 +182,8 @@ VNotebook *VNotebook::createNotebook(const QString &p_name,
|
|||||||
if (!nb->writeToConfig()) {
|
if (!nb->writeToConfig()) {
|
||||||
delete nb;
|
delete nb;
|
||||||
return NULL;
|
return NULL;
|
||||||
|
} else {
|
||||||
|
nb->m_valid = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
return nb;
|
return nb;
|
||||||
|
@ -9,6 +9,7 @@ extern VConfigManager *g_config;
|
|||||||
|
|
||||||
#define TaskIdProperty "PlantUMLTaskId"
|
#define TaskIdProperty "PlantUMLTaskId"
|
||||||
#define TaskFormatProperty "PlantUMLTaskFormat"
|
#define TaskFormatProperty "PlantUMLTaskFormat"
|
||||||
|
#define TaskTimeStampProperty "PlantUMLTaskTimeStamp"
|
||||||
|
|
||||||
VPlantUMLHelper::VPlantUMLHelper(QObject *p_parent)
|
VPlantUMLHelper::VPlantUMLHelper(QObject *p_parent)
|
||||||
: QObject(p_parent)
|
: QObject(p_parent)
|
||||||
@ -16,10 +17,14 @@ VPlantUMLHelper::VPlantUMLHelper(QObject *p_parent)
|
|||||||
prepareCommand(m_program, m_args);
|
prepareCommand(m_program, m_args);
|
||||||
}
|
}
|
||||||
|
|
||||||
void VPlantUMLHelper::processAsync(int p_id, const QString &p_format, const QString &p_text)
|
void VPlantUMLHelper::processAsync(int p_id,
|
||||||
|
TimeStamp p_timeStamp,
|
||||||
|
const QString &p_format,
|
||||||
|
const QString &p_text)
|
||||||
{
|
{
|
||||||
QProcess *process = new QProcess(this);
|
QProcess *process = new QProcess(this);
|
||||||
process->setProperty(TaskIdProperty, p_id);
|
process->setProperty(TaskIdProperty, p_id);
|
||||||
|
process->setProperty(TaskTimeStampProperty, p_timeStamp);
|
||||||
process->setProperty(TaskFormatProperty, p_format);
|
process->setProperty(TaskFormatProperty, p_format);
|
||||||
connect(process, SIGNAL(finished(int, QProcess::ExitStatus)),
|
connect(process, SIGNAL(finished(int, QProcess::ExitStatus)),
|
||||||
this, SLOT(handleProcessFinished(int, QProcess::ExitStatus)));
|
this, SLOT(handleProcessFinished(int, QProcess::ExitStatus)));
|
||||||
@ -58,7 +63,8 @@ void VPlantUMLHelper::handleProcessFinished(int p_exitCode, QProcess::ExitStatus
|
|||||||
QProcess *process = static_cast<QProcess *>(sender());
|
QProcess *process = static_cast<QProcess *>(sender());
|
||||||
int id = process->property(TaskIdProperty).toInt();
|
int id = process->property(TaskIdProperty).toInt();
|
||||||
QString format = process->property(TaskFormatProperty).toString();
|
QString format = process->property(TaskFormatProperty).toString();
|
||||||
qDebug() << "process finished" << id << format << p_exitCode << p_exitStatus;
|
TimeStamp timeStamp = process->property(TaskTimeStampProperty).toULongLong();
|
||||||
|
qDebug() << "process finished" << id << timeStamp << format << p_exitCode << p_exitStatus;
|
||||||
bool failed = true;
|
bool failed = true;
|
||||||
if (p_exitStatus == QProcess::NormalExit) {
|
if (p_exitStatus == QProcess::NormalExit) {
|
||||||
if (p_exitCode < 0) {
|
if (p_exitCode < 0) {
|
||||||
@ -67,9 +73,9 @@ void VPlantUMLHelper::handleProcessFinished(int p_exitCode, QProcess::ExitStatus
|
|||||||
failed = false;
|
failed = false;
|
||||||
QByteArray outBa = process->readAllStandardOutput();
|
QByteArray outBa = process->readAllStandardOutput();
|
||||||
if (format == "svg") {
|
if (format == "svg") {
|
||||||
emit resultReady(id, format, QString::fromLocal8Bit(outBa));
|
emit resultReady(id, timeStamp, format, QString::fromLocal8Bit(outBa));
|
||||||
} else {
|
} else {
|
||||||
emit resultReady(id, format, QString::fromLocal8Bit(outBa.toBase64()));
|
emit resultReady(id, timeStamp, format, QString::fromLocal8Bit(outBa.toBase64()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@ -83,7 +89,7 @@ void VPlantUMLHelper::handleProcessFinished(int p_exitCode, QProcess::ExitStatus
|
|||||||
qWarning() << "PlantUML stderr:" << errStr;
|
qWarning() << "PlantUML stderr:" << errStr;
|
||||||
}
|
}
|
||||||
|
|
||||||
emit resultReady(id, format, "");
|
emit resultReady(id, timeStamp, format, "");
|
||||||
}
|
}
|
||||||
|
|
||||||
process->deleteLater();
|
process->deleteLater();
|
||||||
|
@ -6,18 +6,23 @@
|
|||||||
#include <QStringList>
|
#include <QStringList>
|
||||||
#include <QProcess>
|
#include <QProcess>
|
||||||
|
|
||||||
|
#include "vconstants.h"
|
||||||
|
|
||||||
class VPlantUMLHelper : public QObject
|
class VPlantUMLHelper : public QObject
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
public:
|
public:
|
||||||
explicit VPlantUMLHelper(QObject *p_parent = nullptr);
|
explicit VPlantUMLHelper(QObject *p_parent = nullptr);
|
||||||
|
|
||||||
void processAsync(int p_id, const QString &p_format, const QString &p_text);
|
void processAsync(int p_id,
|
||||||
|
TimeStamp p_timeStamp,
|
||||||
|
const QString &p_format,
|
||||||
|
const QString &p_text);
|
||||||
|
|
||||||
void prepareCommand(QString &p_cmd, QStringList &p_args) const;
|
void prepareCommand(QString &p_cmd, QStringList &p_args) const;
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void resultReady(int p_id, const QString &p_format, const QString &p_result);
|
void resultReady(int p_id, TimeStamp p_timeStamp, const QString &p_format, const QString &p_result);
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
void handleProcessFinished(int p_exitCode, QProcess::ExitStatus p_exitStatus);
|
void handleProcessFinished(int p_exitCode, QProcess::ExitStatus p_exitStatus);
|
||||||
|
@ -473,3 +473,40 @@ void VPreviewManager::updateCodeBlocks(const QVector<QSharedPointer<VImageToPrev
|
|||||||
|
|
||||||
clearObsoleteImages(ts, PreviewSource::CodeBlock);
|
clearObsoleteImages(ts, PreviewSource::CodeBlock);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void VPreviewManager::checkBlocksForObsoletePreview(const QList<int> &p_blocks)
|
||||||
|
{
|
||||||
|
if (p_blocks.isEmpty()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
QSet<int> affectedBlocks;
|
||||||
|
for (auto i : p_blocks) {
|
||||||
|
QTextBlock block = m_document->findBlockByNumber(i);
|
||||||
|
if (!block.isValid()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
VTextBlockData *blockData = dynamic_cast<VTextBlockData *>(block.userData());
|
||||||
|
if (!blockData) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (blockData->getPreviews().isEmpty()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < (int)PreviewSource::MaxNumberOfSources; ++i) {
|
||||||
|
if (blockData->getPreviews().isEmpty()) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
PreviewSource ps = static_cast<PreviewSource>(i);
|
||||||
|
if (blockData->clearObsoletePreview(timeStamp(ps), ps)) {
|
||||||
|
affectedBlocks.insert(i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
m_editor->relayout(affectedBlocks);
|
||||||
|
}
|
||||||
|
@ -67,6 +67,10 @@ public:
|
|||||||
|
|
||||||
bool isPreviewEnabled() const;
|
bool isPreviewEnabled() const;
|
||||||
|
|
||||||
|
// Check @p_blocks to see if there is any obsolete preview and clear them
|
||||||
|
// if there is any.
|
||||||
|
void checkBlocksForObsoletePreview(const QList<int> &p_blocks);
|
||||||
|
|
||||||
// Calculate the block margin (prefix spaces) in pixels.
|
// Calculate the block margin (prefix spaces) in pixels.
|
||||||
static int calculateBlockMargin(const QTextBlock &p_block, int p_tabStopWidth);
|
static int calculateBlockMargin(const QTextBlock &p_block, int p_tabStopWidth);
|
||||||
|
|
||||||
|
@ -89,9 +89,8 @@ bool VTextBlockData::clearObsoletePreview(long long p_timeStamp, PreviewSource p
|
|||||||
bool deleted = false;
|
bool deleted = false;
|
||||||
for (auto it = m_previews.begin(); it != m_previews.end();) {
|
for (auto it = m_previews.begin(); it != m_previews.end();) {
|
||||||
VPreviewInfo *ele = *it;
|
VPreviewInfo *ele = *it;
|
||||||
|
|
||||||
if (ele->m_source == p_source
|
if (ele->m_source == p_source
|
||||||
&& ele->m_timeStamp < p_timeStamp) {
|
&& ele->m_timeStamp != p_timeStamp) {
|
||||||
// Remove it.
|
// Remove it.
|
||||||
qDebug() << "clear obsolete preview" << ele->m_imageInfo.toString();
|
qDebug() << "clear obsolete preview" << ele->m_imageInfo.toString();
|
||||||
delete ele;
|
delete ele;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user