mirror of
https://gitee.com/vnotex/vnote.git
synced 2025-07-05 13:59:52 +08:00
MdEditor: support copying diagram in puml and graphviz
This commit is contained in:
parent
1fe975b1ad
commit
d4daf32f20
@ -44,6 +44,8 @@ public:
|
||||
|
||||
const QVector<VElementRegion> &getImageRegions() const;
|
||||
|
||||
const QVector<VCodeBlock> &getCodeBlocks() const;
|
||||
|
||||
public slots:
|
||||
// Parse and rehighlight immediately.
|
||||
void updateHighlight();
|
||||
@ -360,4 +362,9 @@ inline bool PegMarkdownHighlighter::isFastParseBlock(int p_blockNum) const
|
||||
{
|
||||
return p_blockNum >= m_fastParseBlocks.first && p_blockNum <= m_fastParseBlocks.second;
|
||||
}
|
||||
|
||||
inline const QVector<VCodeBlock> &PegMarkdownHighlighter::getCodeBlocks() const
|
||||
{
|
||||
return m_result->m_codeBlocks;
|
||||
}
|
||||
#endif // PEGMARKDOWNHIGHLIGHTER_H
|
||||
|
@ -7,6 +7,7 @@
|
||||
#include <QScrollBar>
|
||||
|
||||
#include "vutils.h"
|
||||
#include "vcodeblockhighlighthelper.h"
|
||||
|
||||
void VEditUtils::removeBlock(QTextBlock &p_block, QString *p_text)
|
||||
{
|
||||
@ -1083,3 +1084,11 @@ bool VEditUtils::isWordSeparator(QChar p_char)
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
QString VEditUtils::removeCodeBlockFence(const QString &p_text)
|
||||
{
|
||||
QString text = VCodeBlockHighlightHelper::unindentCodeBlock(p_text);
|
||||
Q_ASSERT(text.startsWith("```") && text.endsWith("```"));
|
||||
int idx = text.indexOf('\n') + 1;
|
||||
return text.mid(idx, text.size() - idx - 3);
|
||||
}
|
||||
|
@ -211,6 +211,9 @@ public:
|
||||
|
||||
static bool isWordSeparator(QChar p_char);
|
||||
|
||||
// Remove the fence of fenced code block.
|
||||
static QString removeCodeBlockFence(const QString &p_text);
|
||||
|
||||
private:
|
||||
VEditUtils() {}
|
||||
};
|
||||
|
@ -11,24 +11,36 @@ int VProcessUtils::startProcess(const QString &p_program,
|
||||
QByteArray &p_out,
|
||||
QByteArray &p_err)
|
||||
{
|
||||
int ret = 0;
|
||||
QScopedPointer<QProcess> process(new QProcess());
|
||||
process->start(p_program, p_args);
|
||||
return startProcess(process.data(),
|
||||
p_in,
|
||||
p_exitCode,
|
||||
p_out,
|
||||
p_err);
|
||||
}
|
||||
|
||||
int VProcessUtils::startProcess(QProcess *p_process,
|
||||
const QByteArray &p_in,
|
||||
int &p_exitCode,
|
||||
QByteArray &p_out,
|
||||
QByteArray &p_err)
|
||||
{
|
||||
int ret = 0;
|
||||
if (!p_in.isEmpty()) {
|
||||
if (process->write(p_in) == -1) {
|
||||
process->closeWriteChannel();
|
||||
qWarning() << "fail to write to QProcess:" << process->errorString();
|
||||
if (p_process->write(p_in) == -1) {
|
||||
p_process->closeWriteChannel();
|
||||
qWarning() << "fail to write to QProcess:" << p_process->errorString();
|
||||
return -1;
|
||||
} else {
|
||||
process->closeWriteChannel();
|
||||
p_process->closeWriteChannel();
|
||||
}
|
||||
}
|
||||
|
||||
bool finished = false;
|
||||
bool started = false;
|
||||
while (true) {
|
||||
QProcess::ProcessError err = process->error();
|
||||
QProcess::ProcessError err = p_process->error();
|
||||
if (err == QProcess::FailedToStart
|
||||
|| err == QProcess::Crashed) {
|
||||
if (err == QProcess::FailedToStart) {
|
||||
@ -41,34 +53,34 @@ int VProcessUtils::startProcess(const QString &p_program,
|
||||
}
|
||||
|
||||
if (started) {
|
||||
if (process->state() == QProcess::NotRunning) {
|
||||
if (p_process->state() == QProcess::NotRunning) {
|
||||
finished = true;
|
||||
}
|
||||
} else {
|
||||
if (process->state() != QProcess::NotRunning) {
|
||||
if (p_process->state() != QProcess::NotRunning) {
|
||||
started = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (process->waitForFinished(500)) {
|
||||
if (p_process->waitForFinished(500)) {
|
||||
// Finished.
|
||||
finished = true;
|
||||
}
|
||||
|
||||
if (finished) {
|
||||
QProcess::ExitStatus sta = process->exitStatus();
|
||||
QProcess::ExitStatus sta = p_process->exitStatus();
|
||||
if (sta == QProcess::CrashExit) {
|
||||
ret = -1;
|
||||
break;
|
||||
}
|
||||
|
||||
p_exitCode = process->exitCode();
|
||||
p_exitCode = p_process->exitCode();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
p_out = process->readAllStandardOutput();
|
||||
p_err = process->readAllStandardError();
|
||||
p_out = p_process->readAllStandardOutput();
|
||||
p_err = p_process->readAllStandardError();
|
||||
|
||||
return ret;
|
||||
}
|
||||
@ -86,3 +98,18 @@ int VProcessUtils::startProcess(const QString &p_program,
|
||||
p_out,
|
||||
p_err);
|
||||
}
|
||||
|
||||
int VProcessUtils::startProcess(const QString &p_cmd,
|
||||
const QByteArray &p_in,
|
||||
int &p_exitCode,
|
||||
QByteArray &p_out,
|
||||
QByteArray &p_err)
|
||||
{
|
||||
QScopedPointer<QProcess> process(new QProcess());
|
||||
process->start(p_cmd);
|
||||
return startProcess(process.data(),
|
||||
p_in,
|
||||
p_exitCode,
|
||||
p_out,
|
||||
p_err);
|
||||
}
|
||||
|
@ -4,6 +4,7 @@
|
||||
#include <QStringList>
|
||||
#include <QByteArray>
|
||||
|
||||
class QProcess;
|
||||
|
||||
class VProcessUtils
|
||||
{
|
||||
@ -25,8 +26,20 @@ public:
|
||||
QByteArray &p_out,
|
||||
QByteArray &p_err);
|
||||
|
||||
static int startProcess(const QString &p_cmd,
|
||||
const QByteArray &p_in,
|
||||
int &p_exitCode,
|
||||
QByteArray &p_out,
|
||||
QByteArray &p_err);
|
||||
|
||||
private:
|
||||
VProcessUtils() {}
|
||||
|
||||
static int startProcess(QProcess *p_process,
|
||||
const QByteArray &p_in,
|
||||
int &p_exitCode,
|
||||
QByteArray &p_out,
|
||||
QByteArray &p_err);
|
||||
};
|
||||
|
||||
#endif // VPROCESSUTILS_H
|
||||
|
@ -35,6 +35,17 @@ VEditor::~VEditor()
|
||||
if (m_completer->widget() == m_editor) {
|
||||
m_completer->setWidget(NULL);
|
||||
}
|
||||
|
||||
cleanUp();
|
||||
}
|
||||
|
||||
void VEditor::cleanUp()
|
||||
{
|
||||
for (auto const & file : m_tempFiles) {
|
||||
VUtils::deleteFile(file);
|
||||
}
|
||||
|
||||
m_tempFiles.clear();
|
||||
}
|
||||
|
||||
void VEditor::init()
|
||||
|
@ -254,6 +254,8 @@ protected:
|
||||
|
||||
virtual int lineNumberAreaWidth() const = 0;
|
||||
|
||||
void addTempFile(const QString &p_file);
|
||||
|
||||
QWidget *m_editor;
|
||||
|
||||
VEditorObject *m_object;
|
||||
@ -309,6 +311,8 @@ private:
|
||||
|
||||
QStringList generateCompletionCandidates() const;
|
||||
|
||||
void cleanUp();
|
||||
|
||||
QLabel *m_wrapLabel;
|
||||
QTimer *m_labelTimer;
|
||||
|
||||
@ -352,6 +356,9 @@ private:
|
||||
|
||||
QSharedPointer<VTextEditCompleter> m_completer;
|
||||
|
||||
// Temp files needed to be delete.
|
||||
QStringList m_tempFiles;
|
||||
|
||||
// Functions for private slots.
|
||||
private:
|
||||
void labelTimerTimeout();
|
||||
@ -456,4 +463,8 @@ inline QWidget *VEditor::getEditor() const
|
||||
return m_editor;
|
||||
}
|
||||
|
||||
inline void VEditor::addTempFile(const QString &p_file)
|
||||
{
|
||||
m_tempFiles.append(p_file);
|
||||
}
|
||||
#endif // VEDITOR_H
|
||||
|
@ -119,3 +119,26 @@ bool VGraphvizHelper::testGraphviz(const QString &p_dot, QString &p_msg)
|
||||
|
||||
return ret == 0 && exitCode == 0;
|
||||
}
|
||||
|
||||
QByteArray VGraphvizHelper::process(const QString &p_format, const QString &p_text)
|
||||
{
|
||||
VGraphvizHelper inst;
|
||||
|
||||
int exitCode = -1;
|
||||
QByteArray out, err;
|
||||
|
||||
QStringList args(inst.m_args);
|
||||
args << ("-T" + p_format);
|
||||
int ret = VProcessUtils::startProcess(inst.m_program,
|
||||
args,
|
||||
p_text.toUtf8(),
|
||||
exitCode,
|
||||
out,
|
||||
err);
|
||||
|
||||
if (ret != 0 || exitCode < 0) {
|
||||
qWarning() << "Graphviz fail" << ret << exitCode << QString::fromLocal8Bit(err);
|
||||
}
|
||||
|
||||
return out;
|
||||
}
|
||||
|
@ -16,10 +16,10 @@ public:
|
||||
|
||||
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;
|
||||
|
||||
static bool testGraphviz(const QString &p_dot, QString &p_msg);
|
||||
|
||||
static QByteArray process(const QString &p_format, const QString &p_text);
|
||||
|
||||
signals:
|
||||
void resultReady(int p_id, TimeStamp p_timeStamp, const QString &p_format, const QString &p_result);
|
||||
|
||||
@ -27,6 +27,8 @@ private slots:
|
||||
void handleProcessFinished(int p_exitCode, QProcess::ExitStatus p_exitStatus);
|
||||
|
||||
private:
|
||||
void prepareCommand(QString &p_cmd, QStringList &p_args) const;
|
||||
|
||||
QString m_program;
|
||||
QStringList m_args;
|
||||
};
|
||||
|
@ -8,10 +8,10 @@
|
||||
#include "vconfigmanager.h"
|
||||
#include "vgraphvizhelper.h"
|
||||
#include "vplantumlhelper.h"
|
||||
#include "vcodeblockhighlighthelper.h"
|
||||
#include "vmainwindow.h"
|
||||
#include "veditarea.h"
|
||||
#include "vmathjaxpreviewhelper.h"
|
||||
#include "utils/veditutils.h"
|
||||
|
||||
extern VConfigManager *g_config;
|
||||
|
||||
@ -249,14 +249,6 @@ void VLivePreviewHelper::handleCursorPositionChanged()
|
||||
}
|
||||
}
|
||||
|
||||
static QString removeFence(const QString &p_text)
|
||||
{
|
||||
QString text = VCodeBlockHighlightHelper::unindentCodeBlock(p_text);
|
||||
Q_ASSERT(text.startsWith("```") && text.endsWith("```"));
|
||||
int idx = text.indexOf('\n') + 1;
|
||||
return text.mid(idx, text.size() - idx - 3);
|
||||
}
|
||||
|
||||
void VLivePreviewHelper::updateLivePreview()
|
||||
{
|
||||
if (m_cbIndex < 0) {
|
||||
@ -277,7 +269,7 @@ void VLivePreviewHelper::updateLivePreview()
|
||||
m_graphvizHelper->processAsync(m_cbIndex | LANG_PREFIX_GRAPHVIZ | TYPE_LIVE_PREVIEW,
|
||||
m_timeStamp,
|
||||
"svg",
|
||||
removeFence(vcb.m_text));
|
||||
VEditUtils::removeCodeBlockFence(vcb.m_text));
|
||||
} else {
|
||||
m_document->setPreviewContent(vcb.m_lang, cb.imageData());
|
||||
}
|
||||
@ -292,7 +284,7 @@ void VLivePreviewHelper::updateLivePreview()
|
||||
m_plantUMLHelper->processAsync(m_cbIndex | LANG_PREFIX_PLANTUML | TYPE_LIVE_PREVIEW,
|
||||
m_timeStamp,
|
||||
"svg",
|
||||
removeFence(vcb.m_text));
|
||||
VEditUtils::removeCodeBlockFence(vcb.m_text));
|
||||
} else {
|
||||
m_document->setPreviewContent(vcb.m_lang, cb.imageData());
|
||||
}
|
||||
@ -300,7 +292,7 @@ void VLivePreviewHelper::updateLivePreview()
|
||||
// No need to live preview MathJax.
|
||||
m_document->previewCodeBlock(m_cbIndex,
|
||||
vcb.m_lang,
|
||||
removeFence(vcb.m_text),
|
||||
VEditUtils::removeCodeBlockFence(vcb.m_text),
|
||||
true);
|
||||
}
|
||||
}
|
||||
@ -418,7 +410,7 @@ void VLivePreviewHelper::processForInplacePreview(int p_idx)
|
||||
m_graphvizHelper->processAsync(p_idx | LANG_PREFIX_GRAPHVIZ | TYPE_INPLACE_PREVIEW,
|
||||
m_timeStamp,
|
||||
"svg",
|
||||
removeFence(vcb.m_text));
|
||||
VEditUtils::removeCodeBlockFence(vcb.m_text));
|
||||
} else if (vcb.m_lang == "puml" && m_plantUMLMode == PlantUMLMode::LocalPlantUML) {
|
||||
if (!m_plantUMLHelper) {
|
||||
m_plantUMLHelper = new VPlantUMLHelper(this);
|
||||
@ -429,19 +421,19 @@ void VLivePreviewHelper::processForInplacePreview(int p_idx)
|
||||
m_plantUMLHelper->processAsync(p_idx | LANG_PREFIX_PLANTUML | TYPE_INPLACE_PREVIEW,
|
||||
m_timeStamp,
|
||||
"svg",
|
||||
removeFence(vcb.m_text));
|
||||
VEditUtils::removeCodeBlockFence(vcb.m_text));
|
||||
} else if (vcb.m_lang == "flow"
|
||||
|| vcb.m_lang == "flowchart") {
|
||||
m_mathJaxHelper->previewDiagram(m_mathJaxID,
|
||||
p_idx,
|
||||
m_timeStamp,
|
||||
vcb.m_lang,
|
||||
removeFence(vcb.m_text));
|
||||
VEditUtils::removeCodeBlockFence(vcb.m_text));
|
||||
} else if (vcb.m_lang == "mathjax") {
|
||||
m_mathJaxHelper->previewMathJax(m_mathJaxID,
|
||||
p_idx,
|
||||
m_timeStamp,
|
||||
removeFence(vcb.m_text));
|
||||
VEditUtils::removeCodeBlockFence(vcb.m_text));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -25,6 +25,8 @@
|
||||
#include "utils/vwebutils.h"
|
||||
#include "dialog/vinsertlinkdialog.h"
|
||||
#include "utils/vclipboardutils.h"
|
||||
#include "vplantumlhelper.h"
|
||||
#include "vgraphvizhelper.h"
|
||||
|
||||
extern VWebUtils *g_webUtils;
|
||||
|
||||
@ -1604,7 +1606,16 @@ void VMdEditor::initLinkAndPreviewMenu(QAction *p_before, QMenu *p_menu, const Q
|
||||
return;
|
||||
}
|
||||
|
||||
bool needSeparator = false;
|
||||
if (initInPlacePreviewMenu(p_before, p_menu, block, pos)) {
|
||||
needSeparator = true;
|
||||
}
|
||||
|
||||
if (initExportAndCopyMenu(p_before, p_menu, block, pos)) {
|
||||
needSeparator = true;
|
||||
}
|
||||
|
||||
if (needSeparator) {
|
||||
p_menu->insertSeparator(p_before ? p_before : NULL);
|
||||
}
|
||||
}
|
||||
@ -1665,3 +1676,117 @@ bool VMdEditor::initInPlacePreviewMenu(QAction *p_before,
|
||||
p_menu->insertAction(p_before, copyImageAct);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool VMdEditor::initExportAndCopyMenu(QAction *p_before,
|
||||
QMenu *p_menu,
|
||||
const QTextBlock &p_block,
|
||||
int p_pos)
|
||||
{
|
||||
Q_UNUSED(p_pos);
|
||||
int state = p_block.userState();
|
||||
if (state != HighlightBlockState::CodeBlockStart
|
||||
&& state != HighlightBlockState::CodeBlock
|
||||
&& state != HighlightBlockState::CodeBlockEnd) {
|
||||
return false;
|
||||
}
|
||||
|
||||
int blockNum = p_block.blockNumber();
|
||||
const QVector<VCodeBlock> &cbs = m_pegHighlighter->getCodeBlocks();
|
||||
int idx = 0;
|
||||
for (idx = 0; idx < cbs.size(); ++idx) {
|
||||
if (cbs[idx].m_startBlock <= blockNum
|
||||
&& cbs[idx].m_endBlock >= blockNum) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (idx >= cbs.size()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const VCodeBlock &cb = cbs[idx];
|
||||
if (cb.m_lang != "puml" && cb.m_lang != "dot") {
|
||||
return false;
|
||||
}
|
||||
|
||||
QMenu *subMenu = new QMenu(tr("Copy Diagram"), p_menu);
|
||||
subMenu->setToolTipsVisible(true);
|
||||
|
||||
QAction *pngAct = new QAction(tr("PNG"), subMenu);
|
||||
pngAct->setToolTip(tr("Export diagram as PNG to a temporary file and copy"));
|
||||
connect(pngAct, &QAction::triggered,
|
||||
this, [this, lang = cb.m_lang, text = cb.m_text]() {
|
||||
exportDiagramAndCopy(lang, text, "png");
|
||||
});
|
||||
subMenu->addAction(pngAct);
|
||||
|
||||
QAction *svgAct = new QAction(tr("SVG"), subMenu);
|
||||
svgAct->setToolTip(tr("Export diagram as SVG to a temporary file and copy"));
|
||||
connect(svgAct, &QAction::triggered,
|
||||
this, [this, lang = cb.m_lang, text = cb.m_text]() {
|
||||
exportDiagramAndCopy(lang, text, "svg");
|
||||
});
|
||||
subMenu->addAction(svgAct);
|
||||
|
||||
p_menu->insertMenu(p_before, subMenu);
|
||||
return true;
|
||||
}
|
||||
|
||||
void VMdEditor::exportDiagramAndCopy(const QString &p_lang,
|
||||
const QString &p_text,
|
||||
const QString &p_format)
|
||||
{
|
||||
m_exportTempFile.reset(new QTemporaryFile(QDir::tempPath()
|
||||
+ QDir::separator()
|
||||
+ "XXXXXX." + p_format));
|
||||
if (!m_exportTempFile->open()) {
|
||||
VUtils::showMessage(QMessageBox::Warning,
|
||||
tr("Warning"),
|
||||
tr("Fail to open a temporary file for export."),
|
||||
"",
|
||||
QMessageBox::Ok,
|
||||
QMessageBox::Ok,
|
||||
this);
|
||||
m_exportTempFile.clear();
|
||||
return;
|
||||
}
|
||||
|
||||
emit m_object->statusMessage(tr("Exporting diagram"));
|
||||
|
||||
QString filePath(m_exportTempFile->fileName());
|
||||
QByteArray out;
|
||||
if (p_lang == "puml") {
|
||||
out = VPlantUMLHelper::process(p_format,
|
||||
VEditUtils::removeCodeBlockFence(p_text));
|
||||
} else if (p_lang == "dot") {
|
||||
out = VGraphvizHelper::process(p_format,
|
||||
VEditUtils::removeCodeBlockFence(p_text));
|
||||
}
|
||||
|
||||
if (out.isEmpty() || m_exportTempFile->write(out) == -1) {
|
||||
VUtils::showMessage(QMessageBox::Warning,
|
||||
tr("Warning"),
|
||||
tr("Fail to export diagram."),
|
||||
"",
|
||||
QMessageBox::Ok,
|
||||
QMessageBox::Ok,
|
||||
this);
|
||||
} else {
|
||||
QClipboard *clipboard = QApplication::clipboard();
|
||||
clipboard->clear();
|
||||
QImage img;
|
||||
img.loadFromData(out, p_format.toLocal8Bit().data());
|
||||
if (!img.isNull()) {
|
||||
VClipboardUtils::setImageAndLinkToClipboard(clipboard,
|
||||
img,
|
||||
filePath,
|
||||
QClipboard::Clipboard);
|
||||
emit m_object->statusMessage(tr("Diagram exported and copied"));
|
||||
} else {
|
||||
emit m_object->statusMessage(tr("Fail to read exported image: %1").arg(filePath));
|
||||
}
|
||||
}
|
||||
|
||||
m_exportTempFile->close();
|
||||
|
||||
}
|
||||
|
@ -6,6 +6,8 @@
|
||||
#include <QClipboard>
|
||||
#include <QImage>
|
||||
#include <QUrl>
|
||||
#include <QTemporaryFile>
|
||||
#include <QSharedPointer>
|
||||
|
||||
#include "vtextedit.h"
|
||||
#include "veditor.h"
|
||||
@ -284,12 +286,21 @@ private:
|
||||
const QTextBlock &p_block,
|
||||
int p_pos);
|
||||
|
||||
bool initExportAndCopyMenu(QAction *p_before,
|
||||
QMenu *p_menu,
|
||||
const QTextBlock &p_block,
|
||||
int p_pos);
|
||||
|
||||
void insertImageLink(const QString &p_text, const QString &p_url);
|
||||
|
||||
void setFontPointSizeByStyleSheet(int p_ptSize);
|
||||
|
||||
void setFontAndPaletteByStyleSheet(const QFont &p_font, const QPalette &p_palette);
|
||||
|
||||
void exportDiagramAndCopy(const QString &p_lang,
|
||||
const QString &p_text,
|
||||
const QString &p_format);
|
||||
|
||||
PegMarkdownHighlighter *m_pegHighlighter;
|
||||
|
||||
VCodeBlockHighlightHelper *m_cbHighlighter;
|
||||
@ -314,6 +325,9 @@ private:
|
||||
VEditTab *m_editTab;
|
||||
|
||||
int m_copyTimeStamp;
|
||||
|
||||
// Temp file used for ExportAndCopy.
|
||||
QSharedPointer<QTemporaryFile> m_exportTempFile;
|
||||
};
|
||||
|
||||
inline PegMarkdownHighlighter *VMdEditor::getMarkdownHighlighter() const
|
||||
|
@ -15,7 +15,19 @@ extern VConfigManager *g_config;
|
||||
VPlantUMLHelper::VPlantUMLHelper(QObject *p_parent)
|
||||
: QObject(p_parent)
|
||||
{
|
||||
prepareCommand(m_customCmd, m_program, m_args);
|
||||
m_customCmd = g_config->getPlantUMLCmd();
|
||||
if (m_customCmd.isEmpty()) {
|
||||
prepareCommand(m_program, m_args);
|
||||
}
|
||||
}
|
||||
|
||||
VPlantUMLHelper::VPlantUMLHelper(const QString &p_jar, QObject *p_parent)
|
||||
: QObject(p_parent)
|
||||
{
|
||||
m_customCmd = g_config->getPlantUMLCmd();
|
||||
if (m_customCmd.isEmpty()) {
|
||||
prepareCommand(m_program, m_args, p_jar);
|
||||
}
|
||||
}
|
||||
|
||||
void VPlantUMLHelper::processAsync(int p_id,
|
||||
@ -49,18 +61,13 @@ void VPlantUMLHelper::processAsync(int p_id,
|
||||
process->closeWriteChannel();
|
||||
}
|
||||
|
||||
void VPlantUMLHelper::prepareCommand(QString &p_customCmd,
|
||||
QString &p_program,
|
||||
QStringList &p_args) const
|
||||
void VPlantUMLHelper::prepareCommand(QString &p_program,
|
||||
QStringList &p_args,
|
||||
const QString &p_jar) const
|
||||
{
|
||||
p_customCmd = g_config->getPlantUMLCmd();
|
||||
if (!p_customCmd.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
p_program = "java";
|
||||
|
||||
p_args << "-jar" << g_config->getPlantUMLJar();
|
||||
p_args << "-jar" << (p_jar.isEmpty() ? g_config->getPlantUMLJar() : p_jar);
|
||||
p_args << "-charset" << "UTF-8";
|
||||
|
||||
int nbthread = QThread::idealThreadCount();
|
||||
@ -124,28 +131,23 @@ void VPlantUMLHelper::handleProcessFinished(int p_exitCode, QProcess::ExitStatus
|
||||
|
||||
bool VPlantUMLHelper::testPlantUMLJar(const QString &p_jar, QString &p_msg)
|
||||
{
|
||||
QString program("java");
|
||||
QStringList args;
|
||||
args << "-jar" << p_jar;
|
||||
args << "-charset" << "UTF-8";
|
||||
|
||||
const QString &dot = g_config->getGraphvizDot();
|
||||
if (!dot.isEmpty()) {
|
||||
args << "-graphvizdot";
|
||||
args << dot;
|
||||
}
|
||||
|
||||
args << "-pipe";
|
||||
VPlantUMLHelper inst(p_jar);
|
||||
QStringList args(inst.m_args);
|
||||
args << "-tsvg";
|
||||
|
||||
QString testGraph("VNote->Markdown : hello");
|
||||
|
||||
int exitCode = -1;
|
||||
QByteArray out, err;
|
||||
int ret = VProcessUtils::startProcess(program, args, testGraph.toUtf8(), exitCode, out, err);
|
||||
int ret = VProcessUtils::startProcess(inst.m_program,
|
||||
args,
|
||||
testGraph.toUtf8(),
|
||||
exitCode,
|
||||
out,
|
||||
err);
|
||||
|
||||
p_msg = QString("Command: %1 %2\nExitCode: %3\nOutput: %4\nError: %5")
|
||||
.arg(program)
|
||||
.arg(inst.m_program)
|
||||
.arg(args.join(' '))
|
||||
.arg(exitCode)
|
||||
.arg(QString::fromLocal8Bit(out))
|
||||
@ -153,3 +155,36 @@ bool VPlantUMLHelper::testPlantUMLJar(const QString &p_jar, QString &p_msg)
|
||||
|
||||
return ret == 0 && exitCode == 0;
|
||||
}
|
||||
|
||||
QByteArray VPlantUMLHelper::process(const QString &p_format, const QString &p_text)
|
||||
{
|
||||
VPlantUMLHelper inst;
|
||||
|
||||
int exitCode = -1;
|
||||
QByteArray out, err;
|
||||
int ret = -1;
|
||||
if (inst.m_customCmd.isEmpty()) {
|
||||
QStringList args(inst.m_args);
|
||||
args << ("-t" + p_format);
|
||||
ret = VProcessUtils::startProcess(inst.m_program,
|
||||
args,
|
||||
p_text.toUtf8(),
|
||||
exitCode,
|
||||
out,
|
||||
err);
|
||||
} else {
|
||||
QString cmd(inst.m_customCmd);
|
||||
cmd.replace("%0", p_format);
|
||||
ret = VProcessUtils::startProcess(cmd,
|
||||
p_text.toUtf8(),
|
||||
exitCode,
|
||||
out,
|
||||
err);
|
||||
}
|
||||
|
||||
if (ret != 0 || exitCode < 0) {
|
||||
qWarning() << "PlantUML fail" << ret << exitCode << QString::fromLocal8Bit(err);
|
||||
}
|
||||
|
||||
return out;
|
||||
}
|
||||
|
@ -19,17 +19,24 @@ public:
|
||||
const QString &p_format,
|
||||
const QString &p_text);
|
||||
|
||||
void prepareCommand(QString &p_customCmd, QString &p_cmd, QStringList &p_args) const;
|
||||
|
||||
static bool testPlantUMLJar(const QString &p_jar, QString &p_msg);
|
||||
|
||||
static QByteArray process(const QString &p_format, const QString &p_text);
|
||||
|
||||
signals:
|
||||
void resultReady(int p_id, TimeStamp p_timeStamp, 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:
|
||||
void handleProcessFinished(int p_exitCode, QProcess::ExitStatus p_exitStatus);
|
||||
|
||||
private:
|
||||
VPlantUMLHelper(const QString &p_jar, QObject *p_parent = nullptr);
|
||||
|
||||
void prepareCommand(QString &p_cmd, QStringList &p_args, const QString &p_jar= QString()) const;
|
||||
|
||||
QString m_program;
|
||||
|
||||
QStringList m_args;
|
||||
|
Loading…
x
Reference in New Issue
Block a user